From 03593ccb773b6f05b41b0370d6477557d118bd7b Mon Sep 17 00:00:00 2001 From: Salah-Eddine Date: Sun, 12 Apr 2026 13:45:33 +0200 Subject: [PATCH 1/5] [ADD] sfml lib --- src/graphicals/SFML/SfmlModule.cpp | 181 +++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 src/graphicals/SFML/SfmlModule.cpp diff --git a/src/graphicals/SFML/SfmlModule.cpp b/src/graphicals/SFML/SfmlModule.cpp new file mode 100644 index 0000000..d15687d --- /dev/null +++ b/src/graphicals/SFML/SfmlModule.cpp @@ -0,0 +1,181 @@ +#include "IGraphic.hpp" +#include +#include +#include +#include +#include +#include +#include + +static sf::Color toSFMLColor(std::uint8_t colorIndex) { + switch (colorIndex) { + case 1: return sf::Color::White; + case 2: return sf::Color::Red; + case 3: return sf::Color::Green; + case 4: return sf::Color::Yellow; + case 5: return sf::Color::Blue; + case 6: return sf::Color::Magenta; + case 7: return sf::Color::Cyan; + default: return sf::Color(20, 20, 20); + } +} + +class SFMLModule : public Arcade::IGraphics { +private: + sf::RenderWindow* _window; + sf::Font _font; + std::map _keyMapping; + bool _initialized; + int _cellSize; + float _windowWidth; + float _windowHeight; + + void initKeyMapping() { + _keyMapping[Arcade::InputAction::Up] = sf::Keyboard::Up; + _keyMapping[Arcade::InputAction::Down] = sf::Keyboard::Down; + _keyMapping[Arcade::InputAction::Left] = sf::Keyboard::Left; + _keyMapping[Arcade::InputAction::Right] = sf::Keyboard::Right; + _keyMapping[Arcade::InputAction::Quit] = sf::Keyboard::Q; + _keyMapping[Arcade::InputAction::Menu] = sf::Keyboard::M; + _keyMapping[Arcade::InputAction::Restart] = sf::Keyboard::R; + _keyMapping[Arcade::InputAction::NextGraphics] = sf::Keyboard::G; + _keyMapping[Arcade::InputAction::PrevGraphics] = sf::Keyboard::H; + _keyMapping[Arcade::InputAction::NextGame] = sf::Keyboard::N; + _keyMapping[Arcade::InputAction::PrevGame] = sf::Keyboard::B; + _keyMapping[Arcade::InputAction::Action] = sf::Keyboard::Return; + } + + Arcade::InputAction convertKeyToAction(sf::Keyboard::Key key) { + for (const auto& [action, mappedKey] : _keyMapping) { + if (mappedKey == key) return action; + } + return Arcade::InputAction::None; + } + +public: + SFMLModule() : _window(nullptr), _initialized(false), _cellSize(25), _windowWidth(800), _windowHeight(600) { + initKeyMapping(); + } + + ~SFMLModule() { + if (_initialized) shutdown(); + } + + void init() override { + if (_initialized) return; + + _window = new sf::RenderWindow(sf::VideoMode(1280, 720), "Arcade - SFML", + sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize); + + if (!_window) { + std::cerr << "SFML Window creation failed" << std::endl; + return; + } + + _window->setFramerateLimit(60); + + #ifdef __APPLE__ + if (!_font.loadFromFile("/System/Library/Fonts/Monaco.ttf")) { + std::cerr << "Warning: Could not load font" << std::endl; + } + #else + if (!_font.loadFromFile("/usr/share/fonts/TTF/DejaVuSansMono.ttf")) { + std::cerr << "Warning: Could not load font" << std::endl; + } + #endif + + _initialized = true; + } + + void shutdown() override { + if (!_initialized) return; + + if (_window) { + _window->close(); + delete _window; + _window = nullptr; + } + _initialized = false; + } + + void clear() override { + if (_window) { + _window->clear(sf::Color::Black); + } + } + + void draw(const std::vector& cells) override { + if (!_window) return; + + sf::Vector2u windowSize = _window->getSize(); + float scaleX = windowSize.x / _windowWidth; + float scaleY = windowSize.y / _windowHeight; + + for (const auto& cell : cells) { + float x = cell.x * _cellSize * scaleX; + float y = cell.y * _cellSize * scaleY; + float width = _cellSize * scaleX; + float height = _cellSize * scaleY; + + sf::RectangleShape rect(sf::Vector2f(width - 1, height - 1)); + rect.setPosition(x, y); + rect.setFillColor(toSFMLColor(cell.color)); + + if (cell.color == 0) { + rect.setOutlineThickness(1); + rect.setOutlineColor(sf::Color(40, 40, 40)); + } + + _window->draw(rect); + + if (cell.character != ' ') { + sf::Text text; + text.setFont(_font); + text.setString(cell.character); + text.setCharacterSize(static_cast(_cellSize * 0.7f * scaleY)); + text.setFillColor(toSFMLColor(cell.textColor)); + + sf::FloatRect textBounds = text.getLocalBounds(); + text.setPosition( + x + (width - textBounds.width) / 2.0f, + y + (height - textBounds.height) / 2.0f - textBounds.top + ); + + _window->draw(text); + } + } + } + + void display() override { + if (_window) { + _window->display(); + } + } + + Arcade::InputAction pollEvent() override { + if (!_window) return Arcade::InputAction::None; + + sf::Event event; + while (_window->pollEvent(event)) { + if (event.type == sf::Event::Closed) { + return Arcade::InputAction::Quit; + } + if (event.type == sf::Event::KeyPressed) { + return convertKeyToAction(event.key.code); + } + if (event.type == sf::Event::Resized) { + sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); + _window->setView(sf::View(visibleArea)); + } + } + return Arcade::InputAction::None; + } + + std::string getName() const override { + return "SFML"; + } +}; + +extern "C" Arcade::IGraphics* createGraphics() { + return new SFMLModule(); +} From 84630693059e9dc9d56175a618a75b10eade698e Mon Sep 17 00:00:00 2001 From: YetAnotherMechanicusEnjoyer Date: Sun, 12 Apr 2026 16:13:02 +0200 Subject: [PATCH 2/5] [FIX] Linuxify SFML Module --- src/graphicals/{SFML => Sfml}/SfmlModule.cpp | 76 ++++++++++---------- 1 file changed, 36 insertions(+), 40 deletions(-) rename src/graphicals/{SFML => Sfml}/SfmlModule.cpp (73%) diff --git a/src/graphicals/SFML/SfmlModule.cpp b/src/graphicals/Sfml/SfmlModule.cpp similarity index 73% rename from src/graphicals/SFML/SfmlModule.cpp rename to src/graphicals/Sfml/SfmlModule.cpp index d15687d..8cb16d6 100644 --- a/src/graphicals/SFML/SfmlModule.cpp +++ b/src/graphicals/Sfml/SfmlModule.cpp @@ -6,6 +6,11 @@ #include #include #include +#ifdef __APPLE__ + #define FONT "/System/Library/Fonts/Monaco.ttf" +#else + #define FONT "/usr/share/fonts/TTF/JetBrainsMonoNerdFontMono-Medium.ttf" +#endif static sf::Color toSFMLColor(std::uint8_t colorIndex) { switch (colorIndex) { @@ -31,18 +36,18 @@ class SFMLModule : public Arcade::IGraphics { float _windowHeight; void initKeyMapping() { - _keyMapping[Arcade::InputAction::Up] = sf::Keyboard::Up; - _keyMapping[Arcade::InputAction::Down] = sf::Keyboard::Down; - _keyMapping[Arcade::InputAction::Left] = sf::Keyboard::Left; - _keyMapping[Arcade::InputAction::Right] = sf::Keyboard::Right; - _keyMapping[Arcade::InputAction::Quit] = sf::Keyboard::Q; - _keyMapping[Arcade::InputAction::Menu] = sf::Keyboard::M; - _keyMapping[Arcade::InputAction::Restart] = sf::Keyboard::R; - _keyMapping[Arcade::InputAction::NextGraphics] = sf::Keyboard::G; - _keyMapping[Arcade::InputAction::PrevGraphics] = sf::Keyboard::H; - _keyMapping[Arcade::InputAction::NextGame] = sf::Keyboard::N; - _keyMapping[Arcade::InputAction::PrevGame] = sf::Keyboard::B; - _keyMapping[Arcade::InputAction::Action] = sf::Keyboard::Return; + _keyMapping[Arcade::InputAction::Up] = sf::Keyboard::Key::Up; + _keyMapping[Arcade::InputAction::Down] = sf::Keyboard::Key::Down; + _keyMapping[Arcade::InputAction::Left] = sf::Keyboard::Key::Left; + _keyMapping[Arcade::InputAction::Right] = sf::Keyboard::Key::Right; + _keyMapping[Arcade::InputAction::Quit] = sf::Keyboard::Key::Q; + _keyMapping[Arcade::InputAction::Menu] = sf::Keyboard::Key::M; + _keyMapping[Arcade::InputAction::Restart] = sf::Keyboard::Key::R; + _keyMapping[Arcade::InputAction::NextGraphics] = sf::Keyboard::Key::G; + _keyMapping[Arcade::InputAction::PrevGraphics] = sf::Keyboard::Key::H; + _keyMapping[Arcade::InputAction::NextGame] = sf::Keyboard::Key::N; + _keyMapping[Arcade::InputAction::PrevGame] = sf::Keyboard::Key::B; + _keyMapping[Arcade::InputAction::Action] = sf::Keyboard::Key::Enter; } Arcade::InputAction convertKeyToAction(sf::Keyboard::Key key) { @@ -64,25 +69,19 @@ class SFMLModule : public Arcade::IGraphics { void init() override { if (_initialized) return; - _window = new sf::RenderWindow(sf::VideoMode(1280, 720), "Arcade - SFML", + _window = new sf::RenderWindow(sf::VideoMode({1280, 720}, 24), "Arcade - SFML", sf::Style::Titlebar | sf::Style::Close | sf::Style::Resize); - + if (!_window) { std::cerr << "SFML Window creation failed" << std::endl; return; } _window->setFramerateLimit(60); - - #ifdef __APPLE__ - if (!_font.loadFromFile("/System/Library/Fonts/Monaco.ttf")) { - std::cerr << "Warning: Could not load font" << std::endl; - } - #else - if (!_font.loadFromFile("/usr/share/fonts/TTF/DejaVuSansMono.ttf")) { + + if (!_font.openFromFile(FONT)) { std::cerr << "Warning: Could not load font" << std::endl; } - #endif _initialized = true; } @@ -118,9 +117,9 @@ class SFMLModule : public Arcade::IGraphics { float height = _cellSize * scaleY; sf::RectangleShape rect(sf::Vector2f(width - 1, height - 1)); - rect.setPosition(x, y); + rect.setPosition({x, y}); rect.setFillColor(toSFMLColor(cell.color)); - + if (cell.color == 0) { rect.setOutlineThickness(1); rect.setOutlineColor(sf::Color(40, 40, 40)); @@ -129,18 +128,16 @@ class SFMLModule : public Arcade::IGraphics { _window->draw(rect); if (cell.character != ' ') { - sf::Text text; - text.setFont(_font); - text.setString(cell.character); + sf::Text text(_font, cell.character, 1); text.setCharacterSize(static_cast(_cellSize * 0.7f * scaleY)); text.setFillColor(toSFMLColor(cell.textColor)); - + sf::FloatRect textBounds = text.getLocalBounds(); - text.setPosition( - x + (width - textBounds.width) / 2.0f, - y + (height - textBounds.height) / 2.0f - textBounds.top - ); - + text.setPosition({ + x + (width - textBounds.size.x) / 2.0f, + y + (height - textBounds.size.y) / 2.0f - textBounds.position.y + }); + _window->draw(text); } } @@ -155,16 +152,15 @@ class SFMLModule : public Arcade::IGraphics { Arcade::InputAction pollEvent() override { if (!_window) return Arcade::InputAction::None; - sf::Event event; - while (_window->pollEvent(event)) { - if (event.type == sf::Event::Closed) { + while (auto event = _window->pollEvent()) { + if (event->is()) { return Arcade::InputAction::Quit; } - if (event.type == sf::Event::KeyPressed) { - return convertKeyToAction(event.key.code); + if (event->is()) { + return convertKeyToAction(event->getIf()->code); } - if (event.type == sf::Event::Resized) { - sf::FloatRect visibleArea(0, 0, event.size.width, event.size.height); + if (event->is()) { + sf::FloatRect visibleArea({0, 0}, {static_cast(event->getIf()->size.x), static_cast(event->getIf()->size.y)}); _window->setView(sf::View(visibleArea)); } } From 1192b4c6dca4de9f39ed2caf6bc10503dfc22d61 Mon Sep 17 00:00:00 2001 From: YetAnotherMechanicusEnjoyer Date: Sun, 12 Apr 2026 16:13:19 +0200 Subject: [PATCH 3/5] [UPDATE] Makefile & CMake to add SFML Lib --- CMakeLists.txt | 4 ++-- Makefile | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1fca7e2..fbef4db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,8 +35,8 @@ target_link_libraries(arcade_ncurses PRIVATE ncurses) add_arcade_library(arcade_sdl2 "src/graphicals/Sdl2/Sdl2Module.cpp") target_link_libraries(arcade_sdl2 PRIVATE SDL2 SDL2_ttf) -#add_arcade_library(arcade_sfml "src/graphicals/Sfml/SfmlModule.cpp") -#target_link_libraries(arcade_sfml sfml-graphics sfml-window sfml-system) +add_arcade_library(arcade_sfml "src/graphicals/Sfml/SfmlModule.cpp") +target_link_libraries(arcade_sfml sfml-graphics sfml-window sfml-system) add_arcade_library(arcade_snake "src/games/Snake/SnakeModule.cpp") add_arcade_library(arcade_pacman "src/games/Pacman/PacmanModule.cpp") diff --git a/Makefile b/Makefile index dc04f46..2a10212 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ GRAPH_DIR = graphicals/ CORE_FILES = main.cpp \ - Core.cpp + Core.cpp \ + MenuSelector.cpp CORE = $(addprefix $(SRC_DIR), $(CORE_FILES)) CORE_OBJ = $(CORE:%.cpp=$(DIR_OBJ)%.o) BINARY = arcade @@ -38,6 +39,11 @@ SDL2_OBJ = $(SDL2:%.cpp=$(DIR_OBJ)%.o) SDL2_LIB = $(LIB_DIR)arcade_sdl2.so SDL2_FLAGS = -lSDL2 -lSDL2_ttf +SFML = $(SRC_DIR)$(GRAPH_DIR)Sfml/SfmlModule.cpp +SFML_OBJ = $(SFML:%.cpp=$(DIR_OBJ)%.o) +SFML_LIB = $(LIB_DIR)arcade_sfml.so +SFML_FLAGS = -lsfml-graphics -lsfml-window -lsfml-system + CPPFLAGS = -std=c++20 -Iinclude -fPIC -g -Wall -Wextra -Werror LDFLAGS_CORE = -ldl -rdynamic LDFLAGS_LIB = -shared @@ -49,7 +55,7 @@ core: $(BINARY) games: $(SNAKE_LIB) $(PACMAN_LIB) -graphicals: $(NCURSES_LIB) $(SDL2_LIB) +graphicals: $(NCURSES_LIB) $(SDL2_LIB) $(SFML_LIB) $(BINARY): $(CORE_OBJ) @$(CC) $^ -o $@ $(LDFLAGS_CORE) @@ -75,6 +81,10 @@ $(SDL2_LIB): $(SDL2_OBJ) @$(CC) $^ -o $@ $(LDFLAGS_LIB) $(SDL2_FLAGS) @echo -e "\x1b[32m[OK] Library $@\x1b[0m" +$(SFML_LIB): $(SFML_OBJ) + @mkdir -p $(dir $(LIB_DIR)) + @$(CC) $^ -o $@ $(LDFLAGS_LIB) $(SFML_FLAGS) + @echo -e "\x1b[32m[OK] Library $@\x1b[0m" $(DIR_OBJ)%.o: %.cpp @mkdir -p $(dir $@) From cfbe04e53023451885adc5532b9568f571c083f5 Mon Sep 17 00:00:00 2001 From: YetAnotherMechanicusEnjoyer Date: Sun, 12 Apr 2026 16:19:52 +0200 Subject: [PATCH 4/5] [FIX] Mirror Push Workflow --- .github/workflows/mirror.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index d73eb7e..d41a5da 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -45,9 +45,9 @@ jobs: if [ -f "CMakeLists.txt" ]; then mkdir build && cd build cmake .. - make + make -k else - make && make clean + make -k && make clean fi - name: Check Compilation From 0a360809689d7a788702e13ef88cbb32b623731a Mon Sep 17 00:00:00 2001 From: YetAnotherMechanicusEnjoyer Date: Sun, 12 Apr 2026 16:26:16 +0200 Subject: [PATCH 5/5] [FIX] Mirror Push Workflow for real --- .github/workflows/mirror.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mirror.yml b/.github/workflows/mirror.yml index d41a5da..b977ef7 100644 --- a/.github/workflows/mirror.yml +++ b/.github/workflows/mirror.yml @@ -45,9 +45,9 @@ jobs: if [ -f "CMakeLists.txt" ]; then mkdir build && cd build cmake .. - make -k + make -k || true else - make -k && make clean + make -k || true && make clean fi - name: Check Compilation