diff --git a/assets/background.png b/assets/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..293c583a364b338c632c542ac4fd7f5cc2574333
Binary files /dev/null and b/assets/background.png differ
diff --git a/assets/enemy.png b/assets/enemy.png
new file mode 100644
index 0000000000000000000000000000000000000000..ca29ac8f827e0414a9c13c7770ab74ab931f0f76
Binary files /dev/null and b/assets/enemy.png differ
diff --git a/assets/grusha.png b/assets/grusha.png
new file mode 100644
index 0000000000000000000000000000000000000000..803b81e1713fd23d1932abb069dadbb7ec3bea53
Binary files /dev/null and b/assets/grusha.png differ
diff --git a/assets/pacman.png b/assets/pacman.png
deleted file mode 100644
index 707389317bfe6573ce3529699370fc9efb33f929..0000000000000000000000000000000000000000
Binary files a/assets/pacman.png and /dev/null differ
diff --git a/assets/pacmanDown.png b/assets/pacmanDown.png
index 18d63290bb82e97f70b629c745b29e4f8f443d5b..6c3a8fe058f819e640bf475bcaed641a1a37615f 100644
Binary files a/assets/pacmanDown.png and b/assets/pacmanDown.png differ
diff --git a/assets/pacmanDown2.png b/assets/pacmanDown2.png
new file mode 100644
index 0000000000000000000000000000000000000000..9aca1583555f659045c63dc78c0a15ca514a3f34
Binary files /dev/null and b/assets/pacmanDown2.png differ
diff --git a/assets/pacmanLeft.png b/assets/pacmanLeft.png
index cfad9cd3a0718cf3fe8a89621fe84d0254911c10..09d1c808f0d430262c58ccaafd5abcc256625f52 100644
Binary files a/assets/pacmanLeft.png and b/assets/pacmanLeft.png differ
diff --git a/assets/pacmanLeft2.png b/assets/pacmanLeft2.png
new file mode 100644
index 0000000000000000000000000000000000000000..e0c1e59108ce3c4431884b0ba9e6d84b4e20c809
Binary files /dev/null and b/assets/pacmanLeft2.png differ
diff --git a/assets/pacmanRight.png b/assets/pacmanRight.png
index 9613050a23c47f95d5e51ed3bcf44514e85e68ad..3128093327d4f6ab3c7a6c9ecb2ba9c0077b3c72 100644
Binary files a/assets/pacmanRight.png and b/assets/pacmanRight.png differ
diff --git a/assets/pacmanRight2.png b/assets/pacmanRight2.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb0b059c58a5bec23990d9e3d7ef0a14318d79a7
Binary files /dev/null and b/assets/pacmanRight2.png differ
diff --git a/assets/pacmanUp.png b/assets/pacmanUp.png
index 62ba3dcdcaed1efe5e18561316b57dd2f7b39b95..cd3d7349be3bf7f6eae99ab5719518c4fa9b0cc3 100644
Binary files a/assets/pacmanUp.png and b/assets/pacmanUp.png differ
diff --git a/assets/pacmanUp2.png b/assets/pacmanUp2.png
new file mode 100644
index 0000000000000000000000000000000000000000..da4847a0cff9c2059ae5e01dd633571760811b3c
Binary files /dev/null and b/assets/pacmanUp2.png differ
diff --git a/config.h b/config.h
index b366881ca7f21e585e61b8e166d4eb07b812ef4d..4c90126b2ff5d8788cddea1eb366777b141940d2 100644
--- a/config.h
+++ b/config.h
@@ -8,16 +8,27 @@ namespace config {
     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.ttf";
-    const char SELECT_LEVEL_TITLE[] = "Select Level";
-    const sf::VideoMode SELECT_LEVEL_VIDEO_MODE{ 400, 600 };
+    const char SELECT_LEVEL_TITLE_WINDOW[] = "Settings";
+    const char SELECT_LEVEL_TITLE[] = "Select Level:";
+    const char SELECT_LEVEL_TITLE_PLAYER[] = "Select Player:";
+    const char SELECT_THEME[] = "Select Theme:";
+    const char BUTTON_THEME_WHITE[] = "Theme: White";
+    const char BUTTON_THEME_BLACK[] = "Theme: Black";
+    const sf::VideoMode SELECT_LEVEL_VIDEO_MODE{ 1138, 620 };
     const std::vector<std::string> BUTTON_TEXT = {"Easy","Medium", "Hard", "Exit"};
     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{ 880, 620 };
+    const sf::VideoMode GAME_VIDEO_MODE{ 1138, 620 };
+    const float MENU_WIDTH = GAME_VIDEO_MODE.width / 4;
+    const float SCREEN_HEIGHT = GAME_VIDEO_MODE.height;
+    const float GAME_WIDTH = GAME_VIDEO_MODE.width - MENU_WIDTH;
+    const char BUTTON_START_GAME[] = "Start Game";
     const char EASY_GAME_TITLE[] = "Level: Easy";
+    const char ONE_PLAYER_GAME_TITLE[] = "Player: One";
+    const char TWO_PLAYER_GAME_TITLE[] = "Player: Two";
     const char MEDIUM_GAME_TITLE[] = "Level: Medium";
     const char HARD_GAME_TITLE[] = "Level: Hard";
     const float EASY_GAME_ENEMY_RATIO = 0.0f;
diff --git a/source/application/BobBuilder/BobBuilderDirector.cpp b/source/application/BobBuilder/BobBuilderDirector.cpp
index 09d49f1591d56ffe9f4e455a9e2560f1b49524e8..9f1d9eae701d7f381df697c67d419d5b51bc38c1 100644
--- a/source/application/BobBuilder/BobBuilderDirector.cpp
+++ b/source/application/BobBuilder/BobBuilderDirector.cpp
@@ -12,11 +12,11 @@ GameBuilderDirector::GameBuilderDirector(std::unique_ptr<IGameBuilder> &&ptr_bui
         m_ptr_builder(std::move(ptr_builder)) {
 }
 
-std::unique_ptr<GameState> GameBuilderDirector::build(IStateManager &state_manager) {
+std::unique_ptr<GameState> GameBuilderDirector::build(IStateManager &state_manager, int players) {
     m_ptr_builder->create_rooms();
     m_ptr_builder->set_rooms_sides();
-    m_ptr_builder->create_context(m_dynamic_object_ratio);
+    m_ptr_builder->create_context(m_dynamic_object_ratio, players);
     m_ptr_builder->create_state(state_manager, m_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/application/BobBuilder/BobBuilderDirector.h b/source/application/BobBuilder/BobBuilderDirector.h
index f52a9998652240fa41c20cf149c4deacd930e2c1..6a963898658e84242ec93f9ecd606502431a8228 100644
--- a/source/application/BobBuilder/BobBuilderDirector.h
+++ b/source/application/BobBuilder/BobBuilderDirector.h
@@ -4,7 +4,7 @@
 class GameBuilderDirector {
 public:
     GameBuilderDirector(std::unique_ptr<IGameBuilder>&& ptr_builder, sf::VideoMode mode, std::string  window_title, float dynamic_objects_ratio);
-    std::unique_ptr<GameState> build(IStateManager& state_manager);
+    std::unique_ptr<GameState> build(IStateManager& state_manager, int players);
 
 private:
     std::string m_window_title;
diff --git a/source/application/BobBuilder/GameBuilders.cpp b/source/application/BobBuilder/GameBuilders.cpp
index 9961971cb71888c60b52e7eab78e3dfbcdbf56b2..e38d03cb56a274d630111cdf924450e47f4739c5 100644
--- a/source/application/BobBuilder/GameBuilders.cpp
+++ b/source/application/BobBuilder/GameBuilders.cpp
@@ -4,22 +4,23 @@ 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) {
+void CommonBuilder::create_context(float dynamic_objects_ratio, int players) {
     std::vector<Room*> empty_rooms_buffer;
     for (auto& row : m_rooms)
         for (auto& room : row)
             if (room != nullptr)
                 empty_rooms_buffer.emplace_back(room);
-
-    float id = std::rand() % empty_rooms_buffer.size();
     //в рандомное место располагаем пакмана
+    float id = std::rand() % empty_rooms_buffer.size();
     m_context.pacman.set_location(empty_rooms_buffer[id]);
     auto it = std::next(empty_rooms_buffer.begin(), id);
     empty_rooms_buffer.erase(it);
-    float id2 = std::rand() % empty_rooms_buffer.size();
-    m_context.pacman2.set_location(empty_rooms_buffer[id2]);
-    auto it2 = std::next(empty_rooms_buffer.begin(), id2);
-    empty_rooms_buffer.erase(it2);
+    if (players == 2) {
+        float id2 = std::rand() % empty_rooms_buffer.size();
+        m_context.pacman2.set_location(empty_rooms_buffer[id2]);
+        auto it2 = std::next(empty_rooms_buffer.begin(), id2);
+        empty_rooms_buffer.erase(it2);
+    }
 
     //располагаем врагов
     size_t rooms_row = static_cast<size_t>(m_width / m_room_size);
@@ -62,14 +63,14 @@ std::unique_ptr<GameState> CommonBuilder::get_game() {
 
 void SimpleBuilder::create_rooms() {
     size_t rows = m_height / m_room_size;
-    size_t cols = m_width / m_room_size;
+    size_t cols = config::GAME_WIDTH / m_room_size;
     int room_size = static_cast<int>(m_room_size);
-    sf::Vector2f left_pos = sf::Vector2f{ (m_width - m_room_size * cols + m_room_size)/2, (m_height - m_room_size * rows + m_room_size)/2};
+    sf::Vector2f left_pos = sf::Vector2f{ config::MENU_WIDTH, (m_height - m_room_size * rows + m_room_size)/2};
     for (int row = 0; row < rows * room_size; row += room_size) {
         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({col + left_pos.x, row + left_pos.y});
+            room->set_position({config::MENU_WIDTH + col, row + left_pos.y});
             row_vec.emplace_back(room);
         }
         m_rooms.emplace_back(std::move(row_vec));
@@ -78,7 +79,7 @@ void SimpleBuilder::create_rooms() {
 
 void SimpleBuilder::set_rooms_sides() {
     for (size_t i = 0; i < m_rooms.size(); i++) {
-        for (size_t j = 0; j < m_rooms.begin()->size(); j++) {
+        for (size_t j = 0; j < m_rooms[i].size(); j++) {
             if (i == 0) {
                 auto up_wall = std::make_shared<Wall>(*m_rooms[i][j]);
                 m_rooms[i][j]->set_side(Room::UP, std::move(up_wall));
@@ -112,10 +113,10 @@ void SimpleBuilder::set_rooms_sides() {
 
 void ComplexBuilder::create_rooms() {
     size_t room_quantity_row = (m_height / m_room_size);
-    size_t room_quantity_col = (m_width / m_room_size);
+    size_t room_quantity_col = config::GAME_WIDTH / m_room_size;
 
     int room_size = static_cast<int>(m_room_size);
-    auto starting_point = sf::Vector2f{(m_width - m_room_size*room_quantity_col)/2 + m_room_size/2, (m_height - m_room_size*room_quantity_row)/2 + + m_room_size/2};
+    auto starting_point = sf::Vector2f{config::MENU_WIDTH, (m_height - m_room_size*room_quantity_row)/2 + + m_room_size/2};
 
     for (int row = 0; row < room_quantity_row * room_size; row += room_size) {
         std::vector<Room*> vector_row;
diff --git a/source/application/BobBuilder/GameBuilders.h b/source/application/BobBuilder/GameBuilders.h
index cb4bdeffa7e9237f20aae888c3ce3bc07addeb62..fea5da2576c67322d23d5c4a96032b3c3d003c4b 100644
--- a/source/application/BobBuilder/GameBuilders.h
+++ b/source/application/BobBuilder/GameBuilders.h
@@ -6,7 +6,7 @@
 class CommonBuilder : public IGameBuilder {
 public:
     CommonBuilder(float width, float height, float room_size);
-    void create_context(float dynamic_objects_ratio) override;
+    void create_context(float dynamic_objects_ratio, int players) override;
     void create_state(IStateManager& state_manager, const sf::VideoMode& mode, const std::string& window_title) override;
     void set_all_to_state() override;
     std::unique_ptr<GameState> get_game() override;
diff --git a/source/application/BobBuilder/IGameBuilder.h b/source/application/BobBuilder/IGameBuilder.h
index 4f7b9d6b3fd027d83f3bc22ade5e6dcfeea4f965..84ac8ca9a968ea0ae22a4a7d032190946a95852f 100644
--- a/source/application/BobBuilder/IGameBuilder.h
+++ b/source/application/BobBuilder/IGameBuilder.h
@@ -6,7 +6,7 @@ class IGameBuilder {
 public:
     virtual void create_rooms() = 0;
     virtual void set_rooms_sides() = 0;
-    virtual void create_context(float dynamic_objects_ratio) = 0;
+    virtual void create_context(float dynamic_objects_ratio, int players) = 0;
     virtual void create_state(IStateManager& state_manager, const sf::VideoMode& mode, const std::string& window_title) = 0;
     virtual void set_all_to_state() = 0;
     virtual std::unique_ptr<GameState> get_game() = 0;
diff --git a/source/application/Context/Context.cpp b/source/application/Context/Context.cpp
index a1c3ab6078e4489df3c1ebb98fd52c4e4afe6e09..585b52c618d44546323375bfc6bb203f890c6e34 100644
--- a/source/application/Context/Context.cpp
+++ b/source/application/Context/Context.cpp
@@ -1,5 +1,12 @@
 #include "Context.h"
 
+GameContext::GameContext()
+        : pacman(&PacmanTexture::instance()),
+          pacman2(&PacmanTexture2::instance()),
+          static_objects(),
+          dynamic_objects()
+{}
+
 GameContext GameContext::clone() {
     GameContext context;
     context.pacman = pacman;
diff --git a/source/application/Context/Context.h b/source/application/Context/Context.h
index b6269d8d1a668a346b98c53f85b9f394565d1a66..a9a024f4143c6d4fce4155a52e5bd4b355c90d02 100644
--- a/source/application/Context/Context.h
+++ b/source/application/Context/Context.h
@@ -5,9 +5,11 @@
 #include <list>
 
 struct GameContext {
+    GameContext();
     enum State { INGAME, WIN, LOST } state = INGAME;
     std::list<std::unique_ptr<IDynamicEntity>> dynamic_objects;
     std::list<std::unique_ptr<IStaticEntity>> static_objects;
+
     Pacman pacman;
     Pacman pacman2;
     GameContext clone();
diff --git a/source/application/Drawable/DrawMenu/Button/Button.cpp b/source/application/Drawable/DrawMenu/Button/Button.cpp
index 1f3c0b05b46b5f30e05a6a5668922f1b2fd688d5..d7d5c76206dfb68609de62987a1e3b95a6e3c00c 100644
--- a/source/application/Drawable/DrawMenu/Button/Button.cpp
+++ b/source/application/Drawable/DrawMenu/Button/Button.cpp
@@ -1,27 +1,33 @@
 #include "Button.h"
 #include "../../../../../config.h"
 #include "../Font/Font.h"
+#include "../../../State/ThemeManager.h"
 
 Button::Button(sf::Vector2f pos, sf::Vector2f button_size,
-                 const std::string& text, size_t font_size,
-                 std::unique_ptr<ISelectCommand> ptr_command) {
+               const std::string& text, size_t font_size,
+               std::unique_ptr<ISelectCommand> ptr_command) {
+
     m_rectangle.setSize(button_size);
     m_rectangle.setPosition(pos);
-    m_rectangle.setFillColor(config::BUTTON_COLOR_FILL);
-    m_rectangle.setOutlineColor(config::BUTTON_COLOR_FRAME);
-    m_rectangle.setOutlineThickness(config::BUTTON_FRAME_THICKNESS);
+    m_rectangle.setOutlineColor(ThemeManager::Instance().getButtonOutlineColor());
+    m_rectangle.setOutlineThickness(2.f);
+
     m_text = sf::Text(text, MyFont::Instance(), font_size);
-    m_text.setFillColor(config::BUTTON_COLOR_TEXT);
-    m_text.setPosition(pos);
+    m_text.setFillColor(ThemeManager::Instance().getButtonTextColor());
+    sf::FloatRect textRect = m_text.getLocalBounds();
+    m_text.setPosition(pos.x + (button_size.x - textRect.width) / 2.0f - textRect.left, pos.y + (button_size.y - textRect.height) / 2.0f - textRect.top);
+    m_rectangle.setFillColor(ThemeManager::Instance().getButtonFillColor());
     m_ptr_command = std::move(ptr_command);
 }
 
 void Button::select() {
-    m_rectangle.setFillColor(config::BUTTON_COLOR_SELECTION);
+    m_rectangle.setFillColor(ThemeManager::Instance().getButtonSelectionColor());
 }
+
 void Button::unselect() {
-    m_rectangle.setFillColor(config::BUTTON_COLOR_FILL);
+    m_rectangle.setFillColor(ThemeManager::Instance().getButtonFillColor());
 }
+
 bool Button::is_selected() const noexcept {
     return m_is_selected;
 }
@@ -35,4 +41,32 @@ void Button::push() {
 void Button::draw_into(sf::RenderWindow& window)  {
     window.draw(m_rectangle);
     window.draw(m_text);
+}
+
+void ChooseButton::draw_into(sf::RenderWindow &window) {
+    window.draw(m_out_circle);
+    if (m_is_selected) window.draw(m_in_circle);
+    window.draw(m_text);
+}
+
+bool ChooseButton::contains(sf::Vector2f point) const {
+    return m_out_circle.getGlobalBounds().contains(point) || m_text.getGlobalBounds().contains(point);
+}
+
+ChooseButton::ChooseButton(sf::Vector2f pos, const std::string &text, size_t font_size) {
+
+    m_out_circle.setRadius(10.f);
+    m_out_circle.setOutlineThickness(1.f);
+    m_out_circle.setOutlineColor(ThemeManager::Instance().getButtonOutlineColor());
+    m_out_circle.setFillColor(sf::Color::Transparent);
+    m_out_circle.setPosition(pos);
+
+    m_in_circle.setRadius(6.f);
+    m_in_circle.setFillColor(sf::Color::Blue);
+    m_in_circle.setPosition(pos.x + 4.f, pos.y + 4.f);
+    m_in_circle.setOutlineThickness(0);
+
+    m_text = sf::Text(text, MyFont::Instance(), font_size);
+    m_text.setFillColor(ThemeManager::Instance().getButtonTextColor());
+    m_text.setPosition(pos.x + 40.f, pos.y - 5.f);
 }
\ No newline at end of file
diff --git a/source/application/Drawable/DrawMenu/Button/Button.h b/source/application/Drawable/DrawMenu/Button/Button.h
index eb39b81802f95bb3e16aa4443b5b3b60dc24394a..a580dd8ee1738d65e9b626c5079412a8bebe1d9d 100644
--- a/source/application/Drawable/DrawMenu/Button/Button.h
+++ b/source/application/Drawable/DrawMenu/Button/Button.h
@@ -23,4 +23,19 @@ private:
     bool m_is_selected = false;
     sf::RectangleShape m_rectangle;
     std::unique_ptr<ISelectCommand> m_ptr_command;
+};
+
+class ChooseButton : public IDrawable {
+public:
+    ChooseButton(sf::Vector2f pos, const std::string& text, size_t font_size);
+    void select() { m_is_selected = true; }
+    void unselect() { m_is_selected = false; }
+    bool is_selected() const noexcept { return m_is_selected; }
+    bool contains(sf::Vector2f point) const;
+    void draw_into(sf::RenderWindow& window) override;
+private:
+    sf::Text m_text;
+    bool m_is_selected = false;
+    sf::CircleShape m_out_circle;
+    sf::CircleShape m_in_circle;
 };
\ No newline at end of file
diff --git a/source/application/Drawable/DrawMenu/Menu/Menu.cpp b/source/application/Drawable/DrawMenu/Menu/Menu.cpp
index 931444dc56f3cd1ceb19d2e28c166268b74d9e38..34cdbf24b11428b9a21cb5602f64403daab10067 100644
--- a/source/application/Drawable/DrawMenu/Menu/Menu.cpp
+++ b/source/application/Drawable/DrawMenu/Menu/Menu.cpp
@@ -1,56 +1,167 @@
 #include "Menu.h"
 #include "../../../../../config.h"
 #include "../../../BobBuilder/GameBuilders.h"
+#include "../../../State/ThemeManager.h"
+#include "../Font/Font.h"
 #include <memory>
 
-Menu::Menu(IStateManager& state_manager) {
-    float delta = 20;
-    sf::Vector2f starting_position(80,5);
-    auto easy_director = std::make_unique<GameBuilderDirector>(
+Menu::Menu(IStateManager& state_manager) : m_state_manager(state_manager) {
+    m_directors.push_back(std::make_unique<GameBuilderDirector>(
             std::make_unique<SimpleBuilder>(
                     config::GAME_VIDEO_MODE.width, config::GAME_VIDEO_MODE.height,
                     config::ROOM_SIZE),
             config::GAME_VIDEO_MODE,
             config::EASY_GAME_TITLE,
-            config::EASY_GAME_ENEMY_RATIO);
-    auto medium_director = std::make_unique<GameBuilderDirector>(
+            config::EASY_GAME_ENEMY_RATIO));
+    m_directors.push_back(std::make_unique<GameBuilderDirector>(
             std::make_unique<SimpleBuilder>(
                     config::GAME_VIDEO_MODE.width, config::GAME_VIDEO_MODE.height,
                     config::ROOM_SIZE),
             config::GAME_VIDEO_MODE,
             config::MEDIUM_GAME_TITLE,
-            config::MEDIUM_GAME_ENEMY_RATIO);
-    auto hard_director = std::make_unique<GameBuilderDirector>(
+            config::MEDIUM_GAME_ENEMY_RATIO));
+    m_directors.push_back(std::make_unique<GameBuilderDirector>(
             std::make_unique<ComplexBuilder>(
                     config::GAME_VIDEO_MODE.width, config::GAME_VIDEO_MODE.height,
                     config::ROOM_SIZE),
             config::GAME_VIDEO_MODE,
             config::HARD_GAME_TITLE,
-            config::HARD_GAME_ENEMY_RATIO);
+            config::HARD_GAME_ENEMY_RATIO));
 
-    auto easy_command = std::make_unique<GameCommand>(state_manager, std::move(easy_director));
-    auto medium_command = std::make_unique<GameCommand>(state_manager, std::move(medium_director));
-    auto hard_command = std::make_unique<GameCommand>(state_manager, std::move(hard_director));
-    auto exit_command = std::make_unique<ExitCommand>(state_manager);
+    m_choose_button.push_back(std::make_unique<ChooseButton>(sf::Vector2f(400.f, 130.f), config::EASY_GAME_TITLE, 24));
+    m_choose_button.push_back(std::make_unique<ChooseButton>(sf::Vector2f(400.f, 170.f), config::MEDIUM_GAME_TITLE, 24));
+    m_choose_button.push_back(std::make_unique<ChooseButton>(sf::Vector2f(400.f, 210.f), config::HARD_GAME_TITLE, 24));
 
-    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 1 * config::BUTTON_SIZE.y + 0 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_EASY, config::BUTTON_FONT_SIZE , std::move(easy_command)));
-    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 2 * config::BUTTON_SIZE.y + 1 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_MEDIUM, config::BUTTON_FONT_SIZE , std::move(medium_command)));
-    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 3 * config::BUTTON_SIZE.y + 2 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_HARD, config::BUTTON_FONT_SIZE , std::move(hard_command)));
-    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 4 * config::BUTTON_SIZE.y + 3 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_EXIT, config::BUTTON_FONT_SIZE, std::move(exit_command)));
-}
+    m_choose_button_players.push_back(std::make_unique<ChooseButton>(sf::Vector2f(400.f, 255.f), config::ONE_PLAYER_GAME_TITLE, 24));
+    m_choose_button_players.push_back(std::make_unique<ChooseButton>(sf::Vector2f(400.f, 295.f), config::TWO_PLAYER_GAME_TITLE, 24));
 
-void Menu::draw_into(sf::RenderWindow &window) {
-    //@todo change to const Button&
-    for (auto& ptr_button : m_buttons)
-        ptr_button->draw_into(window);
+    m_choose_button_theme.push_back(std::make_unique<ChooseButton>(sf::Vector2f(400.f, 343.f), config::BUTTON_THEME_WHITE, 24));
+    m_choose_button_theme.push_back(std::make_unique<ChooseButton>(sf::Vector2f(400.f, 383.f), config::BUTTON_THEME_BLACK, 24));
+    m_choose_button_theme[m_selected_theme]->select();
+    m_exit_button = std::make_unique<Button>(sf::Vector2f(900.f, 500.f), sf::Vector2f(150.f, 50.f), config::BUTTON_TEXT_EXIT, 24, std::make_unique<ExitCommand>(state_manager));
+    m_proceed_button = std::make_unique<Button>(sf::Vector2f(450.f, 500.f), sf::Vector2f(150.f, 50.f), config::BUTTON_START_GAME, 24,nullptr);
 }
 
-void Menu::process_mouse(const sf::Vector2f pos, bool is_pressed) {
-    for (auto& ptr_button : m_buttons) {
-        if (ptr_button->is_position_in(pos)) {
-            ptr_button->select();
-            if (is_pressed) ptr_button->push();
+void Menu::process_mouse(sf::Vector2f pos, bool is_pressed) {
+    if (is_pressed) {
+        ///> выбор уровня
+        for (size_t i = 0; i < m_choose_button.size(); i++) {
+            if (m_choose_button[i]->contains(pos)) {
+                for (auto& button : m_choose_button)
+                    button->unselect();
+                m_choose_button[i]->select();
+                m_selected_level = i;
+            }
+        }
+        ///> exit
+        if (m_exit_button->is_position_in(pos))
+            m_exit_button->push();
+        ///> выбор количества игроков
+        for (int i = 0; i < m_choose_button_players.size(); i++) {
+            if (m_choose_button_players[i]->contains(pos)) {
+                for (auto& button : m_choose_button_players)
+                    button->unselect();
+                m_choose_button_players[i]->select();
+                m_selected_players = i;
+            }
+        }
+        ///> выбор темы приложения
+        for (int i = 0; i < m_choose_button_theme.size(); i++) {
+            if (m_choose_button_theme[i]->contains(pos)) {
+                for (auto& button : m_choose_button_theme)
+                    button->unselect();
+                m_choose_button_theme[i]->select();
+                m_selected_theme = i;
+                if  (i == 0)
+                    ThemeManager::Instance().set_theme(ThemeManager::Theme::LIGHT);
+                else
+                    ThemeManager::Instance().set_theme(ThemeManager::Theme::DARK);
+                break;
+            }
+        }
+        ///> создание команды при нажатии на go to game
+        if (m_selected_level >= 0 && m_proceed_button->is_position_in(pos)) {
+            auto command = std::make_unique<GameCommand>(m_state_manager, m_directors[m_selected_level], m_selected_players +1);
+            command->execute();
         }
-        else ptr_button->unselect();
     }
-}
\ No newline at end of file
+}
+
+void Menu::draw_into(sf::RenderWindow &window) {
+    sf::Text title(config::SELECT_LEVEL_TITLE_WINDOW, MyFont::Instance(), 40);
+    title.setPosition(window.getSize().x/2.f-100.f, 50.f);
+    title.setFillColor(ThemeManager::Instance().getTitleTextColor());
+    window.draw(title);
+    sf::Text title2(config::SELECT_LEVEL_TITLE, MyFont::Instance(), 30);
+    title2.setPosition(window.getSize().x/2.f-350.f, 120.f);
+    title2.setFillColor(ThemeManager::Instance().getTitleTextColor());
+    window.draw(title2);
+    for (auto& button : m_choose_button)
+        button->draw_into(window);
+    sf::Text title3(config::SELECT_LEVEL_TITLE_PLAYER, MyFont::Instance(), 30);
+    title3.setPosition(window.getSize().x/2.f-350.f, 240.f);
+    title3.setFillColor(ThemeManager::Instance().getTitleTextColor());
+    window.draw(title3);
+    for (auto& button : m_choose_button_players)
+        button->draw_into(window);
+    sf::Text title4(config::SELECT_THEME, MyFont::Instance(), 30);
+    title4.setPosition(window.getSize().x/2.f-350.f, 330.f);
+    title4.setFillColor(ThemeManager::Instance().getTitleTextColor());
+    window.draw(title4);
+    for (auto& button : m_choose_button_theme)
+        button->draw_into(window);
+    m_proceed_button->draw_into(window);
+    m_exit_button->draw_into(window);
+}
+
+//Menu::Menu(IStateManager& state_manager) {
+//    float delta = 20;
+//    sf::Vector2f starting_position(80,5);
+//    auto easy_director = std::make_unique<GameBuilderDirector>(
+//            std::make_unique<SimpleBuilder>(
+//                    config::GAME_VIDEO_MODE.width, config::GAME_VIDEO_MODE.height,
+//                    config::ROOM_SIZE),
+//            config::GAME_VIDEO_MODE,
+//            config::EASY_GAME_TITLE,
+//            config::EASY_GAME_ENEMY_RATIO);
+//    auto medium_director = std::make_unique<GameBuilderDirector>(
+//            std::make_unique<SimpleBuilder>(
+//                    config::GAME_VIDEO_MODE.width, config::GAME_VIDEO_MODE.height,
+//                    config::ROOM_SIZE),
+//            config::GAME_VIDEO_MODE,
+//            config::MEDIUM_GAME_TITLE,
+//            config::MEDIUM_GAME_ENEMY_RATIO);
+//    auto hard_director = std::make_unique<GameBuilderDirector>(
+//            std::make_unique<ComplexBuilder>(
+//                    config::GAME_VIDEO_MODE.width, config::GAME_VIDEO_MODE.height,
+//                    config::ROOM_SIZE),
+//            config::GAME_VIDEO_MODE,
+//            config::HARD_GAME_TITLE,
+//            config::HARD_GAME_ENEMY_RATIO);
+//
+//    auto easy_command = std::make_unique<GameCommand>(state_manager, std::move(easy_director));
+//    auto medium_command = std::make_unique<GameCommand>(state_manager, std::move(medium_director));
+//    auto hard_command = std::make_unique<GameCommand>(state_manager, std::move(hard_director));
+//    auto exit_command = std::make_unique<ExitCommand>(state_manager);
+//
+//    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 1 * config::BUTTON_SIZE.y + 0 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_EASY, config::BUTTON_FONT_SIZE , std::move(easy_command)));
+//    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 2 * config::BUTTON_SIZE.y + 1 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_MEDIUM, config::BUTTON_FONT_SIZE , std::move(medium_command)));
+//    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 3 * config::BUTTON_SIZE.y + 2 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_HARD, config::BUTTON_FONT_SIZE , std::move(hard_command)));
+//    m_buttons.emplace_back(std::make_unique<Button>(sf::Vector2f{starting_position.x, starting_position.y + 4 * config::BUTTON_SIZE.y + 3 * delta}, config::BUTTON_SIZE, config::BUTTON_TEXT_EXIT, config::BUTTON_FONT_SIZE, std::move(exit_command)));
+//}
+
+//void Menu::draw_into(sf::RenderWindow &window) {
+//    //@todo change to const Button&
+//    for (auto& ptr_button : m_buttons)
+//        ptr_button->draw_into(window);
+//}
+
+//void Menu::process_mouse(sf::Vector2f pos, bool is_pressed) {
+//    for (auto& ptr_button : m_buttons) {
+//        if (ptr_button->is_position_in(pos)) {
+//            ptr_button->select();
+//            if (is_pressed) ptr_button->push();
+//        }
+//        else ptr_button->unselect();
+//    }
+//}
\ No newline at end of file
diff --git a/source/application/Drawable/DrawMenu/Menu/Menu.h b/source/application/Drawable/DrawMenu/Menu/Menu.h
index 9cf8ced9c80f6ba38bc0a87f38898f970bf6cddc..8053a54dadc0b43206d8fecbcf65c3e71484bc42 100644
--- a/source/application/Drawable/DrawMenu/Menu/Menu.h
+++ b/source/application/Drawable/DrawMenu/Menu/Menu.h
@@ -8,9 +8,20 @@ class Menu : public IDrawable {
 public:
     Menu(IStateManager& state_manager);
     void draw_into(sf::RenderWindow& window) override;
-    void process_mouse(const sf::Vector2f pos, bool is_pressed);
+    void process_mouse(sf::Vector2f pos, bool is_pressed);
 
 private:
     sf::RectangleShape m_shape;
+    std::vector<std::unique_ptr<ChooseButton>> m_choose_button;
+    std::vector<std::unique_ptr<ChooseButton>> m_choose_button_players;
+    std::vector<std::unique_ptr<ChooseButton>> m_choose_button_theme;
+    std::unique_ptr<Button> m_proceed_button;
+    std::unique_ptr<Button> m_exit_button;
+    std::vector<std::unique_ptr<GameBuilderDirector>> m_directors;
+    int m_selected_level = -1;
+    int m_selected_players = -1;
+    int m_selected_theme = 0;
+    IStateManager& m_state_manager;
     std::vector<std::unique_ptr<Button>> m_buttons; //@todo vector changes to array<Button, 4>
+
 };
\ No newline at end of file
diff --git a/source/application/Drawable/Entity/MyTexture.cpp b/source/application/Drawable/Entity/MyTexture.cpp
index 991d4a3229da6d03763eb1072781e6c83b21c7c1..5872eec0669ffa8e9b45c23cda6248d38ac475b3 100644
--- a/source/application/Drawable/Entity/MyTexture.cpp
+++ b/source/application/Drawable/Entity/MyTexture.cpp
@@ -1,5 +1,4 @@
 #include "MyTexture.h"
-
 PacmanTexture::PacmanTexture() {
     if (!m_texture_up.loadFromFile(std::string(ASSETS_PATH) + "pacmanUp.png"))
         throw std::runtime_error("Can't added Texture for Pacman");
@@ -11,6 +10,16 @@ PacmanTexture::PacmanTexture() {
         throw std::runtime_error("Can't added Texture for Pacman");
 }
 
+PacmanTexture2::PacmanTexture2() {
+    if (!m_texture_up.loadFromFile(std::string(ASSETS_PATH) + "pacmanUp2.png"))
+        throw std::runtime_error("Can't added Texture for Pacman");
+    if (!m_texture_down.loadFromFile(std::string(ASSETS_PATH) + "pacmanDown2.png"))
+        throw std::runtime_error("Can't added Texture for Pacman");
+    if (!m_texture_right.loadFromFile(std::string(ASSETS_PATH) + "pacmanRight2.png"))
+        throw std::runtime_error("Can't added Texture for Pacman");
+    if (!m_texture_left.loadFromFile(std::string(ASSETS_PATH) + "pacmanLeft2.png"))
+        throw std::runtime_error("Can't added Texture for Pacman");
+}
 //в зависимости от направления - разные текстуры
 sf::Texture& PacmanTexture::get_texture() {
     switch (m_direction) {
@@ -25,6 +34,19 @@ sf::Texture& PacmanTexture::get_texture() {
     }
 }
 
+sf::Texture& PacmanTexture2::get_texture() {
+    switch (m_direction) {
+        case Direction::UP:
+            return m_texture_left;
+        case Direction::DOWN:
+            return m_texture_right;
+        case Direction::RIGHT:
+            return m_texture_up;
+        case Direction::LEFT:
+            return m_texture_down;
+    }
+}
+
 FoodTexture::FoodTexture() {
     if (!m_texture_food.loadFromFile(std::string(ASSETS_PATH) + "grusha.png"))
         throw std::runtime_error("Can't added Texture for food");
@@ -33,3 +55,7 @@ FoodTexture::FoodTexture() {
 EnemyTexture::EnemyTexture() {
     m_texture_enemy.loadFromFile(std::string(ASSETS_PATH) + "enemy.png");
 }
+
+BackgroundTexture::BackgroundTexture() {
+    m_texture_background.loadFromFile(std::string(ASSETS_PATH) + "background.png");
+}
\ No newline at end of file
diff --git a/source/application/Drawable/Entity/MyTexture.h b/source/application/Drawable/Entity/MyTexture.h
index 185e0cb92c1ce0d9558142be60991195f0f88b55..d1f9f5364599bd8142b0b030f63428b2f9c2af1f 100644
--- a/source/application/Drawable/Entity/MyTexture.h
+++ b/source/application/Drawable/Entity/MyTexture.h
@@ -24,6 +24,15 @@ private:
     sf::Texture m_texture_up, m_texture_down, m_texture_right, m_texture_left;
 };
 
+class PacmanTexture2 : public MyTexture {
+public:
+    static PacmanTexture2& instance() { static PacmanTexture2 instance; return instance; }
+    sf::Texture& get_texture() override;
+private:
+    PacmanTexture2();
+    sf::Texture m_texture_up, m_texture_down, m_texture_right, m_texture_left;
+};
+
 //texture for Food
 class FoodTexture : public MyTexture {
 public:
@@ -43,3 +52,12 @@ private:
     EnemyTexture();
     sf::Texture m_texture_enemy;
 };
+
+class BackgroundTexture : public MyTexture {
+public:
+    static BackgroundTexture& instance() { static BackgroundTexture instance; return instance; }
+    sf::Texture& get_texture() override { return m_texture_background; }
+private:
+    BackgroundTexture();
+    sf::Texture m_texture_background;
+};
diff --git a/source/application/Drawable/Entity/Pacman.cpp b/source/application/Drawable/Entity/Pacman.cpp
index 4a85c71c4cd1f1d45f6f2b37ac2637cc1c57062d..7bf09edbe16729d89f712a502210f51b9bea9d2a 100644
--- a/source/application/Drawable/Entity/Pacman.cpp
+++ b/source/application/Drawable/Entity/Pacman.cpp
@@ -1,9 +1,7 @@
 #include "Pacman.h"
 #include "../../../../config.h"
 
-Pacman::Pacman() {
-    set_texture(&PacmanTexture::instance());
-}
+Pacman::Pacman(MyTexture* texture) : m_ptr_texture(texture) {}
 
 void Pacman::move(Room::Direction direction) {
     m_ptr_room->get_side(direction)->enter(this);
diff --git a/source/application/Drawable/Entity/Pacman.h b/source/application/Drawable/Entity/Pacman.h
index 1b041ffc472d7d188eb8b3db363ce33303361f89..9e06084a82719a64451a40a569f68ab8f3bc387e 100644
--- a/source/application/Drawable/Entity/Pacman.h
+++ b/source/application/Drawable/Entity/Pacman.h
@@ -6,7 +6,7 @@
 
 class Pacman : public IEntity, public IVisitor {
 public:
-    Pacman();
+    Pacman(MyTexture* texture);
     void move(Room::Direction direction);
     void prepare_for_drawing() override;
     void set_texture(MyTexture* ptr_texture) { m_ptr_texture = ptr_texture; }
diff --git a/source/application/Drawable/Maze/IObserver.cpp b/source/application/Drawable/Maze/IObserver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bcc8581149d9e31e5dbc5bff62d1f2385aabf151
--- /dev/null
+++ b/source/application/Drawable/Maze/IObserver.cpp
@@ -0,0 +1,12 @@
+
+#include "../../Event/IGameEvent.h"
+#include "IObserver.h"
+
+void ScoreCount::on_notify(const IGameEvent& event) {
+    if (const auto* food_event = dynamic_cast<const DeleteStaticEntity*>(&event)) {
+        if (m_player == 1)
+            ++m_player_one_food;
+        else
+            ++m_player_two_food;
+    }
+}
\ No newline at end of file
diff --git a/source/application/Drawable/Maze/IObserver.h b/source/application/Drawable/Maze/IObserver.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9102da8dcffa86b60042b008ab0f412982c97c4
--- /dev/null
+++ b/source/application/Drawable/Maze/IObserver.h
@@ -0,0 +1,23 @@
+#pragma once
+
+class IGameEvent;
+
+class IObserver {
+public:
+    virtual ~IObserver() = default;
+    virtual void on_notify(const IGameEvent& event) = 0;
+};
+
+
+class ScoreCount : public IObserver {
+public:
+    ScoreCount(int player) : m_player(player) {}
+    void on_notify(const IGameEvent& event) override;
+    int get_player_one() const {return m_player_one_food; }
+    int get_player_two() const {return m_player_two_food; }
+
+private:
+    int m_player;
+    int m_player_one_food{0};
+    int m_player_two_food{0};
+};
\ No newline at end of file
diff --git a/source/application/Drawable/Maze/Maze.cpp b/source/application/Drawable/Maze/Maze.cpp
index 37e9b98e126c56b9173f03e2246344b7a5c92265..7da8a48e15a5add932eed11517beaedc25e671e5 100644
--- a/source/application/Drawable/Maze/Maze.cpp
+++ b/source/application/Drawable/Maze/Maze.cpp
@@ -1,9 +1,10 @@
 #include "Maze.h"
 #include "../../../../config.h"
+#include "../../State/ThemeManager.h"
 
 Room::Room(float size) : m_rectangle({size, size}){
     m_rectangle.setOrigin(m_rectangle.getSize().x/2,m_rectangle.getSize().y/2 );
-    m_rectangle.setFillColor(config::GAME_COLOR_ROOM);
+    m_rectangle.setFillColor(ThemeManager::Instance().getRoomColor());
 }
 
 void Room::set_side(Direction side, std::shared_ptr<IRoomSide> ptr_side) {
@@ -44,20 +45,20 @@ void Wall::prepare_for_drawing() {
 
     switch (direct) {
         case Room::LEFT:
-            m_line[0] = sf::Vertex(corners[0], config::GAME_COLOR_WALL);
-            m_line[1] = sf::Vertex(corners[3], config::GAME_COLOR_WALL);
+            m_line[0] = sf::Vertex(corners[0], ThemeManager::Instance().getWallColor());
+            m_line[1] = sf::Vertex(corners[3], ThemeManager::Instance().getWallColor());
             break;
         case Room::RIGHT:
-            m_line[0] = sf::Vertex(corners[1], config::GAME_COLOR_WALL);
-            m_line[1] = sf::Vertex(corners[2], config::GAME_COLOR_WALL);
+            m_line[0] = sf::Vertex(corners[1], ThemeManager::Instance().getWallColor());
+            m_line[1] = sf::Vertex(corners[2], ThemeManager::Instance().getWallColor());
             break;
         case Room::UP:
-            m_line[0] = sf::Vertex(corners[0], config::GAME_COLOR_WALL);
-            m_line[1] = sf::Vertex(corners[1], config::GAME_COLOR_WALL);
+            m_line[0] = sf::Vertex(corners[0], ThemeManager::Instance().getWallColor());
+            m_line[1] = sf::Vertex(corners[1], ThemeManager::Instance().getWallColor());
             break;
         case Room::DOWN:
-            m_line[0] = sf::Vertex(corners[2], config::GAME_COLOR_WALL);
-            m_line[1] = sf::Vertex(corners[3], config::GAME_COLOR_WALL);
+            m_line[0] = sf::Vertex(corners[2], ThemeManager::Instance().getWallColor());
+            m_line[1] = sf::Vertex(corners[3], ThemeManager::Instance().getWallColor());
             break;
         case Room::INVALID:
             throw std::runtime_error("Invalid side");
diff --git a/source/application/Drawable/Maze/MenuGame.cpp b/source/application/Drawable/Maze/MenuGame.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d4cbc388871868d19f6bac9f7037a3f99d9856e
--- /dev/null
+++ b/source/application/Drawable/Maze/MenuGame.cpp
@@ -0,0 +1,25 @@
+#include "MenuGame.h"
+#include "../../../../config.h"
+#include "../../State/ThemeManager.h"
+#include "../../State/GameState.h"
+#include "../DrawMenu/Font/Font.h"
+
+MenuGame::MenuGame() {
+}
+
+void MenuGame::draw_into(sf::RenderWindow &window, const ScoreCount& scores_one, const ScoreCount& scores_two) {
+    sf::Text m_title(config::SELECT_LEVEL_TITLE_WINDOW, MyFont::Instance(), 40);
+    m_title.setFillColor(ThemeManager::Instance().getButtonScoreColor());
+    m_title.setPosition(10.f, 55.f);
+    window.draw(m_title);
+
+    sf::Text player_one("Player 1: " + std::to_string(scores_one.get_player_one()), MyFont::Instance(), 30);
+    player_one.setFillColor(ThemeManager::Instance().getButtonScoreColor());
+    player_one.setPosition(10.f, 95.f);
+    window.draw(player_one);
+
+    sf::Text player_two("Player 2: " + std::to_string(scores_two.get_player_two()), MyFont::Instance(), 30);
+    player_two.setFillColor(ThemeManager::Instance().getButtonScoreColor());
+    player_two.setPosition(10.f, 125.f);
+    window.draw(player_two);
+}
\ No newline at end of file
diff --git a/source/application/Drawable/Maze/MenuGame.h b/source/application/Drawable/Maze/MenuGame.h
new file mode 100644
index 0000000000000000000000000000000000000000..b60dee6287829c3214834070be1cbc87c4772e21
--- /dev/null
+++ b/source/application/Drawable/Maze/MenuGame.h
@@ -0,0 +1,16 @@
+#pragma once
+#include <SFML/Graphics.hpp>
+#include "IObserver.h"
+
+class MenuGame {
+public:
+    MenuGame();
+    void draw_into(sf::RenderWindow &window, const ScoreCount& scores_one, const ScoreCount& scores_two);
+
+private:
+    sf::RenderWindow m_window;
+    sf::RectangleShape m_background;
+    sf::RectangleShape m_button;
+    sf::Text m_player_one_score;
+    sf::Text m_player_two_score;
+};
\ No newline at end of file
diff --git a/source/application/Event/IGameEvent.cpp b/source/application/Event/IGameEvent.cpp
index afb393c4a5ea138acab4eca81bc24191d072dcaa..bba248c261e9dda0ec24d3a4de4222b791f17a3b 100644
--- a/source/application/Event/IGameEvent.cpp
+++ b/source/application/Event/IGameEvent.cpp
@@ -9,6 +9,7 @@ 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);
+    notify();
 }
 
 DeleteStaticEntity::DeleteStaticEntity(IStaticEntity* ptr_entity) :
@@ -17,4 +18,13 @@ DeleteStaticEntity::DeleteStaticEntity(IStaticEntity* ptr_entity) :
 
 void WinGame::handle(GameContext* context) {
     context->state = GameContext::WIN;
-}
\ No newline at end of file
+}
+
+void IGameEvent::add_observer(IObserver *observer) {
+    m_observers.push_back(observer);
+}
+
+void IGameEvent::notify() const {
+    for (auto observer : m_observers)
+        observer->on_notify(*this);
+}
diff --git a/source/application/Event/IGameEvent.h b/source/application/Event/IGameEvent.h
index 1e8b9fc7a4b8b980e6b94074268c8bf53219c393..4157d10aca8a954f3176b3e455ba5698ce4b3b3c 100644
--- a/source/application/Event/IGameEvent.h
+++ b/source/application/Event/IGameEvent.h
@@ -2,6 +2,7 @@
 
 #include <iostream>
 #include <list>
+#include "../Drawable/Maze/IObserver.h"
 
 class GameContext;
 class IStaticEntity;
@@ -10,6 +11,11 @@ class IGameEvent {
 public:
     virtual void handle(GameContext* context) = 0;
     virtual ~IGameEvent() = default;
+    void add_observer(IObserver* observer);
+protected:
+    void notify() const;
+private:
+    std::vector<IObserver*> m_observers;
 };
 
 class WinGame : public IGameEvent {
@@ -26,6 +32,8 @@ class DeleteStaticEntity : public IGameEvent {
 public:
     DeleteStaticEntity(IStaticEntity* ptr_entity);
     void handle(GameContext* context) override;
+    int get_player_id() const {return m_player_id; }
 private:
     IStaticEntity* m_ptr_entity;
+    int m_player_id;
 };
diff --git a/source/application/SelectCommand/ISelectCommand.h b/source/application/SelectCommand/ISelectCommand.h
index 844b111eda10dafea5a70156ec487e1ade8746b6..de81153d2b8b3784c4798d43f70938a502a9a9da 100644
--- a/source/application/SelectCommand/ISelectCommand.h
+++ b/source/application/SelectCommand/ISelectCommand.h
@@ -27,13 +27,14 @@ public:
 
 class GameCommand: public ChangeStateCommand {
 public:
-    GameCommand(IStateManager& state_manager, std::unique_ptr<GameBuilderDirector> ptr_director) :
-            ChangeStateCommand(state_manager), m_ptr_director(std::move(ptr_director)) {};
+    GameCommand(IStateManager& state_manager, std::unique_ptr<GameBuilderDirector>& ptr_director, int players) :
+            ChangeStateCommand(state_manager), m_ptr_director(std::move(ptr_director)), m_players(players) {};
     void execute() override {
-        auto state = m_ptr_director->build(m_state_manager);
+        auto state = m_ptr_director->build(m_state_manager, m_players);
         m_state_manager.set_next_state(std::move(state));
     };
 
 private:
+    int m_players;
     std::unique_ptr<GameBuilderDirector> m_ptr_director;
 };
\ No newline at end of file
diff --git a/source/application/State/GameState.cpp b/source/application/State/GameState.cpp
index 9dd9d5930e2d40fef2ff4e95e5592190e7b67fd4..7f8bdf76b9150017d398be49dec624025c81dae9 100644
--- a/source/application/State/GameState.cpp
+++ b/source/application/State/GameState.cpp
@@ -1,9 +1,10 @@
 #include "GameState.h"
 #include "SelectState.h"
-#include "../../../config.h"
-#include "../Drawable/Entity/IEntity.h"
+#include "ThemeManager.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){ }
+        IState(state_manager), IWindowKeeper(config::GAME_VIDEO_MODE, window_title),
+        m_menu(), m_score_count_one(std::make_unique<ScoreCount>(1)), m_score_count_two(std::make_unique<ScoreCount>(2)){ }
 
 void GameState::event_handling() {
     sf::Event event{};
@@ -23,42 +24,32 @@ void GameState::event_handling() {
 }
 
 bool 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); //выполнили действие
-            return true;
-        case sf::Keyboard::S:
-            m_context_manager.save_current_context();
-            m_context_manager.get_current_context().pacman.move(Room::DOWN);
-            return true;
-        case sf::Keyboard::A:
-            m_context_manager.save_current_context();
-            m_context_manager.get_current_context().pacman.move(Room::LEFT);
-            return true;
-        case sf::Keyboard::D:
-            m_context_manager.save_current_context();
-            m_context_manager.get_current_context().pacman.move(Room::RIGHT);
-            return true;
+    GameContext& context = m_context_manager.get_current_context();
 
-        case sf::Keyboard::Up:
-            m_context_manager.save_current_context(); //сохраняем состояние
-            m_context_manager.get_current_context().pacman2.move(Room::UP); //выполнили действие
-            return true;
-        case sf::Keyboard::Down:
-            m_context_manager.save_current_context();
-            m_context_manager.get_current_context().pacman2.move(Room::DOWN);
-            return true;
-        case sf::Keyboard::Left:
-            m_context_manager.save_current_context();
-            m_context_manager.get_current_context().pacman2.move(Room::LEFT);
-            return true;
-        case sf::Keyboard::Right:
+    if (code == sf::Keyboard::W || code == sf::Keyboard::A || code == sf::Keyboard::S || code == sf::Keyboard::D) {
+        m_context_manager.save_current_context();
+        switch (code) {
+            case sf::Keyboard::W: context.pacman.move(Room::UP); break;
+            case sf::Keyboard::S: context.pacman.move(Room::DOWN); break;
+            case sf::Keyboard::A: context.pacman.move(Room::LEFT); break;
+            case sf::Keyboard::D: context.pacman.move(Room::RIGHT); break;
+        }
+        return true;
+    }
+
+    if (code == sf::Keyboard::Up || code == sf::Keyboard::Down || code == sf::Keyboard::Left || code == sf::Keyboard::Right) {
+        if (context.pacman2.get_location() != nullptr) {
             m_context_manager.save_current_context();
-            m_context_manager.get_current_context().pacman2.move(Room::RIGHT);
+            switch (code) {
+                case sf::Keyboard::Up: context.pacman2.move(Room::UP); break;
+                case sf::Keyboard::Down: context.pacman2.move(Room::DOWN); break;
+                case sf::Keyboard::Left: context.pacman2.move(Room::LEFT); break;
+                case sf::Keyboard::Right: context.pacman2.move(Room::RIGHT); break;
+            }
             return true;
-        default: return false;
+        }
     }
+    return false;
 }
 
 void GameState::update() {
@@ -71,44 +62,63 @@ void GameState::update() {
         auto ptr_event = ptr_entity->accept(ptr_visitor);
         if (ptr_event)  game_events.emplace_back(std::move(ptr_event));
 
-        IVisitor* ptr_visitor2 = &(context.pacman2);
-        auto ptr_event2 = ptr_entity->accept(ptr_visitor2);
-        if (ptr_event2)  game_events.emplace_back(std::move(ptr_event2));
+        if (context.pacman2.get_location() != nullptr) {
+            IVisitor* ptr_visitor2 = &(context.pacman2);
+            auto ptr_event2 = ptr_entity->accept(ptr_visitor2);
+            if (ptr_event2)  game_events.emplace_back(std::move(ptr_event2));
+        }
     }
     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));
+        if (auto ptr_event = static_ptr->accept(ptr_visitor)) {
+            ptr_event->add_observer(m_score_count_one.get());
+            game_events.emplace_back(std::move(ptr_event));
+        }
 
-        IVisitor* ptr_visitor2 = &(context.pacman2);
-        auto ptr_event2 = static_ptr->accept(ptr_visitor2);
-        if (ptr_event2)  game_events.emplace_back(std::move(ptr_event2));
+        if (context.pacman2.get_location() != nullptr) {
+            IVisitor* ptr_visitor2 = &(context.pacman2);
+            if (auto ptr_event2 = static_ptr->accept(ptr_visitor2)) {
+                ptr_event2->add_observer(m_score_count_two.get());
+                game_events.emplace_back(std::move(ptr_event2));
+            }
+        }
+    }
+
+    if (context.static_objects.empty()) {
+        game_events.emplace_back(std::make_unique<WinGame>());
+        if (m_score_count_one->get_player_one() > m_score_count_two->get_player_two()) std::cout << "выиграл первый";
+        else std::cout << "выиграл второй";
     }
 
     for (int i = 0; i < game_events.size(); i++)
         game_events[i]->handle(&m_context_manager.get_current_context());
 
-    if (context.static_objects.empty()) {
-        game_events.emplace_back(std::move(std::make_unique<WinGame>()));
-    }
     game_events.clear();
 }
 
 void GameState::render() {
     GameContext& context = m_context_manager.get_current_context();
+    sf::Color backgroundColor;
     switch (context.state) {
         case GameContext::INGAME:
-            m_window.clear(config::GAME_COLOR_BACKGROUND_INGAME);
+            backgroundColor = ThemeManager::Instance().getGameBackgroundInGameColor();
             break;
         case GameContext::LOST:
-            m_window.clear(config::GAME_COLOR_BACKGROUND_LOST);
+            backgroundColor = ThemeManager::Instance().getGameBackgroundLostColor();
+            break;
+        case GameContext::WIN:
+            backgroundColor = ThemeManager::Instance().getGameBackgroundWinColor();
             break;
         default:
-            m_window.clear(config::GAME_COLOR_BACKGROUND_WIN);
+            break;
     }
+
+    m_window.clear(backgroundColor);
+    m_menu.draw_into(m_window, *m_score_count_one, *m_score_count_two);
     m_maze.draw_into(m_window);
     context.pacman.draw_into(m_window);
-    context.pacman2.draw_into(m_window);
+    if (context.pacman2.get_location() != nullptr)
+        context.pacman2.draw_into(m_window);
     for (auto& obj :  context.static_objects)
         obj->draw_into(m_window);
 
diff --git a/source/application/State/GameState.h b/source/application/State/GameState.h
index be23a5395c564d3e92db1e0135c701c4c9c88575..ea557516b4759b121e5779863255222d72395c9f 100644
--- a/source/application/State/GameState.h
+++ b/source/application/State/GameState.h
@@ -1,6 +1,7 @@
 #pragma once
 #include "IState.h"
 #include "../Drawable/Maze/Maze.h"
+#include "../Drawable/Maze/MenuGame.h"
 #include "../Context/Context.h"
 #include "../Event/IGameEvent.h"
 
@@ -11,12 +12,15 @@ public:
     void update() override;
     void render() override;
     bool do_step() override;
-
     void set_maze(Maze&& maze) {m_maze = std::move(maze); }
     void set_context(GameContext&& context);
     bool process_key_pressed(sf::Keyboard::Key code);
+    const ScoreCount& get_score_count() const {return *m_score_count_one, *m_score_count_two; }
 private:
     Maze m_maze;
+    MenuGame m_menu;
     ContextManager m_context_manager;
     std::vector<std::unique_ptr<IGameEvent>> m_events;
+    std::unique_ptr<ScoreCount> m_score_count_one;
+    std::unique_ptr<ScoreCount> m_score_count_two;
 };
diff --git a/source/application/State/SelectState.cpp b/source/application/State/SelectState.cpp
index e74338877b6e0b130a6b13c00d6c74e9f06a2e4f..8fdfa880f4d216a63bbdd1f47d60649fa372eb67 100644
--- a/source/application/State/SelectState.cpp
+++ b/source/application/State/SelectState.cpp
@@ -1,10 +1,13 @@
 #include "SelectState.h"
-#include "../../../config.h"
 
 SelectState::SelectState(IStateManager& state_manager,
                          const sf::VideoMode& video_mode,
                          const std::string& window_title) :
-        IState(state_manager), IWindowKeeper(video_mode, window_title), m_menu(state_manager) {}
+        IState(state_manager), IWindowKeeper(video_mode, window_title), m_menu(state_manager) {
+    update_theme();
+    set_texture(&BackgroundTexture::instance());
+    m_backgorund_sprite.setTexture(m_background->get_texture());
+}
 
 void SelectState::event_handling() {
     sf::Event event{};
@@ -26,7 +29,8 @@ void SelectState::update() {
 }
 
 void SelectState::render() {
-    m_window.clear(config::SELECT_LEVEL_BACKGROUND_COLOR);
+    update_theme();
+    m_window.draw(m_backgorund_sprite);
     m_menu.draw_into(m_window);
     m_window.display();
 }
diff --git a/source/application/State/SelectState.h b/source/application/State/SelectState.h
index deef1af0ff322a3e50790631229e214c2b88e1fc..2d05eccdf85a8bfeaac86cc7d702dcd8e3260505 100644
--- a/source/application/State/SelectState.h
+++ b/source/application/State/SelectState.h
@@ -1,13 +1,18 @@
 #pragma once
 #include "IState.h"
 #include "../Drawable/DrawMenu/Menu/Menu.h"
+#include "ThemeManager.h"
 
 struct SelectState: public IState, public IWindowKeeper {
     SelectState(IStateManager& state_manager, const sf::VideoMode& video_mode, const std::string& window_title);
     void event_handling() override;
+    void set_texture(MyTexture* ptr_texture) { m_background = ptr_texture; }
     void update() override;
     void render() override;
     bool do_step() override;
 private:
+    void update_theme() { ThemeManager::Instance().applyTheme(); }
+    MyTexture* m_background;
+    sf::Sprite m_backgorund_sprite;
     Menu m_menu;
 };
\ No newline at end of file
diff --git a/source/application/State/ThemeManager.cpp b/source/application/State/ThemeManager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9f1e6015319e7bf58a36141e486e7b0a999353d6
--- /dev/null
+++ b/source/application/State/ThemeManager.cpp
@@ -0,0 +1,102 @@
+#include "ThemeManager.h"
+
+ThemeManager& ThemeManager::Instance() {
+    static ThemeManager instance;
+    return instance;
+}
+
+sf::Color ThemeManager::getButtonFillColor() const {
+    return m_currentColors.button_fill;
+}
+
+void ThemeManager::set_theme(ThemeManager::Theme newTheme) {
+    m_theme = newTheme;
+    loadThemeColors();
+}
+
+sf::Color ThemeManager::getButtonOutlineColor() const {
+    return m_currentColors.button_frame;
+}
+
+sf::Color ThemeManager::getButtonTextColor() const {
+    return m_currentColors.button_text;
+}
+
+sf::Color ThemeManager::getButtonSelectionColor() const {
+    return m_currentColors.button_selection;
+}
+
+sf::Color ThemeManager::getTitleTextColor() const {
+    return m_currentColors.title_text;
+}
+
+sf::Color ThemeManager::getGameBackgroundInGameColor() const {
+    return m_currentColors.game_background_ingame;
+}
+
+sf::Color ThemeManager::getGameBackgroundWinColor() const {
+    return m_currentColors.game_background_win;
+}
+
+sf::Color ThemeManager::getGameBackgroundLostColor() const {
+    return m_currentColors.game_background_lost;
+}
+
+sf::Color ThemeManager::getRoomColor() const {
+    return m_currentColors.room_color;
+}
+
+sf::Color ThemeManager::getWallColor() const {
+    return m_currentColors.wall_color;
+}
+
+void ThemeManager::loadThemeColors() {
+    if (m_theme == Theme::LIGHT) {
+        m_currentColors = {
+                sf::Color::White,         // button_text
+                sf::Color::Black,
+                sf::Color(21, 117, 217), // button_fill
+                sf::Color(0, 0, 0), // button_selection
+                sf::Color::White,         // button_frame
+                sf::Color(240, 240, 240), // select_level_background
+                sf::Color(255, 255, 255), // game_background_ingame
+                sf::Color(0, 255, 0),     // game_background_win
+                sf::Color(255, 0, 0),     // game_background_lost
+                sf::Color(255, 255, 0),   // game_pacman
+                sf::Color(100, 100, 100), // game_pacman_invisible
+                sf::Color(200, 200, 255), // game_room
+                sf::Color(50, 50, 50),    // game_wall
+                sf::Color(255, 165, 0),   // game_food
+                sf::Color(255, 0, 0),     // game_enemy
+                sf::Color::White,    // title_text
+                sf::Color(255, 255, 255), // room_color
+                sf::Color(0, 0, 0) // wall_color
+        };
+    } else if (m_theme == Theme::DARK) {
+        m_currentColors = {
+                sf::Color::White,         // button_text
+                sf::Color::Black,
+                sf::Color(21, 117, 217),    // button_fill
+                sf::Color(80, 80, 80),    // button_selection
+                sf::Color::White,         // button_frame
+                sf::Color(30, 30, 30),    // select_level_background
+                sf::Color(40, 40, 40),    // game_background_ingame
+                sf::Color(0, 255, 0),     // game_background_win
+                sf::Color(255, 0, 0),     // game_background_lost
+                sf::Color(255, 255, 0),   // game_pacman
+                sf::Color(100, 100, 100), // game_pacman_invisible
+                sf::Color(100, 100, 100), // game_room
+                sf::Color(50, 50, 50),    // game_wall
+                sf::Color(255, 165, 0),   // game_food
+                sf::Color(255, 0, 0),     // game_enemy
+                sf::Color::White,         // title_text
+                sf::Color(0, 0, 0), // room_color
+                sf::Color(0, 0, 255) // wall_color
+        };
+    }
+}
+
+sf::Color ThemeManager::getButtonScoreColor() const {
+    return m_currentColors.button_text_score;
+}
+
diff --git a/source/application/State/ThemeManager.h b/source/application/State/ThemeManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..39f87ee1c793f33857437cffde86ca7052160d92
--- /dev/null
+++ b/source/application/State/ThemeManager.h
@@ -0,0 +1,55 @@
+#pragma once
+#include "../../../config.h"
+
+struct ThemeColors {
+    sf::Color button_text;
+    sf::Color button_text_score;
+    sf::Color button_fill;
+    sf::Color button_selection;
+    sf::Color button_frame;
+    sf::Color select_level_background;
+    sf::Color game_background_ingame;
+    sf::Color game_background_win;
+    sf::Color game_background_lost;
+    sf::Color game_pacman;
+    sf::Color game_pacman_invisible;
+    sf::Color game_room;
+    sf::Color game_wall;
+    sf::Color game_food;
+    sf::Color game_enemy;
+    sf::Color title_text;
+    sf::Color room_color;
+    sf::Color wall_color;
+};
+
+
+class ThemeManager {
+public:
+    enum class Theme { LIGHT, DARK };
+    ThemeManager(const ThemeManager&) = delete;
+    ThemeManager& operator=(const ThemeManager&) = delete;
+    static ThemeManager& Instance();
+    void applyTheme() {loadThemeColors(); }
+    void set_theme(Theme newTheme);
+
+    sf::Color getButtonFillColor() const;
+    sf::Color getButtonOutlineColor() const;
+    sf::Color getButtonTextColor() const;
+    sf::Color getButtonScoreColor() const;
+    sf::Color getButtonSelectionColor() const;
+
+    sf::Color getTitleTextColor() const;
+
+    sf::Color getGameBackgroundInGameColor() const;
+    sf::Color getGameBackgroundWinColor() const;
+    sf::Color getGameBackgroundLostColor() const;
+    sf::Color getRoomColor() const;
+    sf::Color getWallColor() const;
+
+private:
+    Theme m_theme = Theme::LIGHT;
+    ThemeColors m_currentColors;
+    void loadThemeColors();
+
+    ThemeManager() {set_theme(Theme::LIGHT);};
+};