From 86dd10d9a0ad2f6a043771081a62bf1c5ef13249 Mon Sep 17 00:00:00 2001
From: Sulimov Igor Andreevich <igansulimov@edu.hse.ru>
Date: Tue, 25 Mar 2025 01:33:04 +0300
Subject: [PATCH] Almost completed CommonBuilder

---
 CMakeLists.txt                                |  2 +
 include/Builder/Builders/CommonBuilder.h      |  8 ++--
 include/Builder/GameBuilderDirector.h         |  5 +-
 include/Config.h                              | 14 +++---
 .../Entities/DynamicEntities/Enemy.h          | 10 ++--
 include/MazeContent/Entities/Pacman.h         |  6 +--
 .../Entities/StaticEntities/Food.h            |  8 ++--
 include/States/GameState.h                    |  5 ++
 include/States/SelectState.h                  |  1 +
 source/Builder/Builders/CommonBuilder.cpp     | 48 +++++++++++++++++++
 source/Builder/GameBuilderDirector.cpp        | 15 ++++++
 .../Entities/DynamicEntities/Enemy.cpp        | 14 ++++++
 source/MazeContent/Entities/Pacman.cpp        | 14 ++++++
 .../Entities/StaticEntities/Food.cpp          | 19 ++++++++
 14 files changed, 143 insertions(+), 26 deletions(-)
 create mode 100644 source/Builder/GameBuilderDirector.cpp
 create mode 100644 source/MazeContent/Entities/StaticEntities/Food.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7578cf3..f7cdcc7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,8 +24,10 @@ add_executable(pac-man
         "source/MazeContent/Buildings/Pass.cpp"
         "source/MazeContent/Entities/IEntity.cpp"
         "source/MazeContent/Entities/Pacman.cpp"
+        "source/MazeContent/Entities/StaticEntities/Food.cpp"
         "source/MazeContent/Entities/DynamicEntities/Enemy.cpp"
         "source/Context/GameContext.cpp"
+        "source/Builder/GameBuilderDirector.cpp"
         "source/Builder/Builders/CommonBuilder.cpp"
         "source/Builder/Builders/SimpleBuilder.cpp"
         "source/Builder/Builders/ComplexBuilder.cpp"
diff --git a/include/Builder/Builders/CommonBuilder.h b/include/Builder/Builders/CommonBuilder.h
index 95d06db..6ec6ad7 100644
--- a/include/Builder/Builders/CommonBuilder.h
+++ b/include/Builder/Builders/CommonBuilder.h
@@ -6,11 +6,11 @@ class CommonBuilder: public IGameBuilder {
 public:
     virtual void create_rooms() override {}; ///@todo Определиться, нужны ли данные строчки или нет
     virtual void set_rooms_sides() override {}; ///@todo Определиться, нужны ли данные строчки или нет
-    void create_context(float dynamic_objects_ratio) override {}; ///@todo
+    void create_context(float dynamic_objects_ratio) override;
     void create_state(IStateManager& state_manager,
-                      sf::VideoMode video_mode, const std::string& window_title) override {}; ///@todo
-    void set_all_to_state() override {}; ///@todo
-    std::unique_ptr<GameState> get_game() override {}; ///@todo
+        sf::VideoMode video_mode, const std::string& window_title) override;
+    void set_all_to_state() override;
+    std::unique_ptr<GameState> get_game() override;
 public:
     CommonBuilder(float width, float height, float room_size);
     virtual ~CommonBuilder() = default;
diff --git a/include/Builder/GameBuilderDirector.h b/include/Builder/GameBuilderDirector.h
index 39770ad..3c6f1ee 100644
--- a/include/Builder/GameBuilderDirector.h
+++ b/include/Builder/GameBuilderDirector.h
@@ -4,11 +4,10 @@
 
 class GameBuilderDirector {
 public:
-    std::unique_ptr<GameState> build(IStateManager& state_manager); ///@todo
+    std::unique_ptr<GameState> build(IStateManager& state_manager);
 public:
     GameBuilderDirector(std::unique_ptr<IGameBuilder> ptr_builder,
-                        const sf::VideoMode& video_mode, const std::string& window_title,
-                        float dynamic_objects_ratio); ///@todo
+    const sf::VideoMode& video_mode, const std::string& window_title, float dynamic_objects_ratio);
 private:
     std::string m_window_title;
     sf::VideoMode m_video_mode;
diff --git a/include/Config.h b/include/Config.h
index aea287d..2b147c1 100644
--- a/include/Config.h
+++ b/include/Config.h
@@ -23,11 +23,11 @@ namespace config {
 //    const float EASY_GAME_ENEMY_RATIO = 0.0f;
 //    const float MEDIUM_GAME_ENEMY_RATIO = 0.03f;
 //    const float HARD_GAME_ENEMY_RATIO = 0.07f;
-//    const float ROOM_SIZE = 50;
-//    const float GAME_ENEMY_SIZE = ROOM_SIZE * 0.7;
-//    const float GAME_FOOD_SIZE = ROOM_SIZE * 0.2;
+    const float ROOM_SIZE = 50;
+    const float GAME_ENEMY_SIZE = ROOM_SIZE * 0.7;
+    const float GAME_FOOD_SIZE = ROOM_SIZE * 0.2;
 // Пакмэн:
-//    const float GAME_PACMAN_SIZE = ROOM_SIZE * 0.8;
+    const float GAME_PACMAN_SIZE = ROOM_SIZE * 0.8;
 //    const sf::Keyboard::Key KEY_LEFT = sf::Keyboard::A;
 //    const sf::Keyboard::Key KEY_RIGHT = sf::Keyboard::D;
 //    const sf::Keyboard::Key KEY_UP = sf::Keyboard::W;
@@ -41,9 +41,9 @@ namespace config {
 //    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 };
-//    const sf::Color GAME_COLOR_PACMAN{ 250, 150, 0 };
+    const sf::Color GAME_COLOR_PACMAN{ 250, 150, 0 };
     const sf::Color GAME_COLOR_ROOM{ 255, 255, 255 };
     const sf::Color GAME_COLOR_WALL{ 0, 0, 0 };
-//    const sf::Color GAME_FOOD_COLOR{ 0, 200, 100 };
-//    const sf::Color GAME_ENEMY_COLOR{ 255, 50, 0 };
+    const sf::Color GAME_FOOD_COLOR{ 0, 200, 100 };
+    const sf::Color GAME_ENEMY_COLOR{ 255, 50, 0 };
 }
\ No newline at end of file
diff --git a/include/MazeContent/Entities/DynamicEntities/Enemy.h b/include/MazeContent/Entities/DynamicEntities/Enemy.h
index bf1d23d..8dc3e67 100644
--- a/include/MazeContent/Entities/DynamicEntities/Enemy.h
+++ b/include/MazeContent/Entities/DynamicEntities/Enemy.h
@@ -4,12 +4,12 @@
 
 class Enemy: public IDynamicEntity {
 public:
-    void prepare_for_drawing() override; ///@todo
-    void draw_into(sf::RenderWindow& window) const override; ///@todo
-    std::unique_ptr<IDynamicEntity> clone() const override; ///@todo
-    void action() override; ///@todo
+    void prepare_for_drawing() override;
+    void draw_into(sf::RenderWindow& window) const override;
+    std::unique_ptr<IDynamicEntity> clone() const override;
+    void action() override;
 public:
-    Enemy(); ///@todo
+    Enemy();
 private:
     sf::RectangleShape m_rectangle;
     sf::Clock m_stopwatch;
diff --git a/include/MazeContent/Entities/Pacman.h b/include/MazeContent/Entities/Pacman.h
index c7f844f..91f9f33 100644
--- a/include/MazeContent/Entities/Pacman.h
+++ b/include/MazeContent/Entities/Pacman.h
@@ -4,11 +4,11 @@
 
 class Pacman: public IEntity {
 public:
-    void prepare_for_drawing() override; ///@todo
-    void draw_into(sf::RenderWindow& window) const override; ///@todo
+    void prepare_for_drawing() override;
+    void draw_into(sf::RenderWindow& window) const override;
     void move(Room::Direction direction);
 public:
-    Pacman(); ///@todo
+    Pacman();
 private:
     sf::CircleShape m_circle;
 };
\ No newline at end of file
diff --git a/include/MazeContent/Entities/StaticEntities/Food.h b/include/MazeContent/Entities/StaticEntities/Food.h
index cd589eb..f250579 100644
--- a/include/MazeContent/Entities/StaticEntities/Food.h
+++ b/include/MazeContent/Entities/StaticEntities/Food.h
@@ -4,11 +4,11 @@
 
 class Food: public IStaticEntity {
 public:
-    void prepare_for_drawing() override; ///@todo
-    void draw_into(sf::RenderWindow& window) const override; ///@todo
-    std::unique_ptr<IStaticEntity> clone() override; ///@todo
+    void prepare_for_drawing() override;
+    void draw_into(sf::RenderWindow& window) const override;
+    std::unique_ptr<IStaticEntity> clone() const override;
 public:
-    Food(); ///@todo
+    Food();
 private:
     sf::CircleShape m_circle;
 };
\ No newline at end of file
diff --git a/include/States/GameState.h b/include/States/GameState.h
index 873073a..761979d 100644
--- a/include/States/GameState.h
+++ b/include/States/GameState.h
@@ -9,6 +9,11 @@ class GameState: public IState, public IWindowKeeper {
 public:
     void set_maze(Maze&& maze);
     void set_context(GameContext&& context);
+    bool do_step() override; ///@todo
+protected:
+    void event_handling() override; ///@todo
+    void update() override; ///@todo
+    void render() override; ///@todo
 public:
     GameState(IStateManager& state_manager,
               const sf::VideoMode& video_mode, const std::string& window_title);
diff --git a/include/States/SelectState.h b/include/States/SelectState.h
index de523e9..1d4c370 100644
--- a/include/States/SelectState.h
+++ b/include/States/SelectState.h
@@ -6,6 +6,7 @@
 class SelectState: public IState, public IWindowKeeper {
 public:
     bool do_step() override;
+protected:
     void event_handling() override;
     void update() override;
     void render() override;
diff --git a/source/Builder/Builders/CommonBuilder.cpp b/source/Builder/Builders/CommonBuilder.cpp
index 8c9e575..f345679 100644
--- a/source/Builder/Builders/CommonBuilder.cpp
+++ b/source/Builder/Builders/CommonBuilder.cpp
@@ -1,5 +1,53 @@
 #include "Builder/Builders/CommonBuilder.h"
+#include "MazeContent/Entities/DynamicEntities/Enemy.h"
+#include "MazeContent/Entities/StaticEntities/Food.h"
 
 CommonBuilder::CommonBuilder(float width, float height, float room_size):
                             m_width(width), m_height(height), m_room_size(room_size) {}
 
+void CommonBuilder::create_context(float dynamic_objects_ratio) {
+    std::vector<Room*> buffer;
+    for (auto& row : m_rooms) {
+        for (auto& room : row) {
+            buffer.push_back(room.get());
+        }
+    }
+
+    int pos = std::rand() % buffer.size();
+    m_context.pacman.set_location(buffer.at(pos));
+    buffer.erase(buffer.begin() + pos);
+
+    size_t rooms_in_col = static_cast<size_t>(m_height / m_room_size) % 2 == 0 ? m_height / m_room_size - 1 : m_height / m_room_size;
+    size_t rooms_in_row = static_cast<size_t>(m_width / m_room_size) % 2 == 0 ? m_width / m_room_size - 1 : m_width / m_room_size;
+    for (size_t i = 0; i < static_cast<size_t>(rooms_in_row * rooms_in_col * dynamic_objects_ratio); ++i) {
+        pos = std::rand() % buffer.size();
+        m_context.dynamic_objects.emplace_back(std::move(std::make_unique<Enemy>()));
+        m_context.dynamic_objects.back()->set_location(buffer.at(pos));
+        buffer.erase(buffer.begin() + pos);
+    }
+
+    for (size_t i = 0; i < buffer.size(); ++i) {
+        m_context.static_objects.emplace_back(std::move(std::make_unique<Food>()));
+        m_context.static_objects.back()->set_location(buffer.at(i));
+    }
+    buffer.clear();
+}
+
+void CommonBuilder::create_state(IStateManager& state_manager,
+                                 sf::VideoMode video_mode, const std::string& window_title) {
+    m_game_state = std::make_unique<GameState>(state_manager, video_mode, window_title);
+}
+
+void CommonBuilder::set_all_to_state() {
+    std::vector<std::unique_ptr<Room>> rooms;
+    for (auto& row : m_rooms) {
+        for (auto& room : row)
+            rooms.emplace_back(std::move(room));
+    }
+    m_game_state->set_maze(Maze(std::move(rooms)));
+    m_game_state->set_context(std::move(m_context));
+}
+
+std::unique_ptr<GameState> CommonBuilder::get_game() {
+    return std::move(m_game_state);
+}
\ No newline at end of file
diff --git a/source/Builder/GameBuilderDirector.cpp b/source/Builder/GameBuilderDirector.cpp
new file mode 100644
index 0000000..d69bd8e
--- /dev/null
+++ b/source/Builder/GameBuilderDirector.cpp
@@ -0,0 +1,15 @@
+#include "Builder/GameBuilderDirector.h"
+
+GameBuilderDirector::GameBuilderDirector(std::unique_ptr<IGameBuilder> ptr_builder,
+    const sf::VideoMode& video_mode, const std::string& window_title, float dynamic_objects_ratio) :
+        m_ptr_builder(std::move(ptr_builder)), m_video_mode(video_mode), m_window_title(window_title),
+        m_dynamic_object_ratio(dynamic_objects_ratio) {}
+
+std::unique_ptr<GameState> GameBuilderDirector::build(IStateManager& state_manager) {
+    m_ptr_builder->create_rooms();
+    m_ptr_builder->set_rooms_sides();
+    m_ptr_builder->create_context(m_dynamic_object_ratio);
+    m_ptr_builder->create_state(state_manager, m_video_mode, m_window_title);
+    m_ptr_builder->set_all_to_state();
+    return m_ptr_builder->get_game();
+}
\ No newline at end of file
diff --git a/source/MazeContent/Entities/DynamicEntities/Enemy.cpp b/source/MazeContent/Entities/DynamicEntities/Enemy.cpp
index 989bfcb..e530548 100644
--- a/source/MazeContent/Entities/DynamicEntities/Enemy.cpp
+++ b/source/MazeContent/Entities/DynamicEntities/Enemy.cpp
@@ -1,9 +1,23 @@
 #include "MazeContent/Entities/DynamicEntities/Enemy.h"
+#include "Config.h"
+
+Enemy::Enemy() : m_rectangle({ config::GAME_ENEMY_SIZE / 2, config::GAME_ENEMY_SIZE / 2 }) {
+    m_rectangle.setOrigin(m_rectangle.getSize() / 2.f);
+    m_rectangle.setFillColor(config::GAME_ENEMY_COLOR);
+}
 
 std::unique_ptr<IDynamicEntity> Enemy::clone() const {
     return std::make_unique<Enemy>(*this);
 }
 
+void Enemy::prepare_for_drawing() {
+    m_rectangle.setPosition(m_ptr_room->get_position());
+}
+
+void Enemy::draw_into(sf::RenderWindow& window) const {
+    window.draw(m_rectangle);
+}
+
 void Enemy::action() {
     auto miliseconds = static_cast<size_t>(m_stopwatch.getElapsedTime().asMilliseconds());
     if (miliseconds < rand() % 10000)
diff --git a/source/MazeContent/Entities/Pacman.cpp b/source/MazeContent/Entities/Pacman.cpp
index 7799733..867174f 100644
--- a/source/MazeContent/Entities/Pacman.cpp
+++ b/source/MazeContent/Entities/Pacman.cpp
@@ -1,4 +1,18 @@
 #include "MazeContent/Entities/Pacman.h"
+#include <Config.h>
+
+Pacman::Pacman() :m_circle(config::GAME_PACMAN_SIZE / 2) {
+    m_circle.setOrigin(m_circle.getRadius(), m_circle.getRadius());
+    m_circle.setFillColor(config::GAME_COLOR_PACMAN);
+}
+
+void Pacman::prepare_for_drawing() {
+    m_circle.setPosition(m_ptr_room->get_position());
+}
+
+void Pacman::draw_into(sf::RenderWindow& window) const {
+    window.draw(m_circle);
+}
 
 void Pacman::move(Room::Direction direction) {
     m_ptr_room->get_side(direction)->enter(this);
diff --git a/source/MazeContent/Entities/StaticEntities/Food.cpp b/source/MazeContent/Entities/StaticEntities/Food.cpp
new file mode 100644
index 0000000..3b3d683
--- /dev/null
+++ b/source/MazeContent/Entities/StaticEntities/Food.cpp
@@ -0,0 +1,19 @@
+#include "MazeContent/Entities/StaticEntities/Food.h"
+#include "Config.h"
+
+Food::Food() : m_circle{config::GAME_FOOD_SIZE / 2} {
+    m_circle.setOrigin(m_circle.getRadius(), m_circle.getRadius());
+    m_circle.setFillColor(config::GAME_FOOD_COLOR);
+}
+
+std::unique_ptr<IStaticEntity> Food::clone() const {
+    return std::make_unique<Food>(*this);
+}
+
+void Food::prepare_for_drawing() {
+    m_circle.setPosition(m_ptr_room->get_position());
+}
+
+void Food::draw_into(sf::RenderWindow& window) const {
+    window.draw(m_circle);
+}
\ No newline at end of file
-- 
GitLab