Compare commits
1 Commits
assets
...
optimizing
| Author | SHA1 | Date | |
|---|---|---|---|
| 6da3cb66fa |
36
.github/workflows/ubuntu.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: Linux arm64
|
|
||||||
run-name: Build And Test
|
|
||||||
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
|
|
||||||
env:
|
|
||||||
XMAKE_ROOT: y
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
Build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check out repository code
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Prepare XMake
|
|
||||||
uses: xmake-io/github-action-setup-xmake@v1
|
|
||||||
with:
|
|
||||||
xmake-version: latest
|
|
||||||
actions-cache-folder: '.xmake-cache'
|
|
||||||
actions-cache-key: 'ubuntu'
|
|
||||||
|
|
||||||
- name: Install SFML
|
|
||||||
run: |
|
|
||||||
apt update
|
|
||||||
apt install -y libsfml-dev
|
|
||||||
|
|
||||||
- name: XMake config
|
|
||||||
run: xmake f -p linux -y
|
|
||||||
|
|
||||||
- name: Build
|
|
||||||
run: xmake
|
|
||||||
|
|
||||||
- name: Test
|
|
||||||
run: xmake test
|
|
||||||
2
.gitignore
vendored
@@ -10,7 +10,7 @@ build/
|
|||||||
|
|
||||||
# personnal documentation
|
# personnal documentation
|
||||||
doc/*.txt
|
doc/*.txt
|
||||||
doc/diagrams/*.violet.html
|
doc/*.violet.html
|
||||||
doc/mockups/*
|
doc/mockups/*
|
||||||
|
|
||||||
# data files
|
# data files
|
||||||
|
|||||||
56
README.md
@@ -1,30 +1,24 @@
|
|||||||
# jminos
|
# jminos
|
||||||
|
|
||||||
Modern stacker game with every polyominoes from size 1 to 15, made in C++ with [SFML 3](https://www.sfml-dev.org/)!
|
Modern stacker game with every polyominos from size 1 to 15, made in C++ with [SFML 3](https://www.sfml-dev.org/)!
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
// TODO when the game is finished //
|
// TODO when the game is finished //
|
||||||
|
|
||||||
This game has been tested on and built for Windows 11 and WSL2 Ubuntu.
|
This game has been tested on and built on Windows 11 and WSL2 Ubuntu only.
|
||||||
If your OS isn't compactible with either of theses two, you can try [manually building the project](#manual-build).
|
If your OS isn't compactible with either of theses two, you can try [manually building the project](#manual-build).
|
||||||
|
|
||||||
## How to play
|
## How to play
|
||||||
|
|
||||||
Choose which pieces you want to play with and stack them up until you either win or top out!
|
|
||||||
Make full lines to make them dissapear.
|
|
||||||
Use the different spins to kick the pieces in spot you couldn't imagine were attaignable!
|
|
||||||
Each gamemode has its own objective, but you can play as you wish.
|
|
||||||
|
|
||||||
You can see and change in-game keybinds in the **SETTINGS** section of the main menu!
|
You can see and change in-game keybinds in the **SETTINGS** section of the main menu!
|
||||||
All of in-menu navigation is done with the **arrow keys**, the **Enter key** and the **Escape key**. Theses are unchangeable keybinds.
|
All of in-menu navigation is done with the **arrow keys**, the **Enter key** and the **Escape key**. Theses are unchangeable keybinds.
|
||||||
You will find more infos about the Rotation System, the scoring system, or the different pieces type in the **INFO** section of the main menu.
|
You will find more infos about the Rotation System, the scoring system, or the different pieces type in the **INFO** section of the main menu.
|
||||||
|
If you want to know more details about the generation of polyominoes, [check the documentation](/doc/)!
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Every polyominoes up to pentedecaminoes!
|
- Every polyominoes from size 1 to 15, selectable as you wish, with customizable propotionnality for each size!
|
||||||
- 7bag with proportionnality for each polyomino size!
|
|
||||||
- Customizable board size!
|
|
||||||
- Customizable keybinds!
|
- Customizable keybinds!
|
||||||
- 0° rotations!
|
- 0° rotations!
|
||||||
- AutoRS as the Rotation System!
|
- AutoRS as the Rotation System!
|
||||||
@@ -41,17 +35,7 @@ You will find more infos about the Rotation System, the scoring system, or the d
|
|||||||
|
|
||||||
### Screenshots
|
### Screenshots
|
||||||
|
|
||||||
Pentedecamino jumpscare
|
// TODO when the game is finished //
|
||||||

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

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

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

|
|
||||||
|
|
||||||
## Manual build
|
## Manual build
|
||||||
|
|
||||||
@@ -78,42 +62,12 @@ To switch between debug and release mode:
|
|||||||
``xmake f -m release``
|
``xmake f -m release``
|
||||||
|
|
||||||
If for some reasons you wanna run the command line version (not updated):
|
If for some reasons you wanna run the command line version (not updated):
|
||||||
``xmake build text``
|
|
||||||
``xmake run text``
|
``xmake run text``
|
||||||
|
|
||||||
### Package the project
|
### Package the project
|
||||||
|
|
||||||
// TODO when the game is finished //
|
// TODO when the game is finished //
|
||||||
|
|
||||||
## Benchmarks
|
|
||||||
|
|
||||||
### One-sided n-polyominoes
|
|
||||||
|
|
||||||
| n | Number | Generation | File storing | File retrieving | File size |
|
|
||||||
| - | - | - | - | - | - |
|
|
||||||
| 1 | 1 | 0s 0.005622ms | 0s 0.750955ms | 0s 0.014016ms | 2 bytes |
|
|
||||||
| 2 | 1 | 0s 0.005758ms | 0s 0.181323ms | 0s 0.012256ms | 3 bytes |
|
|
||||||
| 3 | 2 | 0s 0.017525ms | 0s 0.054497ms | 0s 0.006431ms | 8 bytes |
|
|
||||||
| 4 | 7 | 0s 0.050554ms | 0s 0.067617ms | 0s 0.010984ms | 35 bytes |
|
|
||||||
| 5 | 18 | 0s 0.191971ms | 0s 0.109905ms | 0s 0.021234ms | 108 bytes |
|
|
||||||
| 6 | 60 | 0s 0.651757ms | 0s 0.327465ms | 0s 0.04558ms | 420 bytes |
|
|
||||||
| 7 | 196 | 0s 3.38847ms | 0s 1.94434ms | 0s 0.258777ms | 1568 bytes |
|
|
||||||
| 8 | 704 | 0s 22.7411ms | 0s 10.0103ms | 0s 1.34813ms | 6336 bytes |
|
|
||||||
| 9 | 2500 | 0s 66.2949ms | 0s 20.6137ms | 0s 2.56374ms | 25000 bytes |
|
|
||||||
| 10 | 9189 | 0s 194.764ms | 0s 84.5884ms | 0s 9.64467ms | 101079 bytes |
|
|
||||||
| 11 | 33896 | 0s 759.182ms | 0s 378.494ms | 0s 44.1424ms | 406752 bytes |
|
|
||||||
| 12 | 126759 | 2s 709.277ms | 1s 530.34ms | 0s 155ms | 1647867 bytes |
|
|
||||||
| 13 | 476270 | 10s 668.308ms | 7s 395.512ms | 0s 765.601ms | 6667780 bytes |
|
|
||||||
| 14 | 1802312 | 45s 606.597ms | 32s 28.7977ms | 2s 919.653ms | 27034680 bytes |
|
|
||||||
| 15 | ~6M | ~5mn | ~5mn | ~10s | ~100 MB |
|
|
||||||
|
|
||||||
_File storing includes normalizing and sorting all polyominoes before writing them to the file._
|
|
||||||
If you want to know more details about the generation and storage of polyominoes, [check the documentation](/doc/)!
|
|
||||||
|
|
||||||
Run it yourself by typing:
|
|
||||||
``xmake build benchmark``
|
|
||||||
``xmake run benchmark``
|
|
||||||
|
|
||||||
## Credits
|
## Credits
|
||||||
|
|
||||||
Library used: [SFML 3](https://www.sfml-dev.org/).
|
Library used: [SFML 3](https://www.sfml-dev.org/).
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 164 KiB After Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 614 KiB |
|
Before Width: | Height: | Size: 779 KiB |
@@ -1,12 +0,0 @@
|
|||||||
#include "AppMenu.h"
|
|
||||||
|
|
||||||
#include "../../Utils/AssetManager.h"
|
|
||||||
|
|
||||||
AppMenu::AppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow) : menuStack(menuStack),
|
|
||||||
settings(settings),
|
|
||||||
renderWindow(renderWindow)
|
|
||||||
{
|
|
||||||
const Asset& file = getResource(AssetName::data_fonts_pressstart_prstartk_ttf);
|
|
||||||
|
|
||||||
this->pressStartFont = sf::Font(file.data, file.size);
|
|
||||||
}
|
|
||||||
@@ -21,10 +21,16 @@ class AppMenu {
|
|||||||
bool enterReleased = false;
|
bool enterReleased = false;
|
||||||
bool escPressed = false;
|
bool escPressed = false;
|
||||||
bool escReleased = false;
|
bool escReleased = false;
|
||||||
sf::Font pressStartFont;
|
sf::Font pressStartFont = sf::Font("data/fonts/pressstart/prstartk.ttf");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow);
|
AppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow) :
|
||||||
|
menuStack(menuStack),
|
||||||
|
settings(settings),
|
||||||
|
renderWindow(renderWindow)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
virtual void computeFrame() = 0;
|
virtual void computeFrame() = 0;
|
||||||
|
|
||||||
@@ -51,6 +57,33 @@ class AppMenu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sf::Text createText(int fontSize = 2) const {
|
||||||
|
sf::Text newText(this->pressStartFont, "", this->settings->getWindowSizeMultiplier() * fontSize);
|
||||||
|
newText.setFillColor(sf::Color::Black);
|
||||||
|
newText.setOutlineColor(sf::Color::White);
|
||||||
|
newText.setOutlineThickness(0);
|
||||||
|
|
||||||
|
return newText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextPosition(sf::Text& text, float xPos, float yPos) const {
|
||||||
|
float sizeMultiplier = this->settings->getWindowSizeMultiplier();
|
||||||
|
|
||||||
|
text.setOrigin(sf::Vector2f({0, text.getLocalBounds().size.y / 2}));
|
||||||
|
text.setPosition(sf::Vector2f({sizeMultiplier * xPos, sizeMultiplier * yPos}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTitlePosition(sf::Text& text, float yPos) const {
|
||||||
|
float sizeMultiplier = this->settings->getWindowSizeMultiplier();
|
||||||
|
|
||||||
|
text.setOrigin({text.getLocalBounds().getCenter().x, text.getLocalBounds().size.y / 2});
|
||||||
|
text.setPosition(sf::Vector2f({sizeMultiplier * 40.f, sizeMultiplier * yPos}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTextOutline(sf::Text& text, bool hasOutline) const {
|
||||||
|
text.setOutlineThickness(hasOutline * (this->settings->getWindowSizeMultiplier() / 2));
|
||||||
|
}
|
||||||
|
|
||||||
void placeText(sf::Text& text, const std::optional<PlayerCursor>& playerCursor, const sf::String& string, float xPos, float yPos, const std::optional<sf::Vector2u>& cursorPos) const {
|
void placeText(sf::Text& text, const std::optional<PlayerCursor>& playerCursor, const sf::String& string, float xPos, float yPos, const std::optional<sf::Vector2u>& cursorPos) const {
|
||||||
float sizeMultiplier = this->settings->getWindowSizeMultiplier();
|
float sizeMultiplier = this->settings->getWindowSizeMultiplier();
|
||||||
|
|
||||||
|
|||||||
@@ -67,14 +67,47 @@ InfoAppMenu::InfoAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<S
|
|||||||
"A spin is detected when the piece is\n"
|
"A spin is detected when the piece is\n"
|
||||||
"locked in place, a mini-spin simply\n"
|
"locked in place, a mini-spin simply\n"
|
||||||
"when the last move was a kick."
|
"when the last move was a kick."
|
||||||
) {
|
),
|
||||||
|
sectionNameText(this->createText()),
|
||||||
|
sectionContentText(this->createText()),
|
||||||
|
renderTexture(this->renderWindow->getSize()),
|
||||||
|
sprite(this->renderTexture.getTexture()) {
|
||||||
|
|
||||||
|
this->setTextOutline(this->sectionNameText, true);
|
||||||
|
|
||||||
|
this->sectionContentText.setLineSpacing((float) this->settings->getWindowSizeMultiplier() / 8);
|
||||||
|
|
||||||
|
this->sectionNameText.setString(this->sectionsName[this->playerCursor.getPosition().x]);
|
||||||
|
this->setTitlePosition(this->sectionNameText, 10.f);
|
||||||
|
|
||||||
|
this->sectionContentText.setString(this->sectionsContent[this->playerCursor.getPosition().x]);
|
||||||
|
this->setTextPosition(this->sectionContentText, 5.f, 30.f);
|
||||||
|
|
||||||
|
this->renderTexture.clear(sf::Color(200, 200, 200));
|
||||||
|
this->renderTexture.draw(this->sectionNameText);
|
||||||
|
this->renderTexture.draw(this->sectionContentText);
|
||||||
|
this->renderTexture.display();
|
||||||
|
this->sprite.setTexture(this->renderTexture.getTexture());
|
||||||
}
|
}
|
||||||
|
|
||||||
void InfoAppMenu::computeFrame() {
|
void InfoAppMenu::computeFrame() {
|
||||||
this->updateMetaBinds();
|
this->updateMetaBinds();
|
||||||
this->playerCursor.updatePosition();
|
this->playerCursor.updatePosition();
|
||||||
|
|
||||||
|
if (this->playerCursor.movedLeft() || this->playerCursor.movedRight()) {
|
||||||
|
this->sectionNameText.setString(this->sectionsName[this->playerCursor.getPosition().x]);
|
||||||
|
this->setTitlePosition(this->sectionNameText, 10.f);
|
||||||
|
|
||||||
|
this->sectionContentText.setString(this->sectionsContent[this->playerCursor.getPosition().x]);
|
||||||
|
this->setTextPosition(this->sectionContentText, 5.f, 30.f);
|
||||||
|
|
||||||
|
this->renderTexture.clear(sf::Color(200, 200, 200));
|
||||||
|
this->renderTexture.draw(this->sectionNameText);
|
||||||
|
this->renderTexture.draw(this->sectionContentText);
|
||||||
|
this->renderTexture.display();
|
||||||
|
this->sprite.setTexture(this->renderTexture.getTexture());
|
||||||
|
}
|
||||||
|
|
||||||
if (this->escReleased) {
|
if (this->escReleased) {
|
||||||
this->menuStack->pop();
|
this->menuStack->pop();
|
||||||
}
|
}
|
||||||
@@ -83,15 +116,7 @@ void InfoAppMenu::computeFrame() {
|
|||||||
void InfoAppMenu::drawFrame() const {
|
void InfoAppMenu::drawFrame() const {
|
||||||
this->renderWindow->clear(sf::Color(200, 200, 200));
|
this->renderWindow->clear(sf::Color(200, 200, 200));
|
||||||
|
|
||||||
sf::Text text(this->pressStartFont, "", this->settings->getWindowSizeMultiplier() * 2);
|
this->renderWindow->draw(sprite);
|
||||||
text.setFillColor(sf::Color(0, 0, 0));
|
|
||||||
text.setOutlineColor(sf::Color(255, 255, 255));
|
|
||||||
|
|
||||||
this->placeTitle(text, this->playerCursor, this->sectionsName[this->playerCursor.getPosition().x], 10.f, this->playerCursor.getPosition());
|
|
||||||
|
|
||||||
text.setLineSpacing((float) this->settings->getWindowSizeMultiplier() / 8);
|
|
||||||
text.setOutlineThickness(0);
|
|
||||||
this->placeText(text, {}, this->sectionsContent[this->playerCursor.getPosition().x], 5.f, 30.f, {});
|
|
||||||
|
|
||||||
this->renderWindow->display();
|
this->renderWindow->display();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,10 @@ class InfoAppMenu : public AppMenu {
|
|||||||
PlayerCursor playerCursor;
|
PlayerCursor playerCursor;
|
||||||
sf::String sectionsName[INFO_SECTIONS_COUNT];
|
sf::String sectionsName[INFO_SECTIONS_COUNT];
|
||||||
sf::String sectionsContent[INFO_SECTIONS_COUNT];
|
sf::String sectionsContent[INFO_SECTIONS_COUNT];
|
||||||
|
sf::Text sectionNameText;
|
||||||
|
sf::Text sectionContentText;
|
||||||
|
sf::RenderTexture renderTexture;
|
||||||
|
sf::Sprite sprite;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
InfoAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow);
|
InfoAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include "AppMenu.h"
|
#include "AppMenu.h"
|
||||||
#include "../PlayerCursor.h"
|
#include "../PlayerCursor.h"
|
||||||
#include "../../Utils/AssetManager.h"
|
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -23,9 +22,8 @@ SettingsKeybindsAppMenu::SettingsKeybindsAppMenu(std::shared_ptr<MenuStack> menu
|
|||||||
std::string textureName = ACTION_NAMES[action];
|
std::string textureName = ACTION_NAMES[action];
|
||||||
textureName = std::regex_replace(textureName, std::regex(" "), "");
|
textureName = std::regex_replace(textureName, std::regex(" "), "");
|
||||||
|
|
||||||
const Asset& textureData = getResource("data/images/keybinds/" + textureName + ".png");
|
std::filesystem::path texturePath("data/images/keybinds/" + textureName + ".png");
|
||||||
|
this->iconTextures[action] = sf::Texture(texturePath, false, {{0, 0}, {16, 16}});
|
||||||
this->iconTextures[action] = sf::Texture(textureData.data, textureData.size, false, {{0, 0}, {16, 16}});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,13 @@ void PlayerCursor::updatePosition() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PlayerCursor::moved() const {
|
||||||
|
return (this->movedLeft()
|
||||||
|
|| this->movedRight()
|
||||||
|
|| this->movedUp()
|
||||||
|
|| this->movedDown());
|
||||||
|
}
|
||||||
|
|
||||||
bool PlayerCursor::movedLeft() const {
|
bool PlayerCursor::movedLeft() const {
|
||||||
return this->shouldMove(this->leftDAS);
|
return this->shouldMove(this->leftDAS);
|
||||||
}
|
}
|
||||||
@@ -115,7 +122,7 @@ const sf::Vector2u& PlayerCursor::getPosition() const {
|
|||||||
bool PlayerCursor::shouldMove(int DAS) const {
|
bool PlayerCursor::shouldMove(int DAS) const {
|
||||||
return (DAS == 1
|
return (DAS == 1
|
||||||
|| (DAS > MENU_DAS && (DAS % 5) == 0)
|
|| (DAS > MENU_DAS && (DAS % 5) == 0)
|
||||||
|| (DAS > (FRAMES_PER_SECOND * 2)));
|
|| (DAS > (MENU_DAS * 4)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerCursor::moveLeft() {
|
void PlayerCursor::moveLeft() {
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ class PlayerCursor {
|
|||||||
|
|
||||||
void updatePosition();
|
void updatePosition();
|
||||||
|
|
||||||
|
bool moved() const;
|
||||||
|
|
||||||
bool movedLeft() const;
|
bool movedLeft() const;
|
||||||
|
|
||||||
bool movedRight() const;
|
bool movedRight() const;
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ int main() {
|
|||||||
|
|
||||||
|
|
||||||
void resetSettingsFile() {
|
void resetSettingsFile() {
|
||||||
std::filesystem::create_directories("data/config");
|
|
||||||
std::ofstream settingsFile("data/config/settings.bin", std::ios::trunc | std::ios::binary);
|
std::ofstream settingsFile("data/config/settings.bin", std::ios::trunc | std::ios::binary);
|
||||||
char byte;
|
char byte;
|
||||||
|
|
||||||
@@ -138,7 +137,6 @@ void resetSettingsFile() {
|
|||||||
void resetKeybindFile(int layout) {
|
void resetKeybindFile(int layout) {
|
||||||
if (layout < 0 || layout > 4) return;
|
if (layout < 0 || layout > 4) return;
|
||||||
|
|
||||||
std::filesystem::create_directories("data/config/keybinds/layout");
|
|
||||||
std::ofstream layoutFile("data/config/keybinds/layout" + std::to_string(layout) + ".bin", std::ios::trunc | std::ios::binary);
|
std::ofstream layoutFile("data/config/keybinds/layout" + std::to_string(layout) + ".bin", std::ios::trunc | std::ios::binary);
|
||||||
std::map<Action, sfKey> keybinds;
|
std::map<Action, sfKey> keybinds;
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
|
|
||||||
PiecesFiles::PiecesFiles() {
|
PiecesFiles::PiecesFiles() {
|
||||||
}
|
}
|
||||||
@@ -27,35 +25,22 @@ bool PiecesFiles::savePieces(int polyominoSize) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Generator generator;
|
Generator generator;
|
||||||
std::vector<Polyomino> polyominoes = generator.generatePolyominoes(polyominoSize);
|
std::vector<Polyomino> nMinos = generator.generatePolyominoes(polyominoSize);
|
||||||
|
|
||||||
return this->savePieces(polyominoSize, polyominoes);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PiecesFiles::savePieces(int polyominoSize, std::vector<Polyomino>& polyominoes) const {
|
|
||||||
std::string filePath;
|
|
||||||
if (!this->getFilePath(polyominoSize, filePath)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::ofstream piecesFile(filePath, std::ios::trunc | std::ios::binary);
|
|
||||||
if (!piecesFile.good()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sorting the polyominoes is done after setting spawn position to ensure the order is always the same
|
// sorting the polyominoes is done after setting spawn position to ensure the order is always the same
|
||||||
for (Polyomino& nMino : polyominoes) {
|
for (Polyomino& nMino : nMinos) {
|
||||||
nMino.goToSpawnPosition();
|
nMino.goToSpawnPosition();
|
||||||
}
|
}
|
||||||
std::sort(polyominoes.begin(), polyominoes.end());
|
std::sort(nMinos.begin(), nMinos.end());
|
||||||
|
|
||||||
for (const Polyomino& polyomino : polyominoes) {
|
for (const Polyomino& nMino : nMinos) {
|
||||||
// write the characteristics of the piece
|
// write the characteristics of the piece
|
||||||
char infoByte = (polyomino.isConvex() << 7) + (polyomino.hasHole() << 6) + polyomino.getLength();
|
char infoByte = (nMino.isConvex() << 7) + (nMino.hasHole() << 6) + nMino.getLength();
|
||||||
piecesFile.write(&infoByte, 1);
|
piecesFile.write(&infoByte, 1);
|
||||||
|
|
||||||
// write the positions of the piece
|
// write the positions of the piece
|
||||||
char positionByte;
|
char positionByte;
|
||||||
for (const Position position : polyomino.getPositions()) {
|
for (Position position : nMino.getPositions()) {
|
||||||
positionByte = (position.x << 4) + position.y;
|
positionByte = (position.x << 4) + position.y;
|
||||||
piecesFile.write(&positionByte, 1);
|
piecesFile.write(&positionByte, 1);
|
||||||
}
|
}
|
||||||
@@ -134,12 +119,7 @@ bool PiecesFiles::loadPieces(int polyominoSize, std::vector<Piece>& pieces, std:
|
|||||||
|
|
||||||
bool PiecesFiles::getFilePath(int polyominoSize, std::string& filePath) const {
|
bool PiecesFiles::getFilePath(int polyominoSize, std::string& filePath) const {
|
||||||
std::string dataFolderPath = "data/pieces/";
|
std::string dataFolderPath = "data/pieces/";
|
||||||
|
if (!std::filesystem::is_directory(dataFolderPath)) {
|
||||||
if (!fs::exists(dataFolderPath)) {
|
|
||||||
fs::create_directories(dataFolderPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs::is_directory(dataFolderPath)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,18 +22,13 @@ class PiecesFiles {
|
|||||||
*/
|
*/
|
||||||
bool savePieces(int polyominoSize) const;
|
bool savePieces(int polyominoSize) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a file containing all the pieces of the specified size, assuming they have been correctly generated
|
|
||||||
* @return If the file could be created
|
|
||||||
*/
|
|
||||||
bool savePieces(int polyominoSize, std::vector<Polyomino>& polyominoes) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace the content of the vectors by the pieces of the specified size, if the file wasn't found the vectors stays untouched
|
* Replace the content of the vectors by the pieces of the specified size, if the file wasn't found the vectors stays untouched
|
||||||
* @return If the file was found
|
* @return If the file was found
|
||||||
*/
|
*/
|
||||||
bool loadPieces(int polyominoSize, std::vector<Piece>& pieces, std::vector<int>& convexPieces, std::vector<int>& holelessPieces, std::vector<int>& otherPieces) const;
|
bool loadPieces(int polyominoSize, std::vector<Piece>& pieces, std::vector<int>& convexPieces, std::vector<int>& holelessPieces, std::vector<int>& otherPieces) const;
|
||||||
|
|
||||||
|
private:
|
||||||
/**
|
/**
|
||||||
* Puts the path to the piece file of the specified size in order, if the data folder wasn't found the string stays untouched
|
* Puts the path to the piece file of the specified size in order, if the data folder wasn't found the string stays untouched
|
||||||
* @return If the data folder was found
|
* @return If the data folder was found
|
||||||
|
|||||||
@@ -3,60 +3,45 @@
|
|||||||
#include "TextApp.h"
|
#include "TextApp.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <filesystem>
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
static const int MAXIMUM_PIECES_SIZE = 10;
|
|
||||||
static const int BENCHMARK_PIECES_SIZE = 15;
|
|
||||||
|
|
||||||
|
|
||||||
void testGeneratorForAllSizes(int max_size);
|
void testGeneratorForAllSizes(int amount);
|
||||||
void testGeneratorForOneSize(int size);
|
void testGeneratorForOneSize(int size);
|
||||||
void printPiecesByTypesForOneSize(int size);
|
void testGeneratorByprintingAllNminos(int n);
|
||||||
void readStatsFromFilesForAllSizes(int max_size);
|
void testStoringAndRetrievingPieces(int size);
|
||||||
|
void generateFilesForAllSizes(int amount);
|
||||||
void benchmarking(int min_size, int max_size);
|
void generateFilesForOneSize(int size);
|
||||||
|
void loadFromFilesForOneSize(int size);
|
||||||
|
void readStatsFromFilesForAllSizes(int amount);
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
std::srand(std::time(NULL));
|
std::srand(std::time(NULL));
|
||||||
|
|
||||||
#ifdef BENCHMARK
|
// dev: generate files if it hasn't been done before, UI will NOT generate the files
|
||||||
benchmarking(1, BENCHMARK_PIECES_SIZE);
|
//generateFilesForAllSizes(10);
|
||||||
#else
|
|
||||||
// dev: generate files if it hasn't been done before, UI will NOT generate the files
|
|
||||||
//generateFilesForAllSizes(10);
|
|
||||||
|
|
||||||
PiecesFiles pf;
|
TextApp UI;
|
||||||
for (int i = 1; i <= MAXIMUM_PIECES_SIZE; i++) {
|
UI.run();
|
||||||
if (!std::filesystem::exists("data/pieces/" + std::to_string(i) + "minos.bin")) {
|
|
||||||
std::cout << "INFO: Pieces files for size " << i << " not found, generating..." << std::endl;
|
|
||||||
pf.savePieces(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TextApp UI;
|
|
||||||
UI.run();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void testGeneratorForAllSizes(int max_size) {
|
void testGeneratorForAllSizes(int amount) {
|
||||||
using std::chrono::high_resolution_clock;
|
using std::chrono::high_resolution_clock;
|
||||||
using std::chrono::duration_cast;
|
using std::chrono::duration_cast;
|
||||||
using std::chrono::duration;
|
using std::chrono::duration;
|
||||||
using std::chrono::milliseconds;
|
using std::chrono::milliseconds;
|
||||||
Generator generator;
|
Generator generator;
|
||||||
|
|
||||||
for (int i = 1; i <= max_size; i++) {
|
for (int i = 1; i <= amount; i++) {
|
||||||
auto t1 = high_resolution_clock::now();
|
auto t1 = high_resolution_clock::now();
|
||||||
std::vector<Polyomino> n_minos = generator.generatePolyominoes(i);
|
std::vector<Polyomino> n_minos = generator.generatePolyominoes(i);
|
||||||
auto t2 = high_resolution_clock::now();
|
auto t2 = high_resolution_clock::now();
|
||||||
|
|
||||||
duration<double, std::milli> ms_double = t2 - t1;
|
duration<double, std::milli> ms_double = t2 - t1;
|
||||||
std::cout << "Generated " << n_minos.size() << " polyominoes of size " << i << " in " << ms_double.count() << "ms" << std::endl;
|
std::cout << "generated " << n_minos.size() << " polyominoes of size " << i << " in " << ms_double.count() << "ms" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,8 +63,24 @@ void testGeneratorForOneSize(int size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printPiecesByTypesForOneSize(int size) {
|
void testGeneratorByprintingAllNminos(int n) {
|
||||||
|
Generator generator;
|
||||||
|
std::vector<Polyomino> n_minos = generator.generatePolyominoes(n);
|
||||||
|
|
||||||
|
for (Polyomino& n_mino : n_minos) {
|
||||||
|
n_mino.goToSpawnPosition();
|
||||||
|
}
|
||||||
|
std::sort(n_minos.begin(), n_minos.end());
|
||||||
|
|
||||||
|
for (Polyomino& n_mino : n_minos) {
|
||||||
|
|
||||||
|
std::cout << n_mino << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testStoringAndRetrievingPieces(int size) {
|
||||||
PiecesFiles piecesFiles;
|
PiecesFiles piecesFiles;
|
||||||
|
piecesFiles.savePieces(size);
|
||||||
|
|
||||||
std::vector<Piece> pieces;
|
std::vector<Piece> pieces;
|
||||||
std::vector<int> convexPieces;
|
std::vector<int> convexPieces;
|
||||||
@@ -103,9 +104,79 @@ void printPiecesByTypesForOneSize(int size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void readStatsFromFilesForAllSizes(int max_size) {
|
void generateFilesForAllSizes(int amount) {
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
using std::chrono::duration;
|
||||||
|
using std::chrono::milliseconds;
|
||||||
PiecesFiles piecesFiles;
|
PiecesFiles piecesFiles;
|
||||||
for (int i = 1; i <= max_size; i++) {
|
|
||||||
|
for (int i = 1; i <= amount; i++) {
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
piecesFiles.savePieces(i);
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
|
||||||
|
duration<double, std::milli> ms_double = t2 - t1;
|
||||||
|
std::cout << "Generated pieces files for size " << i << " in " << ms_double.count() << "ms" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Piece> pieces;
|
||||||
|
std::vector<int> convexPieces;
|
||||||
|
std::vector<int> holelessPieces;
|
||||||
|
std::vector<int> otherPieces;
|
||||||
|
for (int i = 1; i <= amount; i++) {
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
piecesFiles.loadPieces(i, pieces, convexPieces, holelessPieces, otherPieces);
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
|
||||||
|
duration<double, std::milli> ms_double = t2 - t1;
|
||||||
|
std::cout << "Read pieces from files for size " << i << " in " << ms_double.count() << "ms" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateFilesForOneSize(int size) {
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
using std::chrono::duration;
|
||||||
|
using std::chrono::milliseconds;
|
||||||
|
PiecesFiles piecesFiles;
|
||||||
|
|
||||||
|
std::cout << "Generating " << size << "-minos files" << std::endl;
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
piecesFiles.savePieces(size);
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
|
||||||
|
duration<double, std::milli> ms_double = t2 - t1;
|
||||||
|
std::cout << ms_double.count() << "ms" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadFromFilesForOneSize(int size) {
|
||||||
|
using std::chrono::high_resolution_clock;
|
||||||
|
using std::chrono::duration_cast;
|
||||||
|
using std::chrono::duration;
|
||||||
|
using std::chrono::milliseconds;
|
||||||
|
PiecesFiles piecesFiles;
|
||||||
|
|
||||||
|
std::vector<Piece> pieces;
|
||||||
|
std::vector<int> convexPieces;
|
||||||
|
std::vector<int> holelessPieces;
|
||||||
|
std::vector<int> otherPieces;
|
||||||
|
std::cout << "Loading " << size << "-minos from files" << std::endl;
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
auto t1 = high_resolution_clock::now();
|
||||||
|
piecesFiles.loadPieces(size, pieces, convexPieces, holelessPieces, otherPieces);
|
||||||
|
auto t2 = high_resolution_clock::now();
|
||||||
|
|
||||||
|
duration<double, std::milli> ms_double = t2 - t1;
|
||||||
|
std::cout << ms_double.count() << "ms" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void readStatsFromFilesForAllSizes(int amount) {
|
||||||
|
PiecesFiles piecesFiles;
|
||||||
|
for (int i = 1; i <= amount; i++) {
|
||||||
std::vector<Piece> pieces;
|
std::vector<Piece> pieces;
|
||||||
std::vector<int> convexPieces;
|
std::vector<int> convexPieces;
|
||||||
std::vector<int> holelessPieces;
|
std::vector<int> holelessPieces;
|
||||||
@@ -118,66 +189,3 @@ void readStatsFromFilesForAllSizes(int max_size) {
|
|||||||
std::cout << "Others " << i << "-minos : " << otherPieces.size() << std::endl;
|
std::cout << "Others " << i << "-minos : " << otherPieces.size() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void benchmarking(int min_size, int max_size) {
|
|
||||||
using std::chrono::high_resolution_clock;
|
|
||||||
using std::chrono::duration_cast;
|
|
||||||
using std::chrono::duration;
|
|
||||||
using std::chrono::milliseconds;
|
|
||||||
|
|
||||||
std::cout << "| n | Number | Generation | File storing | File retrieving | File size |" << std::endl;
|
|
||||||
std::cout << "| - | - | - | - | - | - |" << std::endl;
|
|
||||||
|
|
||||||
Generator gen;
|
|
||||||
PiecesFiles pf;
|
|
||||||
|
|
||||||
for (int i = min_size; i <= max_size; i++) {
|
|
||||||
std::cout << "| " << i;
|
|
||||||
|
|
||||||
auto t1 = high_resolution_clock::now();
|
|
||||||
std::vector<Polyomino> polyominoes = gen.generatePolyominoes(i);
|
|
||||||
auto t2 = high_resolution_clock::now();
|
|
||||||
duration<double, std::milli> 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::flush(std::cout);
|
|
||||||
|
|
||||||
t1 = high_resolution_clock::now();
|
|
||||||
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::flush(std::cout);
|
|
||||||
|
|
||||||
polyominoes.clear();
|
|
||||||
polyominoes.shrink_to_fit();
|
|
||||||
|
|
||||||
std::vector<Piece> pieces;
|
|
||||||
std::vector<int> convexPieces;
|
|
||||||
std::vector<int> holelessPieces;
|
|
||||||
std::vector<int> otherPieces;
|
|
||||||
|
|
||||||
t1 = high_resolution_clock::now();
|
|
||||||
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::flush(std::cout);
|
|
||||||
|
|
||||||
pieces.clear();
|
|
||||||
pieces.shrink_to_fit();
|
|
||||||
convexPieces.clear();
|
|
||||||
convexPieces.shrink_to_fit();
|
|
||||||
holelessPieces.clear();
|
|
||||||
holelessPieces.shrink_to_fit();
|
|
||||||
otherPieces.clear();
|
|
||||||
otherPieces.shrink_to_fit();
|
|
||||||
|
|
||||||
std::string filePath;
|
|
||||||
pf.getFilePath(i, filePath);
|
|
||||||
int fileSize = std::filesystem::file_size(filePath);
|
|
||||||
std::cout << " | " << fileSize << " bytes |" << std::endl;
|
|
||||||
std::flush(std::cout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
#include "./AssetManager.h"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
static const unsigned char data_fonts_pressstart_prstartk_ttf[] = {
|
|
||||||
#include <data/fonts/pressstart/prstartk.ttf.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_fonts_pressstart_prstart_ttf[] = {
|
|
||||||
#include <data/fonts/pressstart/prstart.ttf.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Rotate0_png[] = {
|
|
||||||
#include <data/images/keybinds/Rotate0.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_RotateCW_png[] = {
|
|
||||||
#include <data/images/keybinds/RotateCW.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const unsigned char data_images_keybinds_Pause_png[] = {
|
|
||||||
#include <data/images/keybinds/Pause.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_RotateCCW_png[] = {
|
|
||||||
#include <data/images/keybinds/RotateCCW.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_Rotate180_png[] = {
|
|
||||||
#include <data/images/keybinds/Rotate180.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_Harddrop_png[] = {
|
|
||||||
#include <data/images/keybinds/Harddrop.png.h>
|
|
||||||
};
|
|
||||||
|
|
||||||
static const Asset assets[] = {
|
|
||||||
{data_fonts_pressstart_prstartk_ttf, sizeof(data_fonts_pressstart_prstartk_ttf)},
|
|
||||||
{data_fonts_pressstart_prstart_ttf, sizeof(data_fonts_pressstart_prstart_ttf)},
|
|
||||||
{data_images_keybinds_Rotate0_png, sizeof(data_images_keybinds_Rotate0_png)},
|
|
||||||
{data_images_keybinds_Moveright_png, sizeof(data_images_keybinds_Moveright_png)},
|
|
||||||
{data_images_keybinds_RotateCW_png, sizeof(data_images_keybinds_RotateCW_png)},
|
|
||||||
{data_images_keybinds_Pause_png, sizeof(data_images_keybinds_Pause_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_RotateCCW_png, sizeof(data_images_keybinds_RotateCCW_png)},
|
|
||||||
{data_images_keybinds_Moveleft_png, sizeof(data_images_keybinds_Moveleft_png)},
|
|
||||||
{data_images_keybinds_Rotate180_png, sizeof(data_images_keybinds_Rotate180_png)},
|
|
||||||
{data_images_keybinds_Retry_png, sizeof(data_images_keybinds_Retry_png)},
|
|
||||||
{data_images_keybinds_Harddrop_png, sizeof(data_images_keybinds_Harddrop_png)},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::map<std::string, AssetName> assetMap = {
|
|
||||||
{"data/fonts/pressstart/prstartk.ttf", AssetName::data_fonts_pressstart_prstartk_ttf},
|
|
||||||
{"data/fonts/pressstart/prstart.ttf", AssetName::data_fonts_pressstart_prstart_ttf},
|
|
||||||
{"data/images/keybinds/Rotate0.png", AssetName::data_images_keybinds_Rotate0_png},
|
|
||||||
{"data/images/keybinds/Moveright.png", AssetName::data_images_keybinds_Moveright_png},
|
|
||||||
{"data/images/keybinds/RotateCW.png", AssetName::data_images_keybinds_RotateCW_png},
|
|
||||||
{"data/images/keybinds/Pause.png", AssetName::data_images_keybinds_Pause_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/RotateCCW.png", AssetName::data_images_keybinds_RotateCCW_png},
|
|
||||||
{"data/images/keybinds/Moveleft.png", AssetName::data_images_keybinds_Moveleft_png},
|
|
||||||
{"data/images/keybinds/Rotate180.png", AssetName::data_images_keybinds_Rotate180_png},
|
|
||||||
{"data/images/keybinds/Retry.png", AssetName::data_images_keybinds_Retry_png},
|
|
||||||
{"data/images/keybinds/Harddrop.png", AssetName::data_images_keybinds_Harddrop_png},
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const Asset& getResource(AssetName fileName) {
|
|
||||||
return assets[static_cast<std::size_t>(fileName)];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Asset& getResource(const std::string& fileName) {
|
|
||||||
return getResource(assetMap.at(fileName));
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct Asset {
|
|
||||||
const unsigned char* data;
|
|
||||||
std::size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class AssetName {
|
|
||||||
data_fonts_pressstart_prstartk_ttf,
|
|
||||||
data_fonts_pressstart_prstart_ttf,
|
|
||||||
data_images_keybinds_Rotate0_png,
|
|
||||||
data_images_keybinds_Moveright_png,
|
|
||||||
data_images_keybinds_RotateCW_png,
|
|
||||||
data_images_keybinds_Pause_png,
|
|
||||||
data_images_keybinds_Hold_png,
|
|
||||||
data_images_keybinds_Softdrop_png,
|
|
||||||
data_images_keybinds_RotateCCW_png,
|
|
||||||
data_images_keybinds_Moveleft_png,
|
|
||||||
data_images_keybinds_Rotate180_png,
|
|
||||||
data_images_keybinds_Retry_png,
|
|
||||||
data_images_keybinds_Harddrop_png,
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
const Asset& getResource(AssetName fileName);
|
|
||||||
|
|
||||||
const Asset& getResource(const std::string& fileName);
|
|
||||||
29
xmake.lua
@@ -1,7 +1,5 @@
|
|||||||
add_rules("mode.debug", "mode.release")
|
add_rules("mode.debug", "mode.release")
|
||||||
|
|
||||||
includes("xmake/bin2c.lua")
|
|
||||||
|
|
||||||
add_requires("sfml 3.0.0")
|
add_requires("sfml 3.0.0")
|
||||||
|
|
||||||
set_languages("c++20")
|
set_languages("c++20")
|
||||||
@@ -13,33 +11,18 @@ target("core")
|
|||||||
add_files("src/Pieces/*.cpp")
|
add_files("src/Pieces/*.cpp")
|
||||||
add_files("src/Core/*.cpp")
|
add_files("src/Core/*.cpp")
|
||||||
|
|
||||||
|
target("text")
|
||||||
|
set_kind("binary")
|
||||||
|
set_default(false)
|
||||||
|
add_files("./src/TextUI/*.cpp")
|
||||||
|
add_deps("core")
|
||||||
|
|
||||||
target("graph")
|
target("graph")
|
||||||
set_default(true)
|
|
||||||
add_rules("bin2c", {
|
|
||||||
extensions = {".png", ".ttf"},
|
|
||||||
outputSource = {"src/Utils/AssetManager.cpp"},
|
|
||||||
outputHeader = {"src/Utils/AssetManager.h"}
|
|
||||||
})
|
|
||||||
set_kind("binary")
|
set_kind("binary")
|
||||||
add_files("./src/GraphicalUI/**.cpp")
|
add_files("./src/GraphicalUI/**.cpp")
|
||||||
add_files("data/fonts/**.ttf", "data/images/**.png")
|
|
||||||
add_deps("core")
|
add_deps("core")
|
||||||
add_packages("sfml")
|
add_packages("sfml")
|
||||||
|
|
||||||
target("text")
|
|
||||||
set_default(false)
|
|
||||||
set_kind("binary")
|
|
||||||
add_files("./src/TextUI/*.cpp")
|
|
||||||
add_deps("core")
|
|
||||||
|
|
||||||
target("benchmark")
|
|
||||||
set_default(false)
|
|
||||||
set_kind("binary")
|
|
||||||
add_files("./src/TextUI/*.cpp")
|
|
||||||
add_deps("core")
|
|
||||||
add_defines("BENCHMARK")
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- If you want to known more usage about xmake, please see https://xmake.io
|
-- If you want to known more usage about xmake, please see https://xmake.io
|
||||||
--
|
--
|
||||||
|
|||||||
124
xmake/bin2c.lua
@@ -1,124 +0,0 @@
|
|||||||
rule("bin2c")
|
|
||||||
set_extensions(".bin")
|
|
||||||
|
|
||||||
on_load(function (target)
|
|
||||||
local headerdir = path.join(target:autogendir(), "rules", "bin2c")
|
|
||||||
|
|
||||||
local outputSource = table.unpack(target:extraconf("rules", "bin2c", "outputSource"))
|
|
||||||
|
|
||||||
if not os.isdir(headerdir) then
|
|
||||||
os.mkdir(headerdir)
|
|
||||||
end
|
|
||||||
|
|
||||||
target:add("includedirs", headerdir)
|
|
||||||
|
|
||||||
target:add("files", outputSource)
|
|
||||||
end)
|
|
||||||
|
|
||||||
before_buildcmd_files(function (target, batchcmds, sourcebatch, opt)
|
|
||||||
local outputHeader = table.unpack(target:extraconf("rules", "bin2c", "outputHeader"))
|
|
||||||
|
|
||||||
local outputHeaderEnumContent = ""
|
|
||||||
|
|
||||||
for _, filePath in ipairs(sourcebatch.sourcefiles) do
|
|
||||||
local escapedName = string.gsub(filePath, "[/|.]", "_")
|
|
||||||
outputHeaderEnumContent = outputHeaderEnumContent .. "\t" .. escapedName .. ",\n"
|
|
||||||
end
|
|
||||||
|
|
||||||
local outputHeaderContent = string.format([[
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
struct Asset {
|
|
||||||
const unsigned char* data;
|
|
||||||
std::size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class AssetName {
|
|
||||||
%s
|
|
||||||
};
|
|
||||||
|
|
||||||
const Asset& getResource(AssetName fileName);
|
|
||||||
|
|
||||||
const Asset& getResource(const std::string& fileName);
|
|
||||||
]], outputHeaderEnumContent)
|
|
||||||
|
|
||||||
local outputSource = table.unpack(target:extraconf("rules", "bin2c", "outputSource"))
|
|
||||||
|
|
||||||
local relativePath = path.join(path.relative(path.directory(outputHeader), path.directory(outputSource)), path.filename(outputHeader))
|
|
||||||
|
|
||||||
local outputSourceContent = string.format([[
|
|
||||||
#include "%s"
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
]], relativePath)
|
|
||||||
|
|
||||||
|
|
||||||
local outputSourceArrayVars = ""
|
|
||||||
local outputSourceMapVars = ""
|
|
||||||
|
|
||||||
for _, filePath in ipairs(sourcebatch.sourcefiles) do
|
|
||||||
local escapedName = string.gsub(filePath, "[/|.]", "_")
|
|
||||||
local varDecl = string.format("static const unsigned char %s[] = {\n\t#include <%s>\n};\n\n", escapedName, filePath .. ".h")
|
|
||||||
outputSourceContent = outputSourceContent .. varDecl
|
|
||||||
outputSourceArrayVars = outputSourceArrayVars .. string.format("\t{%s, sizeof(%s)},\n", escapedName, escapedName)
|
|
||||||
outputSourceMapVars = outputSourceMapVars .. string.format("\t{\"%s\", AssetName::%s},\n", filePath, escapedName)
|
|
||||||
end
|
|
||||||
|
|
||||||
outputSourceContent = outputSourceContent .. string.format([[
|
|
||||||
static const Asset assets[] = {
|
|
||||||
%s
|
|
||||||
};
|
|
||||||
|
|
||||||
static const std::map<std::string, AssetName> assetMap = {
|
|
||||||
%s
|
|
||||||
};
|
|
||||||
|
|
||||||
]], outputSourceArrayVars, outputSourceMapVars)
|
|
||||||
|
|
||||||
outputSourceContent = outputSourceContent .. [[
|
|
||||||
const Asset& getResource(AssetName fileName) {
|
|
||||||
return assets[static_cast<std::size_t>(fileName)];
|
|
||||||
}
|
|
||||||
|
|
||||||
const Asset& getResource(const std::string& fileName) {
|
|
||||||
return getResource(assetMap.at(fileName));
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
|
|
||||||
for _, sourcefile_bin in ipairs(sourcebatch.sourcefiles) do
|
|
||||||
-- get header file
|
|
||||||
local headerdir = path.join(target:autogendir(), "rules", "bin2c")
|
|
||||||
local headerfile = path.join(headerdir, sourcefile_bin .. ".h")
|
|
||||||
target:add("includedirs", headerdir)
|
|
||||||
|
|
||||||
-- add commands
|
|
||||||
batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", sourcefile_bin)
|
|
||||||
batchcmds:mkdir(headerdir)
|
|
||||||
local argv = {"lua", "private.utils.bin2c", "-i", path(sourcefile_bin), "-o", path(headerfile)}
|
|
||||||
local linewidth = target:extraconf("rules", "bin2c", "linewidth")
|
|
||||||
if linewidth then
|
|
||||||
table.insert(argv, "-w")
|
|
||||||
table.insert(argv, tostring(linewidth))
|
|
||||||
end
|
|
||||||
local nozeroend = target:extraconf("rules", "bin2c", "nozeroend")
|
|
||||||
if nozeroend then
|
|
||||||
table.insert(argv, "--nozeroend")
|
|
||||||
end
|
|
||||||
batchcmds:vrunv(os.programfile(), argv, {envs = {XMAKE_SKIP_HISTORY = "y"}})
|
|
||||||
|
|
||||||
-- add deps
|
|
||||||
batchcmds:add_depfiles(sourcefile_bin)
|
|
||||||
batchcmds:set_depmtime(os.mtime(headerfile))
|
|
||||||
batchcmds:set_depcache(target:dependfile(headerfile))
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", outputHeader)
|
|
||||||
io.writefile(outputHeader, outputHeaderContent)
|
|
||||||
batchcmds:show_progress(opt.progress, "${color.build.object}generating.bin2c %s", outputSource)
|
|
||||||
io.writefile(outputSource, outputSourceContent)
|
|
||||||
end)
|
|
||||||