From db89415e5b0a9f02fbf2bf9bdfc02c120131a691 Mon Sep 17 00:00:00 2001 From: Sulimov Igor Andreevich <igansulimov@edu.hse.ru> Date: Mon, 24 Mar 2025 02:39:11 +0300 Subject: [PATCH] Partly completed Button and Menu --- include/Application.h | 6 +++--- include/Buildings/IRoomSide.h | 8 ------- include/Buildings/Room.h | 8 ------- include/Draw/Button.h | 7 ++++--- include/Draw/IDrawable.h | 3 ++- include/Draw/IPreparable.h | 9 ++++++++ include/Draw/Menu.h | 2 +- include/Draw/MyFont.h | 4 +++- include/MazeContent/IEntity.h | 12 +++++++++++ include/MazeContent/IRoomSide.h | 11 ++++++++++ include/MazeContent/Maze.h | 12 +++++++++++ include/MazeContent/Pass.h | 15 +++++++++++++ include/MazeContent/Room.h | 20 ++++++++++++++++++ include/MazeContent/Wall.h | 15 +++++++++++++ include/States/SelectState.h | 8 +++---- include/config.h | 26 +++++++++++------------ source/Application.cpp | 4 ++++ source/Draw/Button.cpp | 21 +++++++++++++++++++ source/Draw/Menu.cpp | 1 + source/Draw/MyFont.cpp | 6 +++++- source/Maze_Content/Maze.cpp | 6 ++++++ source/State/SelectState.cpp | 37 ++++++++++++++++++++++++++++++++- 22 files changed, 197 insertions(+), 44 deletions(-) delete mode 100644 include/Buildings/IRoomSide.h delete mode 100644 include/Buildings/Room.h create mode 100644 include/Draw/IPreparable.h create mode 100644 include/MazeContent/IEntity.h create mode 100644 include/MazeContent/IRoomSide.h create mode 100644 include/MazeContent/Maze.h create mode 100644 include/MazeContent/Pass.h create mode 100644 include/MazeContent/Room.h create mode 100644 include/MazeContent/Wall.h create mode 100644 source/Maze_Content/Maze.cpp diff --git a/include/Application.h b/include/Application.h index 0e85662..7363d50 100644 --- a/include/Application.h +++ b/include/Application.h @@ -6,10 +6,10 @@ class Application: public IStateManager{ private: void set_next_state(std::unique_ptr<IState>&& ptr_state) override; void apply_differ_state_change() noexcept; +public: + Application(); + int run(); private: std::unique_ptr<IState> m_ptr_state_next; std::unique_ptr<IState> m_ptr_state_current; -public: - Application() {}; ///@todo - int run(); }; \ No newline at end of file diff --git a/include/Buildings/IRoomSide.h b/include/Buildings/IRoomSide.h deleted file mode 100644 index 381f790..0000000 --- a/include/Buildings/IRoomSide.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by РРіРѕСЂСЊ on 23.03.2025. -// - -#ifndef PAC_MAN_IROOMSIDE_H -#define PAC_MAN_IROOMSIDE_H - -#endif //PAC_MAN_IROOMSIDE_H diff --git a/include/Buildings/Room.h b/include/Buildings/Room.h deleted file mode 100644 index f594b3a..0000000 --- a/include/Buildings/Room.h +++ /dev/null @@ -1,8 +0,0 @@ -// -// Created by РРіРѕСЂСЊ on 23.03.2025. -// - -#ifndef PAC_MAN_ROOM_H -#define PAC_MAN_ROOM_H - -#endif //PAC_MAN_ROOM_H diff --git a/include/Draw/Button.h b/include/Draw/Button.h index 45f3d1a..573031e 100644 --- a/include/Draw/Button.h +++ b/include/Draw/Button.h @@ -6,15 +6,16 @@ class Button: public IDrawable { public: - void set(); ///@todo + void set(const sf::Vector2f& pos, const sf::Vector2f& button_size, const std::string& text, + size_t font_size, std::unique_ptr<ISelectCommand> ptr_command); void select() noexcept; void unselect() noexcept; bool is_selected() noexcept; bool is_position_in(sf::Vector2f pos) const noexcept; void push() const; - void draw_into(sf::RenderWindow& window) const override {}; ///@todo + void draw_into(sf::RenderWindow& window) const override {}; public: - Button(); ///@todo + Button(); private: sf::Text m_text; bool m_is_selected = false; diff --git a/include/Draw/IDrawable.h b/include/Draw/IDrawable.h index 85b6a20..5b25fe5 100644 --- a/include/Draw/IDrawable.h +++ b/include/Draw/IDrawable.h @@ -2,7 +2,8 @@ #include "SFML/Graphics.hpp" -struct IDrawable { +class IDrawable { +public: virtual void draw_into(sf::RenderWindow& window) const = 0; virtual ~IDrawable() = default; }; \ No newline at end of file diff --git a/include/Draw/IPreparable.h b/include/Draw/IPreparable.h new file mode 100644 index 0000000..780b5ac --- /dev/null +++ b/include/Draw/IPreparable.h @@ -0,0 +1,9 @@ +#pragma once + +#include "IDrawable.h" + +class IPreparable: public IDrawable { +public: + virtual void prepare_for_drawing() = 0; + virtual ~IPreparable() = default; +}; \ No newline at end of file diff --git a/include/Draw/Menu.h b/include/Draw/Menu.h index 318c55c..bd4815d 100644 --- a/include/Draw/Menu.h +++ b/include/Draw/Menu.h @@ -8,7 +8,7 @@ public: void draw_into(sf::RenderWindow& window) const override; void process_mouse(sf::Vector2f pos, bool is_pressed); public: - Menu(IStateManager& state_manager) {} ///@todo + Menu(IStateManager& state_manager); ///@todo private: std::array<Button, 4> m_buttons; }; \ No newline at end of file diff --git a/include/Draw/MyFont.h b/include/Draw/MyFont.h index 9d065a2..404dacb 100644 --- a/include/Draw/MyFont.h +++ b/include/Draw/MyFont.h @@ -3,10 +3,12 @@ #include "SFML/Graphics/Font.hpp" class MyFont { +public: + static MyFont& Instance(); + const sf::Font& get_font() const noexcept; public: MyFont(const MyFont&) = delete; MyFont& operator = (const MyFont&) = delete; - static MyFont& Instance(); private: MyFont(); private: diff --git a/include/MazeContent/IEntity.h b/include/MazeContent/IEntity.h new file mode 100644 index 0000000..0f5725b --- /dev/null +++ b/include/MazeContent/IEntity.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Draw/IPreparable.h" + +class IEntity: public IPreparable { +public: + virtual void set_location(Room ptr_room) = 0; ///@todo + virtual Room get_location() = 0; ///@todo + virtual ~IEntity() = default; +protected: + Room* m_ptr_room{ nullptr }; +}; \ No newline at end of file diff --git a/include/MazeContent/IRoomSide.h b/include/MazeContent/IRoomSide.h new file mode 100644 index 0000000..1675c08 --- /dev/null +++ b/include/MazeContent/IRoomSide.h @@ -0,0 +1,11 @@ +#pragma once + +#include "Draw/IPreparable.h" + +class IEntity; + +class IRoomSide: public IPreparable { +public: + virtual void enter(IEntity* entity) = 0; + virtual ~IRoomSide() = default; +}; \ No newline at end of file diff --git a/include/MazeContent/Maze.h b/include/MazeContent/Maze.h new file mode 100644 index 0000000..5fea69d --- /dev/null +++ b/include/MazeContent/Maze.h @@ -0,0 +1,12 @@ +#pragma once + +#include "Room.h" + +class Maze: public IDrawable { +public: + void draw_into(sf::RenderWindow& window) const override; ///@todo +public: + Maze(std::vector<std::unique_ptr<Room>>&& rooms): m_rooms(std::move(rooms)) {} +private: + std::vector<std::unique_ptr<Room>>&& m_rooms; +}; \ No newline at end of file diff --git a/include/MazeContent/Pass.h b/include/MazeContent/Pass.h new file mode 100644 index 0000000..0771782 --- /dev/null +++ b/include/MazeContent/Pass.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Room.h" + +class Pass : public IRoomSide { +public: + void enter(IEntity* entity) override; ///@todo + void prepare_for_drawing() override; ///@todo + void draw_into(sf::RenderWindow& window) const override; ///@todo +public: + Pass(Room& room1, Room& room2) : m_room1(room1), m_room2(room2) {} +private: + Room& m_room1; + Room& m_room2; +}; \ No newline at end of file diff --git a/include/MazeContent/Room.h b/include/MazeContent/Room.h new file mode 100644 index 0000000..3a8a9de --- /dev/null +++ b/include/MazeContent/Room.h @@ -0,0 +1,20 @@ +#pragma once + +#include "IRoomSide.h" + +class Room: public IDrawable { +public: + enum Direction { INVALID = -1, LEFT, RIGHT, UP, DOWN }; + float get_size(); ///@todo + void set_position(sf::Vector2f); ///@todo + sf::Vector2f get_position(); ///@todo + void set_side(Direction side, IRoomSide prt_side); ///@todo + IRoomSide get_side(Direction side); ///@todo + Direction get_direction(IRoomSide prt_side); ///@todo +public: + Room(float size); ///@todo +public: + std::array<std::shared_ptr<IRoomSide>, 4> m_sides; +private: + sf::RectangleShape m_rectangle; +}; \ No newline at end of file diff --git a/include/MazeContent/Wall.h b/include/MazeContent/Wall.h new file mode 100644 index 0000000..dd6a544 --- /dev/null +++ b/include/MazeContent/Wall.h @@ -0,0 +1,15 @@ +#pragma once + +#include "Room.h" + +class Wall : public IRoomSide { +public: + void enter(IEntity* entity) override {}; + void prepare_for_drawing() override; ///@todo + void draw_into(sf::RenderWindow& window) const override; ///@todo +public: + Wall(Room& room) : m_room(room) {} +private: + Room& m_room; + sf::Vertex m_line[2]; +}; \ No newline at end of file diff --git a/include/States/SelectState.h b/include/States/SelectState.h index 2b366db..de523e9 100644 --- a/include/States/SelectState.h +++ b/include/States/SelectState.h @@ -5,10 +5,10 @@ class SelectState: public IState, public IWindowKeeper { public: - bool do_step() override {return false;} ///@todo - void event_handling() override {}; ///@todo - void update() override {}; ///@todo - void render() override {}; ///@todo + bool do_step() override; + void event_handling() override; + void update() override; + void render() override; public: SelectState(IStateManager& state_manager, const sf::VideoMode& video_mode, const std::string& window_title); private: diff --git a/include/config.h b/include/config.h index 6599abf..ffdca33 100644 --- a/include/config.h +++ b/include/config.h @@ -5,18 +5,18 @@ namespace config { // Общее: // const unsigned int FRAME_RATE_LIMIT = 60; // Меню: -// const sf::Vector2f BUTTON_SIZE = { 250, 100 }; -// const size_t BUTTON_FONT_SIZE = static_cast<size_t>(BUTTON_SIZE.y / 1.5f); -// const float BUTTON_FRAME_THICKNESS = 2.0f; + const sf::Vector2f BUTTON_SIZE = { 250, 100 }; + const size_t BUTTON_FONT_SIZE = static_cast<size_t>(BUTTON_SIZE.y / 1.5f); + const float BUTTON_FRAME_THICKNESS = 2.0f; const char FONT_FILE[] = "Calibri Light.ttf"; -// const char SELECT_LEVEL_TITLE[] = "Select Level"; -// const sf::VideoMode SELECT_LEVEL_VIDEO_MODE{ 400, 600 }; -// const char BUTTON_TEXT_EASY[] = "Easy"; -// const char BUTTON_TEXT_MEDIUM[] = "Medium"; -// const char BUTTON_TEXT_HARD[] = "Hard"; -// const char BUTTON_TEXT_EXIT[] = "Exit"; + const char SELECT_LEVEL_TITLE[] = "Select Level"; + const sf::VideoMode SELECT_LEVEL_VIDEO_MODE{ 400, 600 }; + const char BUTTON_TEXT_EASY[] = "Easy"; + const char BUTTON_TEXT_MEDIUM[] = "Medium"; + const char BUTTON_TEXT_HARD[] = "Hard"; + const char BUTTON_TEXT_EXIT[] = "Exit"; // РРіСЂР°: -// const sf::VideoMode GAME_VIDEO_MODE{ 1080, 720 }; + const sf::VideoMode GAME_VIDEO_MODE{ 1080, 720 }; // const char EASY_GAME_TITLE[] = "Level: Easy"; // const char MEDIUM_GAME_TITLE[] = "Level: Medium"; // const char HARD_GAME_TITLE[] = "Level: Hard"; @@ -33,11 +33,11 @@ namespace config { // const sf::Keyboard::Key KEY_UP = sf::Keyboard::W; // const sf::Keyboard::Key KEY_DOWN = sf::Keyboard::S; // Цвета: -// const sf::Color BUTTON_COLOR_TEXT{ 0, 0, 0 }; + const sf::Color BUTTON_COLOR_TEXT{ 0, 0, 0 }; const sf::Color BUTTON_COLOR_FILL{ 180, 180, 180 }; const sf::Color BUTTON_COLOR_SELECTION{ 255, 180, 180 }; -// const sf::Color BUTTON_COLOR_FRAME{ 0, 0, 0 }; -// const sf::Color SELECT_LEVEL_BACKGROUND_COLOR{ 230,230,230 }; + const sf::Color BUTTON_COLOR_FRAME{ 0, 0, 0 }; + const sf::Color SELECT_LEVEL_BACKGROUND_COLOR{ 230,230,230 }; // const sf::Color GAME_COLOR_BACKGROUND_INGAME{ 230,230,230 }; // const sf::Color GAME_COLOR_BACKGROUND_WIN{ 0, 255, 0 }; // const sf::Color GAME_COLOR_BACKGROUND_LOST{ 255, 0, 0 }; diff --git a/source/Application.cpp b/source/Application.cpp index a9f7d9e..978d8ed 100644 --- a/source/Application.cpp +++ b/source/Application.cpp @@ -1,7 +1,11 @@ #include "Application.h" +#include "States/SelectState.h" #include <iostream> +Application::Application(): m_ptr_state_current(std::make_unique<SelectState> + (*this, config::SELECT_LEVEL_VIDEO_MODE, config::SELECT_LEVEL_TITLE)) {} + void Application::set_next_state(std::unique_ptr<IState>&& ptr_state) { m_ptr_state_next = std::move(ptr_state); } diff --git a/source/Draw/Button.cpp b/source/Draw/Button.cpp index 9c5f634..5fd6436 100644 --- a/source/Draw/Button.cpp +++ b/source/Draw/Button.cpp @@ -1,4 +1,25 @@ #include "Draw/Button.h" +#include "Draw/MyFont.h" + +Button::Button() { + m_text.setFont(MyFont::Instance().get_font()); + m_text.setCharacterSize(config::BUTTON_FONT_SIZE); + m_text.setFillColor(config::BUTTON_COLOR_TEXT); + m_rectangle.setFillColor(config::BUTTON_COLOR_FILL); + m_rectangle.setOutlineThickness(config::BUTTON_FRAME_THICKNESS); + m_rectangle.setOutlineColor(config::BUTTON_COLOR_FRAME); +} + +void Button::set(const sf::Vector2f& pos, const sf::Vector2f& button_size, const std::string& text, + size_t font_size, std::unique_ptr<ISelectCommand> ptr_command) { + m_rectangle.setOrigin(m_rectangle.getSize() / 2.f); + m_rectangle.setSize(button_size); + m_rectangle.setPosition(pos); + m_text.setString(text); + auto bounds = m_text.getLocalBounds(); + m_text.setOrigin(bounds.left + bounds.width / 2.0f, bounds.top + bounds.height / 2.0f); + m_ptr_command = std::move(ptr_command); +} void Button::push() const { m_ptr_command->execute(); diff --git a/source/Draw/Menu.cpp b/source/Draw/Menu.cpp index cb22023..ee7987b 100644 --- a/source/Draw/Menu.cpp +++ b/source/Draw/Menu.cpp @@ -1,5 +1,6 @@ #include "Draw/Menu.h" + void Menu::draw_into(sf::RenderWindow& window) const { for (const Button& ptr_button : m_buttons) ptr_button.draw_into(window); diff --git a/source/Draw/MyFont.cpp b/source/Draw/MyFont.cpp index e92fa09..0389c99 100644 --- a/source/Draw/MyFont.cpp +++ b/source/Draw/MyFont.cpp @@ -3,11 +3,15 @@ MyFont::MyFont() { if (!m_font.loadFromFile(FONT_PATH + std::string(config::FONT_FILE))) { - throw std::runtime_error("Could not open the font file!"); + throw std::runtime_error("Could not open the Font file!"); } } MyFont& MyFont::Instance() { static MyFont instance; return instance; +} + +const sf::Font& MyFont::get_font() const noexcept { + return m_font; } \ No newline at end of file diff --git a/source/Maze_Content/Maze.cpp b/source/Maze_Content/Maze.cpp new file mode 100644 index 0000000..8f80fe6 --- /dev/null +++ b/source/Maze_Content/Maze.cpp @@ -0,0 +1,6 @@ +#include "MazeContent/Maze.h" + +void Maze::draw_into(sf::RenderWindow& window) const { + for (const auto& room : m_rooms) + room->draw_into(window); +} \ No newline at end of file diff --git a/source/State/SelectState.cpp b/source/State/SelectState.cpp index d0e20cb..e4cf73a 100644 --- a/source/State/SelectState.cpp +++ b/source/State/SelectState.cpp @@ -1,4 +1,39 @@ #include "States/SelectState.h" +#include "States/ExitState.h" SelectState::SelectState(IStateManager& state_manager, const sf::VideoMode& video_mode, const std::string& window_title): - IWindowKeeper(video_mode, window_title), IState(state_manager), m_menu(state_manager) {} \ No newline at end of file + IWindowKeeper(video_mode, window_title), IState(state_manager), m_menu(state_manager) {} + +bool SelectState::do_step() { + event_handling(); + update(); + render(); + return true; +} + +void SelectState::event_handling() { + sf::Event event; + while (m_window.pollEvent(event)) { + if (event.type == sf::Event::Closed) { + m_state_manager.set_next_state(std::make_unique<ExitState>(m_state_manager)); + break; + } + if (event.type == sf::Event::Resized) { + sf::View view = m_window.getView(); + view.setSize(event.size.width, event.size.height); + m_window.setView(view); + } + } +} + +void SelectState::update() { + sf::Vector2f pos = m_window.mapPixelToCoords(sf::Mouse::getPosition(m_window)); + bool is_pressed = sf::Mouse::isButtonPressed(sf::Mouse::Button::Left); + m_menu.process_mouse(pos, is_pressed); +} + +void SelectState::render() { + m_window.clear(config::SELECT_LEVEL_BACKGROUND_COLOR); + m_menu.draw_into(m_window); + m_window.display(); +} \ No newline at end of file -- GitLab