3 Commits

Author SHA1 Message Date
507bc9cc86 omg on a un deuxième menu 2025-03-23 20:15:05 +01:00
e721a71894 omg on a un menu 2025-03-23 18:45:34 +01:00
1781b85332 update readme 2025-03-23 16:53:58 +01:00
18 changed files with 353 additions and 18 deletions

1
.gitignore vendored
View File

@@ -11,6 +11,7 @@ build/
# personnal documentation
doc/*.txt
doc/*.violet.html
doc/mockups/*
# pieces files
data/pieces/*.bin

View File

@@ -1,8 +1,11 @@
# jminos
Modern stacker game with every polyominos from size 1 to 15, made in C++ with [SFML 3](https://www.sfml-dev.org/)!
## Manual build and run
You need to install xmake and have a compiler with c++20 compatibility
This project uses xmake for compiling.
To be able to build it, you need to [install xmake](https://xmake.io) and have a compiler with c++20 compatibility, xmake will install SFML for you.
### Build the project
@@ -15,8 +18,12 @@ If you need to change the toolchain (for example using gcc):
### Run the project
Graphical version:
``xmake run graph``
``xmake run``
Note that the program will genereate the polyomino files for you. This can be quite long so it only does it up to size 10.
Command line version:
If for some reasons you wanna run the command line version:
``xmake run text``
## Credits
Font used: [Press Start](https://www.zone38.net/font/#pressstart).

Binary file not shown.

View File

@@ -0,0 +1,17 @@
Thanks for downloading one of codeman38's retro video game fonts, as seen on Memepool, BoingBoing, and all around the blogosphere.
So, you're wondering what the license is for these fonts? Pretty simple; it's based upon that used for Bitstream's Vera font set <http://www.gnome.org/fonts/>.
Basically, here are the key points summarized, in as little legalese as possible; I hate reading license agreements as much as you probably do:
With one specific exception, you have full permission to bundle these fonts in your own free or commercial projects-- and by projects, I'm referring to not just software but also electronic documents and print publications.
So what's the exception? Simple: you can't re-sell these fonts in a commercial font collection. I've seen too many font CDs for sale in stores that are just a repackaging of thousands of freeware fonts found on the internet, and in my mind, that's quite a bit like highway robbery. Note that this *only* applies to products that are font collections in and of themselves; you may freely bundle these fonts with an operating system, application program, or the like.
Feel free to modify these fonts and even to release the modified versions, as long as you change the original font names (to ensure consistency among people with the font installed) and as long as you give credit somewhere in the font file to codeman38 or zone38.net. I may even incorporate these changes into a later version of my fonts if you wish to send me the modifed fonts via e-mail.
Also, feel free to mirror these fonts on your own site, as long as you make it reasonably clear that these fonts are not your own work. I'm not asking for much; linking to zone38.net or even just mentioning the nickname codeman38 should be enough.
Well, that pretty much sums it up... so without further ado, install and enjoy these fonts from the golden age of video games.
[ codeman38 | cody@zone38.net | http://www.zone38.net/ ]

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,4 @@
#include "InGameAppMenu.h"
#include "GamePlayingAppMenu.h"
#include "AppMenu.h"
@@ -7,7 +7,7 @@
#include <SFML/Graphics.hpp>
InGameAppMenu::InGameAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow) :
GamePlayingAppMenu::GamePlayingAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow) :
AppMenu(menuStack, settings, renderWindow),
game(this->settings->getMenu().startGame(this->settings->getGamemode()))
{
@@ -16,7 +16,7 @@ InGameAppMenu::InGameAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_p
this->paused = false;
}
void InGameAppMenu::computeFrame() {
void GamePlayingAppMenu::computeFrame() {
this->updateMetaBinds();
if (this->escReleased) {
@@ -46,7 +46,7 @@ void InGameAppMenu::computeFrame() {
}
}
void InGameAppMenu::drawFrame() const {
void GamePlayingAppMenu::drawFrame() const {
this->renderWindow->clear(sf::Color::Black);
int sizeMultiplier = this->settings->getWindowSizeMultiplier();

View File

@@ -7,13 +7,13 @@
#include <SFML/Graphics.hpp>
class InGameAppMenu : public AppMenu {
class GamePlayingAppMenu : public AppMenu {
private:
Game game;
bool paused;
public:
InGameAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow);
GamePlayingAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow);
void computeFrame();

View File

@@ -0,0 +1,91 @@
#include "GameSettingsAppMenu.h"
#include "AppMenu.h"
#include "GamePlayingAppMenu.h"
#include "PlayerCursor.h"
#include <stack>
#include <memory>
#include <vector>
#include <SFML/Graphics.hpp>
GameSettingsAppMenu::GameSettingsAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow) :
AppMenu(menuStack, settings, renderWindow),
playerCursor(std::vector<unsigned int>({2, 3, 1})) {
}
void GameSettingsAppMenu::computeFrame() {
this->updateMetaBinds();
this->playerCursor.updatePosition();
switch (this->playerCursor.getPosition().y) {
case 1 : {
switch (this->playerCursor.getPosition().x) {
case 0 : {this->settings->setGamemode(SPRINT); break;}
case 1 : {this->settings->setGamemode(MARATHON); break;}
case 2 : {this->settings->setGamemode(ULTRA); break;}
}
break;
}
case 2 : {
switch (this->playerCursor.getPosition().x) {
case 0 : {this->settings->setGamemode(MASTER); break;}
case 1 : break; //TODO
case 2 : break; //TODO
}
break;
}
}
if (this->enterReleased) {
if (this->playerCursor.getPosition().y == 0) {
//TODO
}
if (this->playerCursor.getPosition().y > 0) {
this->menuStack->push(std::make_shared<GamePlayingAppMenu>(this->menuStack, this->settings, this->renderWindow));
}
}
if (this->escReleased) {
this->menuStack->pop();
}
}
void GameSettingsAppMenu::drawFrame() const {
this->renderWindow->clear(sf::Color(200, 200, 200));
sf::Font font("data/fonts/pressstart/prstartk.ttf");
sf::Text text(font, "", this->settings->getWindowSizeMultiplier() * 2);
text.setFillColor(sf::Color(0, 0, 0));
text.setOutlineColor(sf::Color(255, 255, 255));
text.setString("GAME SETTINGS");
text.setOrigin(text.getLocalBounds().getCenter());
text.setPosition(sf::Vector2f({(float) this->settings->getWindowSizeMultiplier() * 40, (float) this->settings->getWindowSizeMultiplier() * 5}));
this->renderWindow->draw(text);
this->placeText(text, "PIECES SELECT", 5.f, 15.f, 0, 0);
this->placeText(text, "BOARD SELECT", 40.f, 15.f, 1, 0);
this->placeText(text, "SPRINT", 5.f, 25.f, 0, 1);
this->placeText(text, "MARATHON", 25.f, 25.f, 1, 1);
this->placeText(text, "ULTRA", 50.f, 25.f, 2, 1);
this->placeText(text, "MASTER", 5.f, 35.f, 0, 2);
this->placeText(text, "TODO", 25.f, 35.f, 1, 2);
this->placeText(text, "TOOD", 50.f, 35.f, 2, 2);
this->renderWindow->display();
}
void GameSettingsAppMenu::placeText(sf::Text& text, const sf::String& string, float xPos, float yPos, unsigned int xCursorOutline, unsigned int yCursorOutline) const {
float sizeMultiplier = this->settings->getWindowSizeMultiplier();
text.setString(string);
text.setOutlineThickness((this->playerCursor.getPosition().x == xCursorOutline
&& this->playerCursor.getPosition().y == yCursorOutline) ? (sizeMultiplier / 2) : 0);
text.setOrigin(sf::Vector2f({0, text.getLocalBounds().size.y / 2}));
text.setPosition(sf::Vector2f({sizeMultiplier * xPos, sizeMultiplier * yPos}));
this->renderWindow->draw(text);
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include "AppMenu.h"
#include "PlayerCursor.h"
#include <stack>
#include <memory>
#include <SFML/Graphics.hpp>
class GameSettingsAppMenu : public AppMenu {
private:
PlayerCursor playerCursor;
public:
GameSettingsAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow);
void computeFrame();
void drawFrame() const;
void placeText(sf::Text& text, const sf::String& string, float xPos, float yPos, unsigned int xCursorOutline, unsigned int yCursorOutline) const ;
};

View File

@@ -1,23 +1,35 @@
#include "MainAppMenu.h"
#include "AppMenu.h"
#include "InGameAppMenu.h"
#include "GameSettingsAppMenu.h"
#include "PlayerCursor.h"
#include <stack>
#include <memory>
#include <vector>
#include <SFML/Graphics.hpp>
MainAppMenu::MainAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow) :
AppMenu(menuStack, settings, renderWindow) {
AppMenu(menuStack, settings, renderWindow),
playerCursor(std::vector<unsigned int>({1, 1, 1})) {
}
void MainAppMenu::computeFrame() {
this->updateMetaBinds();
this->playerCursor.updatePosition();
if (this->enterReleased) {
this->menuStack->push(std::make_shared<InGameAppMenu>(this->menuStack, this->settings, this->renderWindow));
if (this->playerCursor.getPosition().y == 0) {
this->menuStack->push(std::make_shared<GameSettingsAppMenu>(this->menuStack, this->settings, this->renderWindow));
}
if (this->playerCursor.getPosition().y == 1) {
//TODO
}
if (this->playerCursor.getPosition().y == 2) {
//TODO
}
}
if (this->escReleased) {
this->menuStack->pop();
@@ -25,7 +37,37 @@ void MainAppMenu::computeFrame() {
}
void MainAppMenu::drawFrame() const {
this->renderWindow->clear(sf::Color::Black);
this->renderWindow->clear(sf::Color(200, 200, 200));
float sizeMultiplier = this->settings->getWindowSizeMultiplier();
sf::Font font("data/fonts/pressstart/prstartk.ttf");
sf::Text text(font, "", this->settings->getWindowSizeMultiplier() * 2);
text.setFillColor(sf::Color(0, 0, 0));
text.setOutlineColor(sf::Color(255, 255, 255));
text.setString("JMINOS");
text.setOrigin(text.getLocalBounds().getCenter());
text.setPosition(sf::Vector2f({sizeMultiplier * 40, sizeMultiplier * 10}));
this->renderWindow->draw(text);
text.setString("PLAY");
text.setOutlineThickness((this->playerCursor.getPosition().y == 0) ? (sizeMultiplier / 2) : 0);
text.setOrigin(text.getLocalBounds().getCenter());
text.setPosition(sf::Vector2f({sizeMultiplier * 40, sizeMultiplier * 20}));
this->renderWindow->draw(text);
text.setString("SETTINGS");
text.setOutlineThickness((this->playerCursor.getPosition().y == 1) ? (sizeMultiplier / 2) : 0);
text.setOrigin(text.getLocalBounds().getCenter());
text.setPosition(sf::Vector2f({sizeMultiplier * 40, sizeMultiplier * 30}));
this->renderWindow->draw(text);
text.setString("INFO");
text.setOutlineThickness((this->playerCursor.getPosition().y == 2) ? (sizeMultiplier / 2) : 0);
text.setOrigin(text.getLocalBounds().getCenter());
text.setPosition(sf::Vector2f({sizeMultiplier * 40, sizeMultiplier * 40}));
this->renderWindow->draw(text);
this->renderWindow->display();
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include "AppMenu.h"
#include "PlayerCursor.h"
#include <stack>
#include <memory>
@@ -8,6 +9,9 @@
class MainAppMenu : public AppMenu {
private:
PlayerCursor playerCursor;
public:
MainAppMenu(std::shared_ptr<MenuStack> menuStack, std::shared_ptr<Settings> settings, std::shared_ptr<sf::RenderWindow> renderWindow);

View File

@@ -0,0 +1,105 @@
#include "PlayerCursor.h"
#include "../Keybinds.h"
#include "../Settings.h"
#include <vector>
#include <algorithm>
#include <SFML/Graphics.hpp>
static const int MENU_DAS = FRAMES_PER_SECOND / 2;
PlayerCursor::PlayerCursor(std::vector<unsigned int> rows) :
rows(rows) {
this->position = sf::Vector2u({0, 0});
this->leftDAS = 0;
this->rightDAS = 0;
this->upDAS = 0;
this->downDAS = 0;
}
void PlayerCursor::updatePosition() {
(sf::Keyboard::isKeyPressed(sfKey::Left)) ? (this->leftDAS++) : (this->leftDAS = 0);
if (this->shouldMove(this->leftDAS)) {
this->moveLeft();
}
(sf::Keyboard::isKeyPressed(sfKey::Right)) ? (this->rightDAS++) : (this->rightDAS = 0);
if (this->shouldMove(this->rightDAS)) {
this->moveRight();
}
(sf::Keyboard::isKeyPressed(sfKey::Up)) ? (this->upDAS++) : (this->upDAS = 0);
if (this->shouldMove(this->upDAS)) {
this->moveUp();
}
(sf::Keyboard::isKeyPressed(sfKey::Down)) ? (this->downDAS++) : (this->downDAS = 0);
if (this->shouldMove(this->downDAS)) {
this->moveDown();
}
}
void PlayerCursor::goToPosition(const sf::Vector2u& newPosition) {
if (this->rows.size() > newPosition.y) {
if (this->rows.at(newPosition.y) > newPosition.x) {
this->position = newPosition;
}
}
}
const sf::Vector2u& PlayerCursor::getPosition() const {
return this->position;
}
bool PlayerCursor::shouldMove(int DAS) const {
return (DAS == 1
|| (DAS > MENU_DAS && (DAS % 5) == 0)
|| (DAS > (FRAMES_PER_SECOND * 2)));
}
void PlayerCursor::moveLeft() {
if (this->position.x == 0) {
this->position.x = this->rows.at(this->position.y) - 1;
}
else {
this->position.x--;
}
}
void PlayerCursor::moveRight() {
if (this->position.x == this->rows.at(this->position.y) - 1) {
this->position.x = 0;
}
else {
this->position.x++;
}
}
void PlayerCursor::moveUp() {
if (this->position.y == 0) {
this->position.y = this->rows.size() - 1;
}
else {
this->position.y--;
}
if (this->position.x >= this->rows.at(this->position.y)) {
this->position.x = this->rows.at(this->position.y) - 1;
}
}
void PlayerCursor::moveDown() {
if (this->position.y == this->rows.size() - 1) {
this->position.y = 0;
}
else {
this->position.y++;
}
if (this->position.x >= this->rows.at(this->position.y)) {
this->position.x = this->rows.at(this->position.y) - 1;
}
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <vector>
#include <SFML/Graphics.hpp>
class PlayerCursor {
private:
std::vector<unsigned int> rows;
sf::Vector2u position;
int leftDAS;
int rightDAS;
int upDAS;
int downDAS;
public:
PlayerCursor(std::vector<unsigned int> rows);
void updatePosition();
void goToPosition(const sf::Vector2u& newPosition);
const sf::Vector2u& getPosition() const;
private:
bool shouldMove(int DAS) const;
void moveLeft();
void moveRight();
void moveUp();
void moveDown();
};

View File

@@ -7,7 +7,7 @@
#include <fstream>
static const sf::Vector2u BASE_WINDOW_SIZE = {80, 50};
static const int WINDOW_SIZE_MULTIPLIERS[] = {4, 6, 9, 14, 20};
static const int WINDOW_SIZE_MULTIPLIERS[] = {4, 6, 10, 14, 20};
static const int WINDOW_SIZE_LAST_MODE = (sizeof(WINDOW_SIZE_MULTIPLIERS) / sizeof(int)) - 1;

View File

@@ -10,7 +10,12 @@
static const int MAXIMUM_BOARD_WIDTH = 40;
static const int MAXIMUM_BOARD_HEIGHT = 40;
//#define __JMINOS_RELEASE__
#ifdef __JMINOS_RELEASE__
static const int MAXIMUM_PIECES_SIZE = 15;
#else
static const int MAXIMUM_PIECES_SIZE = 10;
#endif
class Settings {

View File

@@ -12,7 +12,8 @@ void resetKeybindFile(int layout);
int main() {
std::srand(std::time(NULL));
// keep only for dev
#ifndef __JMINOS_RELEASE__
PiecesFiles pf;
for (int i = 1; i <= MAXIMUM_PIECES_SIZE; i++) {
if (!std::filesystem::exists("data/pieces/" + std::to_string(i) + "minos.bin")) {
@@ -29,8 +30,10 @@ int main() {
}
}
// before compiling release version
resetConfigFiles();
// uncomment before compiling release version
//resetConfigFiles();
#endif
GraphApp UI;
UI.run();

View File

@@ -6,6 +6,8 @@ set_languages("c++20")
set_rundir(".")
set_optimize("fastest")
target("core")
set_kind("$(kind)")
add_files("src/Pieces/*.cpp")