Compare commits
16 Commits
e676cd19f6
...
xpack
| Author | SHA1 | Date | |
|---|---|---|---|
|
a836dd31e2
|
|||
|
94e5450a74
|
|||
|
7977fb976b
|
|||
|
86a034a4ac
|
|||
|
9208a5750d
|
|||
|
7301c40ba9
|
|||
|
792bf73e79
|
|||
|
c9d5cc35ff
|
|||
|
7040ce3381
|
|||
|
508405b00c
|
|||
|
6dbcc717f7
|
|||
|
19d953891b
|
|||
| 161c9425ae | |||
| 561b6d76b8 | |||
| b276213794 | |||
| 7b5801e630 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -17,3 +17,8 @@ doc/mockups/*
|
||||
data/pieces/*.bin
|
||||
data/config/*.bin
|
||||
data/config/keybinds/*.bin
|
||||
|
||||
# flatpak files
|
||||
flatpak/.flatpak-builder
|
||||
flatpak/builddir
|
||||
flatpak/repo
|
||||
|
||||
42
README.md
42
README.md
@@ -2,12 +2,18 @@
|
||||
|
||||
Modern stacker game with every polyominoes from size 1 to 15, made in C++ with [SFML 3](https://www.sfml-dev.org/)!
|
||||
|
||||
- [Download](#download)
|
||||
- [How to play](#how-to-play)
|
||||
- [Features](#features)
|
||||
- [Manual build](#manual-build)
|
||||
- [Benchmarks](#benchmarks)
|
||||
- [Credits](#credits)
|
||||
|
||||
## Download
|
||||
|
||||
// TODO when the game is finished //
|
||||
|
||||
This game has been tested on and built for Windows 11 and WSL2 Ubuntu.
|
||||
If your OS isn't compactible with either of theses two, you can try [manually building the project](#manual-build).
|
||||
You can download the latest release [here](https://git.ale-pri.com/TetrisNerd/jminos/releases)!
|
||||
This game has been tested on Windows 11 and Linux, and releases are provided for theses two systems.
|
||||
If your OS isn't compatible, you can try [manually building the project](#manual-build).
|
||||
|
||||
## How to play
|
||||
|
||||
@@ -44,22 +50,28 @@ You will find more infos about the Rotation System, the scoring system, or the d
|
||||
### Screenshots
|
||||
|
||||
Pentedecamino jumpscare
|
||||

|
||||
|
||||

|
||||
|
||||
Pieces select screen
|
||||

|
||||
|
||||

|
||||
|
||||
AutoRS demonstration
|
||||

|
||||
|
||||

|
||||
|
||||
0° spins demonstration
|
||||

|
||||
|
||||

|
||||
|
||||
## Manual build
|
||||
|
||||
This project uses xmake for compiling, xmake is cross-platform and works in most OS, xmake also automatically install supported librairies.
|
||||
To be able to build this project, you need to [have xmake installed](https://xmake.io) and have a compiler with C++20 compatibility.
|
||||
|
||||
If you want to contribute or are simply curious, you can check the [wiki](https://git.ale-pri.com/TetrisNerd/jminos/wiki)!
|
||||
|
||||
### Build the project
|
||||
|
||||
``cd jminos``
|
||||
@@ -69,6 +81,9 @@ To be able to build this project, you need to [have xmake installed](https://xma
|
||||
If you need to change the toolchain (for example using gcc):
|
||||
``xmake f --toolchain=gcc``
|
||||
|
||||
If you want to build for another platform (for example with mingw):
|
||||
``xmake f -p mingw``
|
||||
|
||||
### Run the project
|
||||
|
||||
``xmake run``
|
||||
@@ -86,7 +101,13 @@ The command line version is **not** updated.
|
||||
|
||||
### Package the project
|
||||
|
||||
// TODO when the game is finished //
|
||||
To package the executable manually properly, follow theses steps:
|
||||
|
||||
1. Clone the project into a new folder.
|
||||
2. If you already have all 15 pieces files, copy them over to the ``data/pieces`` folder, else you will be generating them at the next step.
|
||||
3. Go into release mode (``xmake f -m release``) and run the project once (``xmake`` and ``xmake run``). This is to generate the default config files, close the game immediately after it started.
|
||||
4. Make a new folder named ``jminos`` and copy the executable (should be located somewhere like ``build/linux/x86_64/release/graph``) as well as the ``data/pieces`` and ``data/config`` folders.
|
||||
5. Zip the newly created ``jminos`` folder into a file named ``jminos_{platform}``.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
@@ -112,7 +133,6 @@ The command line version is **not** updated.
|
||||
|
||||
_File storing includes type checking and sorting all polyominoes before writing them to the file._
|
||||
The files are compressed, they used to be about 5x as large.
|
||||
If you want to know more details about the generation and storage of polyominoes, [check the documentation](/doc/)!
|
||||
|
||||
Run it yourself by typing:
|
||||
``xmake f -m release``
|
||||
@@ -128,4 +148,4 @@ Inspired by other modern stacker games such as Techmino, jstris, tetr.io, etc.
|
||||
This game isn't affiliated with any of them.
|
||||
|
||||
Special thanks to my friend [Simon](https://git.ale-pri.com/Persson-dev) who did most of the outside stuff (github actions, files compression, asset manager, xmake).
|
||||
All the code in src/Common and src/Utils comes from him.
|
||||
All the code in src/Common/, src/Utils/ and xmake/ comes from him.
|
||||
|
||||
BIN
doc/diagrams/class_diagramm_graphicalUI.png
Normal file
BIN
doc/diagrams/class_diagramm_graphicalUI.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 82 KiB |
BIN
doc/diagrams/package_diagramm.png
Normal file
BIN
doc/diagrams/package_diagramm.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
@@ -2,11 +2,11 @@
|
||||
|
||||
## Pieces
|
||||
|
||||
If you don't know what a polyomino is, check [this other file](Pieces_representation.md#what-are-polyominoes).
|
||||
_Note: the current algorithm has been adapted to use file compression. There is currently no documentation on how the compression work, but you can check the code in the [src/Common](https://git.ale-pri.com/TetrisNerd/jminos/src/branch/main/src/Common) folder._
|
||||
|
||||
Generating polyominoes of size n is exponential in regard to n. Because of this, we will store the pieces beforehand and load them upon launching the game.
|
||||
|
||||
We want the pieces to be always sorted in the same order, always attributed the same block type, and always set at the same spawn position, no matter how they were generated. We also want them to be separated in 3 categories : convex, not convex but without a hole, and with a hole. Theses problematics are already resolved internally, but will be calculated before storage as to not need extra calculcations upon load (except for the block type which is trivially computed).
|
||||
We want the pieces to be always sorted in the same order, always attributed the same block type, and always set at the same spawn position, no matter how they were generated. We also want them to be separated in 3 categories : convex, not convex but without a hole, and with a hole. Theses problematics are already solved internally, but will be calculated before storage as to not need extra calculcations upon load (except for the block type which is trivially computed).
|
||||
|
||||
Pieces are stored in binary files. Each file simply contains every polyomino of one size, one after the other. Since each file contains all polyominoes of the same size, we know how much stuff to read and don't need delimiters. We know we've read all pieces simply when we reach the end of file character.
|
||||
|
||||
@@ -55,5 +55,4 @@ The settings file has the following format:
|
||||
- For every single piece, use 1 byte for (the size + encoding that it is a single piece),
|
||||
and 3 bytes to store the number of the piece (allows number up to 16M, size 15 has 6M pieces).
|
||||
|
||||
The current file format version is 11.
|
||||
If the file starts with a number lower than that, it will be regenerated upon launching the game.
|
||||
When starting the game, it will verify if the current settings file is in the latest format, if it is not it will be regenerated with default values.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Game logic
|
||||
|
||||
This section will detail how the player's action are interpreted into the game.
|
||||
We will only talk about pieces and not polyominoes. In this project, pieces are an abstraction of a polyomino. Though if you want to know more the polyominoes in this project, check [this other file](Pieces_representation.md).
|
||||
We will only talk about pieces and not polyominoes. In this project, pieces are an abstraction of a polyomino.
|
||||
|
||||
## Order of operations
|
||||
|
||||
|
||||
2
flatpak/FlatpakLaunch.sh
Normal file
2
flatpak/FlatpakLaunch.sh
Normal file
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
JMINOS_DATA="/app/share" JMINOS_CONFIG=$XDG_CONFIG_HOME /app/bin/graph
|
||||
9
flatpak/org.zulianc.jminos.desktop
Normal file
9
flatpak/org.zulianc.jminos.desktop
Normal file
@@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Version=1.0
|
||||
Name=Jminos
|
||||
Exec=/usr/bin/graph
|
||||
Icon=org.zulianc.jminos
|
||||
Terminal=false
|
||||
Categories=Game;
|
||||
Comment=Amazing stacker game by the J
|
||||
BIN
flatpak/org.zulianc.jminos.ico
Normal file
BIN
flatpak/org.zulianc.jminos.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
71
flatpak/org.zulianc.jminos.metainfo.xml
Normal file
71
flatpak/org.zulianc.jminos.metainfo.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<component type="desktop-application">
|
||||
<id>org.zulianc.jminos</id>
|
||||
<launchable type="desktop-id">org.zulianc.jminos.desktop</launchable>
|
||||
<name>jminos</name>
|
||||
<developer_name>Zulianc</developer_name>
|
||||
<summary>Amazing stacker game by the J </summary>
|
||||
<!-- <metadata_license>CC0-1.0</metadata_license>
|
||||
<project_license>GPL-3.0-only</project_license> -->
|
||||
<url type="homepage">https://git.ale-pri.com/TetrisNerd/jminos</url>
|
||||
<description>
|
||||
<p>
|
||||
Modern stacker game with every polyominoes from size 1 to 15, made in C++ with SFML 3!
|
||||
</p>
|
||||
<p>Features</p>
|
||||
<ul>
|
||||
<li>Every polyominoes up to pentedecaminoes!</li>
|
||||
<li>7bag with proportionnality for each polyomino size!</li>
|
||||
<li>AutoRS as the Rotation System!</li>
|
||||
<li>0° rotations!</li>
|
||||
<li>All spin!</li>
|
||||
<li>IRS, IHS, infinite hold, and other leniency mechanics!</li>
|
||||
<li>Customizable board size!</li>
|
||||
<li>Customizable keybinds!</li>
|
||||
<li>Very bland interface!! (i'm not a designer)</li>
|
||||
</ul>
|
||||
<p>Available gamemodes</p>
|
||||
<ul>
|
||||
<li>SPRINT : clear 40 lines as fast as possible!</li>
|
||||
<li>MARATHON : clear 200 lines with increasing gravity!</li>
|
||||
<li>ULTRA : scores as much as possible in only 2 minutes!</li>
|
||||
<li>MASTER : clear 200 lines at levels higher than maximum gravity!</li>
|
||||
<li>INVISIBLE : get 1000 grade while not being able to see the board!</li>
|
||||
<li>ZEN : practice indefinitely in this mode with no gravity!</li>
|
||||
</ul>
|
||||
</description>
|
||||
|
||||
<launchable type="desktop-id">
|
||||
org.zulianc.jminos.desktop
|
||||
</launchable>
|
||||
<categories>
|
||||
<category>Game</category>
|
||||
</categories>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<caption>Big piece</caption>
|
||||
<image>https://git.ale-pri.com/TetrisNerd/jminos/raw/branch/main/doc/readme/big_piece.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Pieces selection</caption>
|
||||
<image>https://git.ale-pri.com/TetrisNerd/jminos/media/branch/main/doc/readme/pieces_selection.png</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Rotations</caption>
|
||||
<image>https://git.ale-pri.com/TetrisNerd/jminos/media/branch/main/doc/readme/rotations.gif</image>
|
||||
</screenshot>
|
||||
<screenshot>
|
||||
<caption>Rotation_0</caption>
|
||||
<image>https://git.ale-pri.com/TetrisNerd/jminos/media/branch/main/doc/readme/rotation_0.gif</image>
|
||||
</screenshot>
|
||||
</screenshots>
|
||||
<releases>
|
||||
<release version="1.0" date="2025-07-02">
|
||||
<url>https://git.ale-pri.com/TetrisNerd/jminos/src/tag/v1.0/</url>
|
||||
<description>
|
||||
Inital release
|
||||
</description>
|
||||
</release>
|
||||
</releases>
|
||||
<content_rating type="oars-1.1" />
|
||||
</component>
|
||||
BIN
flatpak/org.zulianc.jminos.png
Normal file
BIN
flatpak/org.zulianc.jminos.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
31
flatpak/org.zulianc.jminos.yml
Normal file
31
flatpak/org.zulianc.jminos.yml
Normal file
@@ -0,0 +1,31 @@
|
||||
app-id: org.zulianc.jminos
|
||||
runtime: org.freedesktop.Platform
|
||||
runtime-version: "24.08"
|
||||
sdk: org.freedesktop.Sdk
|
||||
command: FlatpakLaunch.sh
|
||||
|
||||
finish-args:
|
||||
- --socket=x11
|
||||
- --device=dri
|
||||
|
||||
modules:
|
||||
- xmake.yml
|
||||
|
||||
- name: jminos
|
||||
buildsystem: simple
|
||||
build-options:
|
||||
build-args:
|
||||
- --share=network
|
||||
build-commands:
|
||||
- xmake f --policies=package.install_locally --external_build=y -m release -y
|
||||
- xmake
|
||||
- xmake install -o output
|
||||
- install -D output/bin/* /app/bin
|
||||
- cp -r output/data /app/share
|
||||
- install -D flatpak/FlatpakLaunch.sh /app/bin
|
||||
- install -D -t /app/share/applications flatpak/${FLATPAK_ID}.desktop
|
||||
- install -Dm644 flatpak/${FLATPAK_ID}.metainfo.xml /app/share/metainfo/${FLATPAK_ID}.metainfo.xml
|
||||
- install -D flatpak/${FLATPAK_ID}.png /app/share/icons/hicolor/512x512/apps/${FLATPAK_ID}.png
|
||||
sources:
|
||||
- type: dir
|
||||
path: ..
|
||||
12
flatpak/xmake.yml
Normal file
12
flatpak/xmake.yml
Normal file
@@ -0,0 +1,12 @@
|
||||
name: xmake
|
||||
buildsystem: simple
|
||||
no-autogen: true
|
||||
cleanup: ['*']
|
||||
build-commands:
|
||||
- ./configure --prefix=/app
|
||||
- make -j $(FLATPAK_BUILDER_N_JOBS)
|
||||
- prefix=/app ./scripts/get.sh __local__ __install_only__
|
||||
sources:
|
||||
- type: git
|
||||
url: https://github.com/xmake-io/xmake.git
|
||||
tag: v3.0.1
|
||||
@@ -49,14 +49,14 @@ void benchmarking(int min_size, int max_size) {
|
||||
ms_double = t2 - t1;
|
||||
std::cout << " | " << polyominoes.size();
|
||||
std::flush(std::cout);
|
||||
std::cout << " | " << (int) ms_double.count() / 1000 << "s " << std::fmod(ms_double.count(), 1000) << "ms ";
|
||||
std::cout << " | " << (int) ms_double.count() / 1000 << "s " << std::fmod(ms_double.count(), 1000) << "ms";
|
||||
std::flush(std::cout);
|
||||
|
||||
t1 = high_resolution_clock::now();
|
||||
ok = pf.savePieces(i, polyominoes);
|
||||
t2 = high_resolution_clock::now();
|
||||
ms_double = t2 - t1;
|
||||
std::cout << " | " << (int) ms_double.count() / 1000 << "s " << std::fmod(ms_double.count(), 1000) << "ms ";
|
||||
std::cout << " | " << (int) ms_double.count() / 1000 << "s " << std::fmod(ms_double.count(), 1000) << "ms";
|
||||
std::flush(std::cout);
|
||||
|
||||
if (!ok) {
|
||||
@@ -76,7 +76,7 @@ void benchmarking(int min_size, int max_size) {
|
||||
ok = pf.loadPieces(i, pieces, convexPieces, holelessPieces, otherPieces);
|
||||
t2 = high_resolution_clock::now();
|
||||
ms_double = t2 - t1;
|
||||
std::cout << " | " << (int) ms_double.count() / 1000 << "s " << std::fmod(ms_double.count(), 1000) << "ms ";
|
||||
std::cout << " | " << (int) ms_double.count() / 1000 << "s " << std::fmod(ms_double.count(), 1000) << "ms";
|
||||
std::flush(std::cout);
|
||||
|
||||
if (!ok) {
|
||||
|
||||
@@ -15,9 +15,7 @@ AppMenu::AppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings>
|
||||
settings(settings),
|
||||
renderWindow(renderWindow) {
|
||||
|
||||
const Asset& file = getResource(AssetName::data_fonts_pressstart_prstartk_ttf);
|
||||
|
||||
this->pressStartFont = sf::Font(file.data, file.size);
|
||||
this->pressStartFont = sf::Font(AssetManager::getResourcePath("data/fonts/pressstart/prstart.ttf"));
|
||||
}
|
||||
|
||||
void AppMenu::updateMetaBinds() {
|
||||
|
||||
@@ -23,9 +23,7 @@ SettingsKeybindsAppMenu::SettingsKeybindsAppMenu(std::shared_ptr<MenuStack> menu
|
||||
std::string textureName = ACTION_NAMES[action];
|
||||
textureName = std::regex_replace(textureName, std::regex(" "), "");
|
||||
|
||||
const Asset& textureData = getResource("data/images/keybinds/" + textureName + ".png");
|
||||
|
||||
this->iconTextures[action] = sf::Texture(textureData.data, textureData.size, false, {{0, 0}, {16, 16}});
|
||||
this->iconTextures[action] = sf::Texture(AssetManager::getResourcePath("data/images/keybinds/" + textureName + ".png"), false, {{0, 0}, {16, 16}});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
#include <SFML/Graphics.hpp>
|
||||
#include "../Utils/AssetManager.h"
|
||||
|
||||
|
||||
Keybinds::Keybinds(int layoutNumber) :
|
||||
@@ -20,7 +21,7 @@ Keybinds::Keybinds(int layoutNumber) :
|
||||
}
|
||||
|
||||
void Keybinds::loadKeybindsFromFile() {
|
||||
std::ifstream layoutFile("data/config/keybinds/layout" + std::to_string(this->layoutNumber) + ".bin", std::ios::binary);
|
||||
std::ifstream layoutFile(AssetManager::getConfigPath("data/config/keybinds/layout" + std::to_string(this->layoutNumber) + ".bin"), std::ios::binary);
|
||||
|
||||
for (Action action : ACTION_LIST_IN_ORDER) {
|
||||
this->keybinds.at(action).clear();
|
||||
@@ -47,7 +48,7 @@ void Keybinds::loadKeybindsFromFile() {
|
||||
void Keybinds::saveKeybindsToFile() const {
|
||||
if (!this->modifiable) return;
|
||||
|
||||
std::ofstream layoutFile("data/config/keybinds/layout" + std::to_string(this->layoutNumber) + ".bin", std::ios::trunc | std::ios::binary);
|
||||
std::ofstream layoutFile(AssetManager::getConfigPath("data/config/keybinds/layout" + std::to_string(this->layoutNumber) + ".bin"), std::ios::trunc | std::ios::binary);
|
||||
|
||||
char byte;
|
||||
for (Action action : ACTION_LIST_IN_ORDER) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "../Core/Menu.h"
|
||||
#include "Keybinds.h"
|
||||
#include "PiecesType.h"
|
||||
#include "../Utils/AssetManager.h"
|
||||
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
@@ -49,7 +50,7 @@ void Settings::loadPieces(int loadablePiecesSizeRequest) {
|
||||
}
|
||||
|
||||
void Settings::loadSettingsFromFile(bool loadPieces, std::optional<int> loadablePiecesSizeRequest) {
|
||||
std::ifstream settingsFile("data/config/settings.bin", std::ios::binary);
|
||||
std::ifstream settingsFile(AssetManager::getConfigPath("data/config/settings.bin"), std::ios::binary);
|
||||
char byte;
|
||||
|
||||
// file format version
|
||||
@@ -158,7 +159,7 @@ void Settings::saveSettingsToFile() const {
|
||||
|
||||
this->keybinds.at(CUSTOMIZABLE_KEYBINDS).saveKeybindsToFile();
|
||||
|
||||
std::ofstream settingsFile("data/config/settings.bin", std::ios::trunc | std::ios::binary);
|
||||
std::ofstream settingsFile(AssetManager::getConfigPath("data/config/settings.bin"), std::ios::trunc | std::ios::binary);
|
||||
char byte;
|
||||
|
||||
// file format version
|
||||
|
||||
@@ -4,11 +4,13 @@
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "../Utils/AssetManager.h"
|
||||
|
||||
[[nodiscard]] bool resetSettingsFile();
|
||||
[[nodiscard]] bool resetKeybindFile(int layout);
|
||||
|
||||
|
||||
int main() {
|
||||
int main(int arc, char** args) {
|
||||
std::srand(std::time(NULL));
|
||||
|
||||
bool everythingIsOK = true;
|
||||
@@ -18,7 +20,7 @@ int main() {
|
||||
PiecesFiles pf;
|
||||
bool warned = false;
|
||||
for (int i = 1; i <= MAXIMUM_PIECES_SIZE; i++) {
|
||||
if (!std::filesystem::exists("data/pieces/" + std::to_string(i) + "minos.bin")) {
|
||||
if (!std::filesystem::exists(AssetManager::getResourcePath("data/pieces/" + std::to_string(i) + "minos.bin"))) {
|
||||
#ifndef DEBUG
|
||||
if (!warned && i > DEBUG_PIECES_SIZE) {
|
||||
std::cout << "IMPORTANT: You are currently in release mode, if you do not wish to generate big pieces (can take several minutes), type 'xmake f -m debug'." << std::endl;
|
||||
@@ -36,7 +38,7 @@ int main() {
|
||||
|
||||
bool releasePiecesGenerated = true;
|
||||
for (int i = DEBUG_PIECES_SIZE + 1; i <= RELEASE_PIECES_SIZE; i++) {
|
||||
if (!std::filesystem::exists("data/pieces/" + std::to_string(i) + "minos.bin")) {
|
||||
if (!std::filesystem::exists(AssetManager::getResourcePath("data/pieces/" + std::to_string(i) + "minos.bin"))) {
|
||||
releasePiecesGenerated = false;
|
||||
}
|
||||
}
|
||||
@@ -47,29 +49,29 @@ int main() {
|
||||
|
||||
bool everythingGenerated = true;
|
||||
for (int i = 1; i <= MAXIMUM_PIECES_SIZE; i++) {
|
||||
std::string filePath = "data/pieces/" + std::to_string(i) + "minos.bin";
|
||||
auto filePath = AssetManager::getResourcePath("data/pieces/" + std::to_string(i) + "minos.bin");
|
||||
|
||||
if (!std::filesystem::exists(filePath)) {
|
||||
std::cout << "ERROR: Could not open file " + filePath << std::endl;
|
||||
std::cout << "ERROR: Could not open file " << filePath << std::endl;
|
||||
everythingIsOK &= false;
|
||||
}
|
||||
}
|
||||
|
||||
// CHECK CONFIG FILES
|
||||
|
||||
if (!std::filesystem::exists("data/config/settings.bin")) {
|
||||
if (!std::filesystem::exists(AssetManager::getConfigPath("data/config/settings.bin"))) {
|
||||
std::cout << "INFO: Settings file not found, generating..." << std::endl;
|
||||
everythingIsOK &= resetSettingsFile();
|
||||
|
||||
for (int i = 0; i < NUMBER_OF_KEYBINDS; i++) {
|
||||
if (!std::filesystem::exists("data/config/keybinds/layout" + std::to_string(i) + ".bin")) {
|
||||
if (!std::filesystem::exists(AssetManager::getConfigPath("data/config/keybinds/layout" + std::to_string(i) + ".bin"))) {
|
||||
std::cout << "INFO: Keybind file number " << (i + 1) << "/" << NUMBER_OF_KEYBINDS << " not found, generating..." << std::endl;
|
||||
everythingIsOK &= resetKeybindFile(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::ifstream settingsFile("data/config/settings.bin", std::ios::binary);
|
||||
std::ifstream settingsFile(AssetManager::getConfigPath("data/config/settings.bin"), std::ios::binary);
|
||||
char byte;
|
||||
|
||||
settingsFile.get(byte);
|
||||
@@ -99,14 +101,14 @@ int main() {
|
||||
|
||||
|
||||
bool resetSettingsFile() {
|
||||
if (!std::filesystem::exists("data/config")) {
|
||||
std::filesystem::create_directories("data/config");
|
||||
if (!std::filesystem::exists(AssetManager::getConfigPath("data/config"))) {
|
||||
std::filesystem::create_directories(AssetManager::getConfigPath("data/config"));
|
||||
}
|
||||
|
||||
std::string filePath ="data/config/settings.bin";
|
||||
auto filePath = AssetManager::getConfigPath("data/config/settings.bin");
|
||||
std::ofstream settingsFile(filePath, std::ios::trunc | std::ios::binary);
|
||||
if (!settingsFile.good()) {
|
||||
std::cerr << "ERROR: Could not open file " + filePath << std::endl;
|
||||
std::cerr << "ERROR: Could not open file " << filePath << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -180,14 +182,14 @@ bool resetKeybindFile(int layout) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!std::filesystem::exists("data/config/keybinds")) {
|
||||
std::filesystem::create_directories("data/config/keybinds");
|
||||
if (!std::filesystem::exists(AssetManager::getConfigPath("data/config/keybinds"))) {
|
||||
std::filesystem::create_directories(AssetManager::getConfigPath("data/config/keybinds"));
|
||||
}
|
||||
|
||||
std::string filePath = "data/config/keybinds/layout" + std::to_string(layout) + ".bin";
|
||||
auto filePath = AssetManager::getConfigPath("data/config/keybinds/layout" + std::to_string(layout) + ".bin");
|
||||
std::ofstream layoutFile(filePath, std::ios::trunc | std::ios::binary);
|
||||
if (!layoutFile.good()) {
|
||||
std::cerr << "ERROR: Could not open file " + filePath << std::endl;
|
||||
std::cerr << "ERROR: Could not open file " << filePath << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "../Common/Compression.h"
|
||||
#include "../Utils/AssetManager.h"
|
||||
|
||||
|
||||
PiecesFiles::PiecesFiles() {
|
||||
@@ -140,7 +141,7 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector<Piece>& pieces, std:
|
||||
}
|
||||
|
||||
bool PiecesFiles::getFilePath(int polyominoSize, std::string& filePath) const {
|
||||
std::string dataFolderPath = "data/pieces/";
|
||||
auto dataFolderPath = AssetManager::getResourcePath("data/pieces");
|
||||
|
||||
if (!std::filesystem::exists(dataFolderPath)) {
|
||||
std::filesystem::create_directories(dataFolderPath);
|
||||
@@ -150,6 +151,6 @@ bool PiecesFiles::getFilePath(int polyominoSize, std::string& filePath) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
filePath = dataFolderPath + std::to_string(polyominoSize) + "minos.bin";
|
||||
filePath = (dataFolderPath / (std::to_string(polyominoSize) + "minos.bin")).string();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../Pieces/Generator.h"
|
||||
#include "../Pieces/PiecesFiles.h"
|
||||
#include "TextApp.h"
|
||||
#include "../Utils/AssetManager.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
@@ -22,7 +23,7 @@ int main(int argc, char** argv) {
|
||||
PiecesFiles pf;
|
||||
bool warned = false;
|
||||
for (int i = 1; i <= MAXIMUM_PIECES_SIZE; i++) {
|
||||
if (!std::filesystem::exists("data/pieces/" + std::to_string(i) + "minos.bin")) {
|
||||
if (!std::filesystem::exists(AssetManager::getResourcePath("data/pieces/" + std::to_string(i) + "minos.bin"))) {
|
||||
if (!warned) {
|
||||
std::cout << "INFO: Pieces files for size " << i << " not found, generating..." << std::endl;
|
||||
warned = true;
|
||||
|
||||
@@ -1,97 +1,42 @@
|
||||
#include "./AssetManager.h"
|
||||
#include "AssetManager.h"
|
||||
|
||||
#include <map>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h> //GetModuleFileNameW
|
||||
#else
|
||||
#include <limits.h>
|
||||
#include <unistd.h> //readlink
|
||||
#endif
|
||||
|
||||
static const unsigned char data_fonts_pressstart_prstart_ttf[] = {
|
||||
#include <data/fonts/pressstart/prstart.ttf.h>
|
||||
};
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
static const unsigned char data_fonts_pressstart_prstartk_ttf[] = {
|
||||
#include <data/fonts/pressstart/prstartk.ttf.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Rotate180_png[] = {
|
||||
#include <data/images/keybinds/Rotate180.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Rotate0_png[] = {
|
||||
#include <data/images/keybinds/Rotate0.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_RotateCCW_png[] = {
|
||||
#include <data/images/keybinds/RotateCCW.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Retry_png[] = {
|
||||
#include <data/images/keybinds/Retry.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_RotateCW_png[] = {
|
||||
#include <data/images/keybinds/RotateCW.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Moveright_png[] = {
|
||||
#include <data/images/keybinds/Moveright.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Harddrop_png[] = {
|
||||
#include <data/images/keybinds/Harddrop.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Moveleft_png[] = {
|
||||
#include <data/images/keybinds/Moveleft.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Hold_png[] = {
|
||||
#include <data/images/keybinds/Hold.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Softdrop_png[] = {
|
||||
#include <data/images/keybinds/Softdrop.png.h>
|
||||
};
|
||||
|
||||
static const unsigned char data_images_keybinds_Pause_png[] = {
|
||||
#include <data/images/keybinds/Pause.png.h>
|
||||
};
|
||||
|
||||
static const Asset assets[] = {
|
||||
{data_fonts_pressstart_prstart_ttf, sizeof(data_fonts_pressstart_prstart_ttf)},
|
||||
{data_fonts_pressstart_prstartk_ttf, sizeof(data_fonts_pressstart_prstartk_ttf)},
|
||||
{data_images_keybinds_Rotate180_png, sizeof(data_images_keybinds_Rotate180_png)},
|
||||
{data_images_keybinds_Rotate0_png, sizeof(data_images_keybinds_Rotate0_png)},
|
||||
{data_images_keybinds_RotateCCW_png, sizeof(data_images_keybinds_RotateCCW_png)},
|
||||
{data_images_keybinds_Retry_png, sizeof(data_images_keybinds_Retry_png)},
|
||||
{data_images_keybinds_RotateCW_png, sizeof(data_images_keybinds_RotateCW_png)},
|
||||
{data_images_keybinds_Moveright_png, sizeof(data_images_keybinds_Moveright_png)},
|
||||
{data_images_keybinds_Harddrop_png, sizeof(data_images_keybinds_Harddrop_png)},
|
||||
{data_images_keybinds_Moveleft_png, sizeof(data_images_keybinds_Moveleft_png)},
|
||||
{data_images_keybinds_Hold_png, sizeof(data_images_keybinds_Hold_png)},
|
||||
{data_images_keybinds_Softdrop_png, sizeof(data_images_keybinds_Softdrop_png)},
|
||||
{data_images_keybinds_Pause_png, sizeof(data_images_keybinds_Pause_png)},
|
||||
|
||||
};
|
||||
|
||||
static const std::map<std::string, AssetName> assetMap = {
|
||||
{"data/fonts/pressstart/prstart.ttf", AssetName::data_fonts_pressstart_prstart_ttf},
|
||||
{"data/fonts/pressstart/prstartk.ttf", AssetName::data_fonts_pressstart_prstartk_ttf},
|
||||
{"data/images/keybinds/Rotate180.png", AssetName::data_images_keybinds_Rotate180_png},
|
||||
{"data/images/keybinds/Rotate0.png", AssetName::data_images_keybinds_Rotate0_png},
|
||||
{"data/images/keybinds/RotateCCW.png", AssetName::data_images_keybinds_RotateCCW_png},
|
||||
{"data/images/keybinds/Retry.png", AssetName::data_images_keybinds_Retry_png},
|
||||
{"data/images/keybinds/RotateCW.png", AssetName::data_images_keybinds_RotateCW_png},
|
||||
{"data/images/keybinds/Moveright.png", AssetName::data_images_keybinds_Moveright_png},
|
||||
{"data/images/keybinds/Harddrop.png", AssetName::data_images_keybinds_Harddrop_png},
|
||||
{"data/images/keybinds/Moveleft.png", AssetName::data_images_keybinds_Moveleft_png},
|
||||
{"data/images/keybinds/Hold.png", AssetName::data_images_keybinds_Hold_png},
|
||||
{"data/images/keybinds/Softdrop.png", AssetName::data_images_keybinds_Softdrop_png},
|
||||
{"data/images/keybinds/Pause.png", AssetName::data_images_keybinds_Pause_png},
|
||||
|
||||
};
|
||||
|
||||
const Asset& getResource(AssetName fileName) {
|
||||
return assets[static_cast<std::size_t>(fileName)];
|
||||
static fs::path getExeDirectory(){
|
||||
#ifdef _WIN32
|
||||
wchar_t path[MAX_PATH] = { 0 };
|
||||
GetModuleFileNameW(NULL, path, MAX_PATH);
|
||||
return path;
|
||||
#else
|
||||
char result[PATH_MAX];
|
||||
ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
|
||||
return std::string(result, (count > 0) ? count : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
const Asset& getResource(const std::string& fileName) {
|
||||
return getResource(assetMap.at(fileName));
|
||||
|
||||
|
||||
static fs::path getEnv(const std::string& var) {
|
||||
char* env = std::getenv(var.c_str());
|
||||
return env ? env :
|
||||
#ifdef JMINOS_IGNORE_WORKDIR
|
||||
getExeDirectory().parent_path().parent_path();
|
||||
#else
|
||||
"";
|
||||
#endif
|
||||
}
|
||||
|
||||
fs::path AssetManager::getResourcePath(const std::string& resource) {
|
||||
return fs::path{getEnv("JMINOS_DATA")} / resource;
|
||||
}
|
||||
|
||||
fs::path AssetManager::getConfigPath(const std::string& resource) {
|
||||
return fs::path{getEnv("JMINOS_CONFIG")} / resource;
|
||||
}
|
||||
@@ -2,29 +2,17 @@
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
|
||||
struct Asset {
|
||||
const unsigned char* data;
|
||||
std::size_t size;
|
||||
};
|
||||
class AssetManager {
|
||||
public:
|
||||
/**
|
||||
* @brief Used to load things (might be read-only)
|
||||
*/
|
||||
static std::filesystem::path getResourcePath(const std::string& resource);
|
||||
|
||||
enum class AssetName {
|
||||
data_fonts_pressstart_prstart_ttf,
|
||||
data_fonts_pressstart_prstartk_ttf,
|
||||
data_images_keybinds_Rotate180_png,
|
||||
data_images_keybinds_Rotate0_png,
|
||||
data_images_keybinds_RotateCCW_png,
|
||||
data_images_keybinds_Retry_png,
|
||||
data_images_keybinds_RotateCW_png,
|
||||
data_images_keybinds_Moveright_png,
|
||||
data_images_keybinds_Harddrop_png,
|
||||
data_images_keybinds_Moveleft_png,
|
||||
data_images_keybinds_Hold_png,
|
||||
data_images_keybinds_Softdrop_png,
|
||||
data_images_keybinds_Pause_png,
|
||||
|
||||
};
|
||||
|
||||
const Asset& getResource(AssetName fileName);
|
||||
|
||||
const Asset& getResource(const std::string& fileName);
|
||||
/**
|
||||
* @brief Used to save things
|
||||
*/
|
||||
static std::filesystem::path getConfigPath(const std::string& resource);
|
||||
};
|
||||
26
xmake.lua
26
xmake.lua
@@ -1,8 +1,20 @@
|
||||
add_rules("mode.debug", "mode.release")
|
||||
|
||||
includes("xmake/bin2c.lua")
|
||||
set_version("1.0.0")
|
||||
set_project("org.zulianc.jminos")
|
||||
|
||||
add_requires("sfml 3.0.0", "zlib")
|
||||
includes("@builtin/xpack")
|
||||
|
||||
option("external_build")
|
||||
set_default(false)
|
||||
option_end()
|
||||
|
||||
if has_config("external_build") then
|
||||
add_requires("sfml 3.0.0", "zlib", {system = false})
|
||||
add_defines("JMINOS_IGNORE_WORKDIR")
|
||||
else
|
||||
add_requires("sfml 3.0.0", "zlib")
|
||||
end
|
||||
|
||||
set_languages("c++20")
|
||||
|
||||
@@ -10,7 +22,7 @@ set_rundir(".")
|
||||
|
||||
target("core")
|
||||
set_kind("$(kind)")
|
||||
add_files("src/Pieces/*.cpp", "src/Core/*.cpp", "src/Common/*.cpp")
|
||||
add_files("src/Pieces/*.cpp", "src/Core/*.cpp", "src/Common/*.cpp", "src/Utils/*.cpp")
|
||||
add_packages("zlib")
|
||||
|
||||
target("text")
|
||||
@@ -27,16 +39,11 @@ target("bmark")
|
||||
|
||||
target("graph")
|
||||
set_default(true)
|
||||
add_rules("bin2c", {
|
||||
extensions = {".png", ".ttf"},
|
||||
outputSource = {"src/Utils/AssetManager.cpp"},
|
||||
outputHeader = {"src/Utils/AssetManager.h"}
|
||||
})
|
||||
set_kind("binary")
|
||||
add_files("./src/GraphicalUI/**.cpp")
|
||||
add_files("data/fonts/**.ttf", "data/images/**.png")
|
||||
add_deps("core")
|
||||
add_packages("sfml")
|
||||
add_installfiles("(data/**)")
|
||||
|
||||
if is_mode("debug") then
|
||||
add_defines("DEBUG")
|
||||
@@ -46,6 +53,7 @@ if is_plat("mingw") then
|
||||
add_ldflags("-static-libstdc++", "-static")
|
||||
end
|
||||
|
||||
includes("xmake/xpack.lua")
|
||||
|
||||
--
|
||||
-- If you want to known more usage about xmake, please see https://xmake.io
|
||||
|
||||
36
xmake/xpack.lua
Normal file
36
xmake/xpack.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
if is_os("linux") then
|
||||
|
||||
xpack("jminos")
|
||||
set_formats("flatpak")
|
||||
set_extension("flatpak")
|
||||
set_title("jminos")
|
||||
set_author("zulianc")
|
||||
set_description("A test installer.")
|
||||
set_homepage("https://git.ale-pri.com/TetrisNerd/jminos")
|
||||
set_company("org.zulianc")
|
||||
on_package(function (package)
|
||||
os.cd("flatpak")
|
||||
os.exec("flatpak install org.flatpak.Builder --user -y")
|
||||
os.exec("flatpak run org.flatpak.Builder --force-clean --user --install-deps-from=flathub --repo=repo --install builddir org.zulianc.jminos.yml")
|
||||
os.exec("flatpak build-bundle repo jminos.flatpak org.zulianc.jminos --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo")
|
||||
os.mv("jminos.flatpak", package:outputdir())
|
||||
end)
|
||||
on_load(function (package)
|
||||
package:set("basename", package:name() .. "-v" .. package:version() .. "-" .. package:arch())
|
||||
end)
|
||||
|
||||
else
|
||||
|
||||
xpack("jminos")
|
||||
set_formats("zip", "nsis")
|
||||
add_targets("graph")
|
||||
add_installfiles("(data/**.png)")
|
||||
set_iconfile("../flatpak/org.zulianc.jminos.ico")
|
||||
on_load(function (package)
|
||||
package:set("basename", package:name() .. "-v" .. package:version() .. "-" .. package:arch())
|
||||
end)
|
||||
after_installcmd(function (package, batchcmds)
|
||||
batchcmds:rm(package:installdir("**/.gitkeep"))
|
||||
end)
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user