diff --git a/source/application/App/Application.h b/source/application/App/Application.h index e2ad97f039730e116cbd8a4784f69f9954e46852..d8c0124f5d12df093cefaa247696f0258b22f9ba 100644 --- a/source/application/App/Application.h +++ b/source/application/App/Application.h @@ -10,6 +10,7 @@ class Application : public IStateManager { public: Application(); int run(); + ~Application() = default; private: void set_next_state(std::unique_ptr<IState>&& ptr_state) override; diff --git a/source/application/BobBuilder/GameBuilders.cpp b/source/application/BobBuilder/GameBuilders.cpp index d2232a1bfd13c27e2542f6145357288f52446648..653f125ccecbd8ef42beaec35b88bb91dbc45e19 100644 --- a/source/application/BobBuilder/GameBuilders.cpp +++ b/source/application/BobBuilder/GameBuilders.cpp @@ -7,25 +7,24 @@ CommonBuilder::CommonBuilder(float width, float height, float room_size) : } void CommonBuilder::create_context(float dynamic_objects_ratio) { - GameContext context; std::vector<Room*> empty_rooms_buffer; for (auto& row : m_rooms) for (auto& room : row) - empty_rooms_buffer.emplace_back(room); - + if (room != nullptr) + empty_rooms_buffer.emplace_back(room); float id = std::rand() % empty_rooms_buffer.size(); - context.pacman.set_location(empty_rooms_buffer[id]); + m_context.pacman.set_location(empty_rooms_buffer[id]); auto it = std::next(empty_rooms_buffer.begin(), id); empty_rooms_buffer.erase(it); + //@todo располагать врагов - + //располагаем еду for (auto it : empty_rooms_buffer) { auto food = std::make_unique<Food>(); food->set_location(it); - context.static_objects.emplace_back(std::move(food)); + m_context.static_objects.emplace_back(std::move(food)); } empty_rooms_buffer.clear(); - m_context = std::move(context); } void CommonBuilder::create_state(IStateManager &state_manager, const sf::VideoMode &mode, const std::string &window_title) { @@ -36,7 +35,7 @@ void CommonBuilder::set_all_to_state() { std::vector<Room*> rooms; for (auto& row : m_rooms) for (auto& col : row) - rooms.push_back(col); + rooms.emplace_back(col); Maze maze(rooms); m_game_state->set_maze(std::move(maze)); m_game_state->set_context(std::move(m_context)); @@ -55,10 +54,10 @@ void SimpleBuilder::create_rooms() { std::vector<Room*> row_vec; for (size_t col = 0; col < cols * room_size; col += room_size) { Room* room = new Room(m_room_size); - room->set_position(sf::Vector2f {col + left_pos.x, row + left_pos.y}); - row_vec.push_back(std::move(room)); + room->set_position({col + left_pos.x, row + left_pos.y}); + row_vec.emplace_back(room); } - m_rooms.push_back(std::move(row_vec)); + m_rooms.emplace_back(std::move(row_vec)); } } diff --git a/source/application/Context/Context.cpp b/source/application/Context/Context.cpp index 2757e87538cb91183250ac7a0e3e00455f54fef3..fe23398a7d68299620dc18bd3ca36791015ef4e1 100644 --- a/source/application/Context/Context.cpp +++ b/source/application/Context/Context.cpp @@ -4,6 +4,7 @@ GameContext GameContext::clone() { GameContext context; context.pacman = pacman; context.state = state; + for (auto& obj: static_objects) { context.static_objects.emplace_back(obj->clone()); } @@ -13,11 +14,17 @@ GameContext GameContext::clone() { return context; } +//@todo void ContextManager::restore_previous_context() { if (m_history.size() == 1) { m_initial_context = m_history.top().clone(); return; } m_initial_context = std::move(m_history.top()); - m_history.pop(); -} \ No newline at end of file +} + +void ContextManager::reset(GameContext &&context) { + while (!m_history.empty()) m_history.pop(); + m_initial_context = context.clone(); + m_history.emplace(m_initial_context.clone()); +} diff --git a/source/application/Context/Context.h b/source/application/Context/Context.h index 096ffba785abc248e000e8aa7d79311ed28e80e7..456d2e396e8c3f5a4c071a57b7eaa194f52746c4 100644 --- a/source/application/Context/Context.h +++ b/source/application/Context/Context.h @@ -19,7 +19,7 @@ class ContextManager { public: void save_current_context() { m_history.push(m_initial_context.clone()); }; void restore_previous_context(); - void reset(GameContext&& context) { m_initial_context = std::move(context); }; + void reset(GameContext&& context); GameContext& get_current_context() { return m_initial_context; }; private: GameContext m_initial_context; diff --git a/source/application/Drawable/Entity/IEntity.cpp b/source/application/Drawable/Entity/IEntity.cpp index 966fcad5aef7e35f4cb6ba2e07ab967d512d3f91..ab32bca22cc688da21afa05afcfce018067ffbc4 100644 --- a/source/application/Drawable/Entity/IEntity.cpp +++ b/source/application/Drawable/Entity/IEntity.cpp @@ -20,8 +20,18 @@ void Food::prepare_for_drawing() { m_shape.setPosition(m_ptr_room->get_position()); } -void Food::draw_into(sf::RenderWindow &window) { - prepare_for_drawing(); +std::unique_ptr<IGameEvent> Enemy::accept(IVisitor* ptr_visitor) { + return ptr_visitor->visit(this); +} + +std::unique_ptr<IGameEvent> Food::accept(IVisitor* ptr_visitor) { + return ptr_visitor->visit(this); +} + + +void Food::draw_into(sf::RenderWindow& window) { + m_shape.setPosition(m_ptr_room->get_position()); + //из класса Room: sf::Vector2f get_position() { return m_rectangle.getPosition(); } window.draw(m_shape); } @@ -51,5 +61,4 @@ void Enemy::action() { auto direction = static_cast<Room::Direction>(rand() % 4); m_ptr_room->get_side(direction)->enter(this); m_clock.restart(); - } \ No newline at end of file diff --git a/source/application/Drawable/Entity/IEntity.h b/source/application/Drawable/Entity/IEntity.h index f833764fda5a5fdc600c7ecafb47f35330772e3b..6a83d0970b5d9a76df4b1d088ed9c45e8ac6a69a 100644 --- a/source/application/Drawable/Entity/IEntity.h +++ b/source/application/Drawable/Entity/IEntity.h @@ -1,8 +1,18 @@ #pragma once #include "../IDrawable.h" +#include "../../Event/IGameEvent.h" class Room; +class Food; +class Enemy; + +class IVisitor { +public: + virtual std::unique_ptr<IGameEvent> visit(Food* ptr_entity) = 0; + virtual std::unique_ptr<IGameEvent> visit(Enemy* ptr_entity) = 0; + +}; class IEntity: public IPreparable { public: @@ -12,12 +22,17 @@ protected: Room* m_ptr_room; }; -class IStaticEntity : public IEntity { +class IVisitable { +public: + virtual std::unique_ptr<IGameEvent> accept(IVisitor* ptr_visitor) = 0; +}; + +class IStaticEntity : public IEntity, public IVisitable { public: virtual std::unique_ptr<IStaticEntity> clone() const = 0; }; -class IDynamicEntity: public IEntity { +class IDynamicEntity: public IEntity, public IVisitable { public: virtual void action() = 0; virtual std::unique_ptr<IDynamicEntity> clone() const = 0; @@ -30,6 +45,8 @@ public: void action() override; void prepare_for_drawing() override; std::unique_ptr<IDynamicEntity> clone() const override; + std::unique_ptr<IGameEvent> accept(IVisitor* ptr_visitor) override; + ~Enemy() override {}; private: sf::CircleShape m_shape; sf::Clock m_clock; @@ -41,6 +58,8 @@ public: void draw_into(sf::RenderWindow& window) override; void prepare_for_drawing() override; std::unique_ptr<IStaticEntity> clone() const override; + std::unique_ptr<IGameEvent> accept(IVisitor* ptr_visitor) override; + ~Food() override {}; private: sf::CircleShape m_shape; }; \ No newline at end of file diff --git a/source/application/Drawable/Entity/Pacman.cpp b/source/application/Drawable/Entity/Pacman.cpp index 5b584bbff29cae40922d0485df97830d01d7a64e..e20ab2d1667b382f7c7750d37a7e311ee6dc24cf 100644 --- a/source/application/Drawable/Entity/Pacman.cpp +++ b/source/application/Drawable/Entity/Pacman.cpp @@ -15,6 +15,16 @@ void Pacman::prepare_for_drawing() { m_shape.setPosition(m_ptr_room->get_position()); } +std::unique_ptr<IGameEvent> Pacman::visit(Food *ptr_food) { + if (ptr_food->get_location() != this->get_location()) return {}; + return std::make_unique<DeleteStaticEntity>(ptr_food); +} + +std::unique_ptr<IGameEvent> Pacman::visit(Enemy *ptr_enemy) { + if (ptr_enemy->get_location() != this->get_location()) return {}; + return std::make_unique<LostGame>(); +} + void Pacman::draw_into(sf::RenderWindow &window) { prepare_for_drawing(); window.draw(m_shape); diff --git a/source/application/Drawable/Entity/Pacman.h b/source/application/Drawable/Entity/Pacman.h index 445d516a46d152994ec0d98f352a6ac57e319bdb..8e5f5f693bb16e60581e4449327a33b80d86e7fd 100644 --- a/source/application/Drawable/Entity/Pacman.h +++ b/source/application/Drawable/Entity/Pacman.h @@ -3,12 +3,15 @@ #include "IEntity.h" #include "../Maze/Maze.h" -class Pacman : public IEntity { +class Pacman : public IEntity, public IVisitor { public: Pacman(); void move(Room::Direction direction); void prepare_for_drawing() override; void draw_into(sf::RenderWindow& window) override; + std::unique_ptr<IGameEvent> visit(Food* ptr_entity) override; + std::unique_ptr<IGameEvent> visit(Enemy* ptr_entity) override; + ~Pacman() override {}; private: sf::CircleShape m_shape; }; \ No newline at end of file diff --git a/source/application/Drawable/Maze/Maze.cpp b/source/application/Drawable/Maze/Maze.cpp index 23c2b15b8268ea0a3d44580640d4d3022fa05b75..a8aba2ec0b8bbd63d2dbdf4a22f646aee93c0684 100644 --- a/source/application/Drawable/Maze/Maze.cpp +++ b/source/application/Drawable/Maze/Maze.cpp @@ -17,10 +17,11 @@ Room::Direction Room::get_direction(IRoomSide* ptr_side) { if (m_sides[RIGHT].get() == ptr_side) return RIGHT; if (m_sides[UP].get() == ptr_side) return UP; if (m_sides[DOWN].get() == ptr_side) return DOWN; - else return INVALID; + return INVALID; } void Room::draw_into(sf::RenderWindow& window) { + window.draw(m_rectangle); for (const auto& side : m_sides) { side->draw_into(window); } diff --git a/source/application/Event/IGameEvent.cpp b/source/application/Event/IGameEvent.cpp index acd31bc397a06bb5d4dd3d688c8a48c2c71ed653..53101ecc7be613a32d84ea4a046ee13be416987d 100644 --- a/source/application/Event/IGameEvent.cpp +++ b/source/application/Event/IGameEvent.cpp @@ -5,10 +5,16 @@ void LostGame::handle(GameContext context) { context.state = GameContext::LOST; } -void DeleteStaticEntity::handle(GameContext context) { - context.static_objects.erase(m_ptr_entity); +void DeleteStaticEntity::handle(GameContext* context) { + auto it = std::find_if(context->static_objects.begin(), context->static_objects.end(), + [this](const std::unique_ptr<IStaticEntity>& ptr) { return ptr.get() == m_ptr_entity; }); + context->static_objects.erase(it); } -void WinGame::handle(GameContext context) { - context.state = GameContext::WIN; +DeleteStaticEntity::DeleteStaticEntity(IStaticEntity* ptr_entity) : + m_ptr_entity(ptr_entity) { +} + +void WinGame::handle(GameContext* context) { + context->state = GameContext::WIN; } \ No newline at end of file diff --git a/source/application/Event/IGameEvent.h b/source/application/Event/IGameEvent.h index 326eaabaa36197e0d9d49bc05be92df688b7b434..ea042600c1c63eb42a1d0930a6fd4cb3e18bf3e4 100644 --- a/source/application/Event/IGameEvent.h +++ b/source/application/Event/IGameEvent.h @@ -24,8 +24,8 @@ public: class DeleteStaticEntity : public IGameEvent { public: - DeleteStaticEntity(std::list<std::unique_ptr<IStaticEntity>>::iterator ptr_entity) : m_ptr_entity(ptr_entity) {}; - void handle(GameContext context) override; + DeleteStaticEntity(IStaticEntity* ptr_entity); + void handle(GameContext* context) override; private: - std::list<std::unique_ptr<IStaticEntity>>::iterator m_ptr_entity; + IStaticEntity* m_ptr_entity; }; diff --git a/source/application/State/GameState.cpp b/source/application/State/GameState.cpp index d87550d3831bc803f6243e7f57766a28a9b0ec5d..bab1573444a092463d3fd4b422d16a50b986b09b 100644 --- a/source/application/State/GameState.cpp +++ b/source/application/State/GameState.cpp @@ -1,7 +1,7 @@ #include "GameState.h" #include "SelectState.h" #include "../../../workdir/config.h" - +#include "../Drawable/Entity/IEntity.h" GameState::GameState(IStateManager &state_manager, const sf::VideoMode &video_mode, const std::string &window_title) : IState(state_manager), IWindowKeeper(config::GAME_VIDEO_MODE, window_title){ } @@ -23,45 +23,47 @@ void GameState::event_handling() { void GameState::process_key_pressed(sf::Keyboard::Key code) { switch (code) { case sf::Keyboard::W: - m_context_manager.save_current_context(); m_context_manager.get_current_context().pacman.move(Room::UP); break; case sf::Keyboard::S: - m_context_manager.save_current_context(); m_context_manager.get_current_context().pacman.move(Room::DOWN); break; case sf::Keyboard::A: - m_context_manager.save_current_context(); m_context_manager.get_current_context().pacman.move(Room::LEFT); break; case sf::Keyboard::D: - m_context_manager.save_current_context(); m_context_manager.get_current_context().pacman.move(Room::RIGHT); break; } +} -}; void GameState::update() { + std::vector<std::unique_ptr<IGameEvent>> game_events; if (m_context_manager.get_current_context().state != GameContext::INGAME) return; - GameContext& context = m_context_manager.get_current_context(); - for (auto& entity : context.dynamic_objects) - entity->action(); - for (auto it = context.static_objects.begin(); it != context.static_objects.end(); ++it) { - if (context.pacman.get_location() == (*it)->get_location()) { - m_events.emplace_back(std::move(std::make_unique<DeleteStaticEntity>(it))); - } + for (auto& entity_ptr : context.dynamic_objects) { + entity_ptr->action(); + IVisitor* ptr_visitor = &(context.pacman); + game_events.emplace_back(entity_ptr->accept(ptr_visitor)); + } + for (auto& static_ptr : context.static_objects) { + IVisitor* ptr_visitor = &(context.pacman); + auto ptr_event = static_ptr->accept(ptr_visitor); + if (ptr_event) + game_events.emplace_back(std::move(ptr_event)); } - for (auto it = context.dynamic_objects.begin(); it != context.dynamic_objects.end(); ++it) { if (context.pacman.get_location() == (*it)->get_location()) { - m_events.emplace_back(std::move(std::make_unique<LostGame>())); + game_events.emplace_back(std::move(std::make_unique<LostGame>())); } } - + for (int i = 0; i < game_events.size(); i++) { + game_events[i]->handle(&m_context_manager.get_current_context()); + } if (context.static_objects.empty()) { - m_events.emplace_back(std::move(std::make_unique<WinGame>())); + game_events.emplace_back(std::move(std::make_unique<WinGame>())); } + game_events.clear(); } void GameState::render() { @@ -77,13 +79,12 @@ void GameState::render() { m_window.clear(config::GAME_COLOR_BACKGROUND_WIN); } m_maze.draw_into(m_window); - for (auto& el: context.static_objects) { - el->draw_into(m_window); + context.pacman.draw_into(m_window); + for (auto& obj : context.static_objects) { + obj->draw_into(m_window); } - context.pacman.draw_into(m_window); - for (auto& el : context.dynamic_objects) el->draw_into(m_window); m_window.display(); @@ -97,6 +98,5 @@ bool GameState::do_step() { } void GameState::set_context(GameContext&& context) { - m_context_manager.save_current_context(); m_context_manager.reset(std::move(context)); } \ No newline at end of file