diff --git a/Array-Minesweeper/Array-Minesweeper.vcxproj b/Array-Minesweeper/Array-Minesweeper.vcxproj
index 310df8e5..bec4d02e 100644
--- a/Array-Minesweeper/Array-Minesweeper.vcxproj
+++ b/Array-Minesweeper/Array-Minesweeper.vcxproj
@@ -133,6 +133,16 @@
+
+
+
+
+
+
+
+
+
+
@@ -153,10 +163,20 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/Array-Minesweeper/SFML/include/SFML/Config.hpp b/Array-Minesweeper/SFML/include/SFML/Config.hpp
index f4ea4ef3..3093a7a5 100644
--- a/Array-Minesweeper/SFML/include/SFML/Config.hpp
+++ b/Array-Minesweeper/SFML/include/SFML/Config.hpp
@@ -31,7 +31,7 @@
////////////////////////////////////////////////////////////
#define SFML_VERSION_MAJOR 2
#define SFML_VERSION_MINOR 6
-#define SFML_VERSION_PATCH 0
+#define SFML_VERSION_PATCH 1
////////////////////////////////////////////////////////////
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s-d.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s-d.pdb
index 9371818c..bbd97a4b 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s-d.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s-d.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s.pdb
index 9371818c..bbd97a4b 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-audio-s.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-audio.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-audio.pdb
index eec00db2..e0cd9357 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-audio.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-audio.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s-d.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s-d.pdb
index c0bed6ba..d187d972 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s-d.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s-d.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s.pdb
index c0bed6ba..d187d972 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-graphics-s.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-graphics.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-graphics.pdb
index c516163a..310a084a 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-graphics.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-graphics.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-main-d.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-main-d.pdb
index 3e17d4a2..432660dd 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-main-d.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-main-d.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-main-s.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-main-s.pdb
index 3e17d4a2..432660dd 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-main-s.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-main-s.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-network-s-d.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-network-s-d.pdb
index 7afce526..446f1fb8 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-network-s-d.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-network-s-d.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-network-s.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-network-s.pdb
index 7afce526..446f1fb8 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-network-s.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-network-s.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-network.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-network.pdb
index 93ec6553..fa073311 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-network.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-network.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-system-s-d.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-system-s-d.pdb
index 2ba28522..aa448263 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-system-s-d.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-system-s-d.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-system-s.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-system-s.pdb
index 2ba28522..aa448263 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-system-s.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-system-s.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-system.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-system.pdb
index 59b5195a..ea487f4f 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-system.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-system.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-window-s-d.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-window-s-d.pdb
index 4a11994b..98a4c966 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-window-s-d.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-window-s-d.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-window-s.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-window-s.pdb
index 4a11994b..98a4c966 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-window-s.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-window-s.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/Debug/sfml-window.pdb b/Array-Minesweeper/SFML/lib/Debug/sfml-window.pdb
index 332a83ca..1e2442bd 100644
Binary files a/Array-Minesweeper/SFML/lib/Debug/sfml-window.pdb and b/Array-Minesweeper/SFML/lib/Debug/sfml-window.pdb differ
diff --git a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfig.cmake b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfig.cmake
index f8b915b6..f28497b6 100644
--- a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfig.cmake
+++ b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfig.cmake
@@ -144,5 +144,5 @@ if (NOT SFML_FOUND)
endif()
if (SFML_FOUND AND NOT SFML_FIND_QUIETLY)
- message(STATUS "Found SFML 2.6.0 in ${CMAKE_CURRENT_LIST_DIR}")
+ message(STATUS "Found SFML 2.6.1 in ${CMAKE_CURRENT_LIST_DIR}")
endif()
diff --git a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfigVersion.cmake b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfigVersion.cmake
index b2208ca9..25db8760 100644
--- a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfigVersion.cmake
+++ b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLConfigVersion.cmake
@@ -9,19 +9,19 @@
# The variable CVF_VERSION must be set before calling configure_file().
-set(PACKAGE_VERSION "2.6.0")
+set(PACKAGE_VERSION "2.6.1")
if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION)
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
- if("2.6.0" MATCHES "^([0-9]+)\\.")
+ if("2.6.1" MATCHES "^([0-9]+)\\.")
set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}")
if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0)
string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}")
endif()
else()
- set(CVF_VERSION_MAJOR "2.6.0")
+ set(CVF_VERSION_MAJOR "2.6.1")
endif()
if(PACKAGE_FIND_VERSION_RANGE)
diff --git a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLSharedTargets.cmake b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLSharedTargets.cmake
index 1c1c3c06..852e1a8d 100644
--- a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLSharedTargets.cmake
+++ b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLSharedTargets.cmake
@@ -7,7 +7,7 @@ if(CMAKE_VERSION VERSION_LESS "2.8.3")
message(FATAL_ERROR "CMake >= 2.8.3 required")
endif()
cmake_policy(PUSH)
-cmake_policy(VERSION 2.8.3...3.24)
+cmake_policy(VERSION 2.8.3...3.25)
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------
diff --git a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLStaticTargets.cmake b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLStaticTargets.cmake
index 7257de65..419bb1b8 100644
--- a/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLStaticTargets.cmake
+++ b/Array-Minesweeper/SFML/lib/cmake/SFML/SFMLStaticTargets.cmake
@@ -7,7 +7,7 @@ if(CMAKE_VERSION VERSION_LESS "2.8.3")
message(FATAL_ERROR "CMake >= 2.8.3 required")
endif()
cmake_policy(PUSH)
-cmake_policy(VERSION 2.8.3...3.24)
+cmake_policy(VERSION 2.8.3...3.25)
#----------------------------------------------------------------
# Generated CMake target import file.
#----------------------------------------------------------------
diff --git a/Array-Minesweeper/header/Event/EventService.h b/Array-Minesweeper/header/Event/EventService.h
index 093932f5..9477ed8a 100644
--- a/Array-Minesweeper/header/Event/EventService.h
+++ b/Array-Minesweeper/header/Event/EventService.h
@@ -24,7 +24,7 @@ namespace Event
bool gameWindowWasClosed();
bool hasQuitGame();
bool isKeyboardEvent();
- void updateButtonsState(ButtonState& button_state);
+ void updateButtonsState(ButtonState& button_state, sf::Mouse::Button button_type);
public:
EventService();
diff --git a/Array-Minesweeper/header/Gameplay/Board/BoardController.h b/Array-Minesweeper/header/Gameplay/Board/BoardController.h
new file mode 100644
index 00000000..9d24ca25
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/Board/BoardController.h
@@ -0,0 +1,84 @@
+#pragma once
+#include
+#include "../../header/Gameplay/Cell/CellController.h"
+#include "../../header/UI/UIElement/ButtonView.h"
+#include
+
+namespace Gameplay
+{
+ namespace Board
+ {
+ class BoardView;
+
+ enum class BoardState
+ {
+ FIRST_CELL, // The state when the player opens first cell.
+ PLAYING, // The game is in progress.
+ COMPLETED, // The game is over.
+ };
+
+ class BoardController
+ {
+ public:
+ static const int number_of_rows = 9;
+ static const int number_of_colums = 9;
+ static const int mines_count = 8;
+
+ BoardController();
+ ~BoardController();
+
+ void initialize();
+ void update();
+ void render();
+
+ void processCellInput(Cell::CellController* cell_controller, UI::UIElement::ButtonType button_type);
+ void reset();
+
+ BoardState getBoardState();
+ void setBoardState(BoardState state);
+
+ int getMinesCount();
+
+ void flagAllMines();
+ void openAllCells();
+ void showBoard();
+
+ private:
+ BoardView* board_view;
+ Cell::CellController* board[number_of_rows][number_of_colums];
+
+ // To generate random values.
+ std::default_random_engine random_engine;
+
+ // To give random seed to generator.
+ std::random_device random_device;
+
+ BoardState board_state;
+ int flagged_cells;
+
+ void createBoard();
+ void initializeCells();
+
+ void populateBoard(sf::Vector2i cell_position);
+ void populateMines(sf::Vector2i cell_position);
+ void populateCells();
+ int countMinesAround(sf::Vector2i cell_position);
+
+ void flagCell(sf::Vector2i cell_position);
+ void openCell(sf::Vector2i cell_position);
+ bool areAllCellOpen();
+
+ void processCellType(sf::Vector2i cell_position);
+ void processEmptyCell(sf::Vector2i cell_position);
+ void processMineCell(sf::Vector2i cell_position);
+
+ void openEmptyCells(sf::Vector2i cell_position);
+ bool isValidCellPosition(sf::Vector2i cell_position);
+
+
+ void resetBoard();
+ void deleteBoard();
+ void destroy();
+ };
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Gameplay/Board/BoardService.h b/Array-Minesweeper/header/Gameplay/Board/BoardService.h
new file mode 100644
index 00000000..65ae995b
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/Board/BoardService.h
@@ -0,0 +1,39 @@
+#pragma once
+#include "../../header/Gameplay/Board/BoardController.h"
+#include "../../header/Gameplay/Cell/CellController.h"
+#include "../../header/UI/UIElement/ButtonView.h"
+
+
+namespace Gameplay
+{
+ enum class GameResult;
+
+ namespace Board
+ {
+ class BoardService
+ {
+ private:
+ Board::BoardController* board_controller;
+
+ void destroy();
+
+ public:
+ BoardService();
+ ~BoardService();
+ void initialize();
+ void update();
+ void render();
+
+ void processCellInput(Cell::CellController* cell_controller, UI::UIElement::ButtonType button_type);
+
+ BoardState getBoardState();
+ void setBoardState(BoardState state);
+ void resetBoard();
+
+ int getMinesCount();
+
+ void flagAllMines();
+ void showBoard();
+ };
+ }
+}
diff --git a/Array-Minesweeper/header/Gameplay/Board/BoardView.h b/Array-Minesweeper/header/Gameplay/Board/BoardView.h
new file mode 100644
index 00000000..2e453bc0
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/Board/BoardView.h
@@ -0,0 +1,41 @@
+#pragma once
+#include "../../header/UI/UIElement/ImageView.h"
+
+namespace Gameplay
+{
+ namespace Board
+ {
+ class BoardController;
+
+ class BoardView
+ {
+ private:
+
+ const float board_width_offset = 115.f;
+ const float board_height_offset = 329.f;
+
+ const float board_width = 866.f;
+ const float board_height = 1080.f;
+
+ const float background_alpha = 85.f;
+
+ BoardController* board_controller;
+ UI::UIElement::ImageView* board_image;
+ UI::UIElement::ImageView* background_image;
+
+ void initializeBackgroudImage();
+ void initializeBoardImage();
+
+ public:
+ BoardView(BoardController* controller);
+ ~BoardView();
+
+ void initialize();
+ void update();
+ void render();
+
+ float getCellWidth();
+ float getCellHeight();
+ };
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Gameplay/Cell/CellController.h b/Array-Minesweeper/header/Gameplay/Cell/CellController.h
new file mode 100644
index 00000000..5e965fc1
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/Cell/CellController.h
@@ -0,0 +1,45 @@
+#pragma once
+#include
+
+namespace Gameplay
+{
+ namespace Cell
+ {
+ class CellView;
+ class CellModel;
+ enum class CellState;
+ enum class CellType;
+
+ class CellController
+ {
+ private:
+ CellView* cell_view;
+ CellModel* cell_model;
+
+ void destroy();
+
+ public:
+ CellController(sf::Vector2i grid_position);
+ ~CellController();
+
+ void initialize(float cell_width, float cell_height);
+ void update();
+ void render();
+
+ void flagCell();
+ void openCell();
+
+ bool canOpenCell();
+ CellState getCellState();
+ void setCellState(CellState state);
+
+ CellType getCellType();
+ void setCellType(CellType type);
+
+ sf::Vector2i getCellPosition();
+ int getMinesAround();
+
+ void reset();
+ };
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Gameplay/Cell/CellModel.h b/Array-Minesweeper/header/Gameplay/Cell/CellModel.h
new file mode 100644
index 00000000..0b29cdda
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/Cell/CellModel.h
@@ -0,0 +1,57 @@
+#pragma once
+#include
+
+namespace Gameplay
+{
+ namespace Cell
+ {
+ enum class CellState
+ {
+ HIDDEN,
+ OPEN,
+ FLAGGED,
+ };
+
+ enum class CellType
+ {
+ EMPTY,
+ ONE,
+ TWO,
+ THREE,
+ FOUR,
+ FIVE,
+ SIX,
+ SEVEN,
+ EIGHT,
+ MINE,
+ };
+
+ class CellModel
+ {
+ private:
+ CellState cell_state;
+ CellType cell_type;
+
+ sf::Vector2i position;
+ int mines_around;
+
+ public:
+ CellModel(sf::Vector2i grid_position);
+ ~CellModel();
+
+ CellState getCellState();
+ void setCellState(CellState state);
+
+ CellType getCellType();
+ void setCellType(CellType type);
+
+ sf::Vector2i getCellPosition();
+ void setCellPosition(sf::Vector2i grid_position);
+
+ int getMinesAround();
+ void setMinesAround(int mine_count);
+
+ void reset();
+ };
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Gameplay/Cell/CellView.h b/Array-Minesweeper/header/Gameplay/Cell/CellView.h
new file mode 100644
index 00000000..2ba19c49
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/Cell/CellView.h
@@ -0,0 +1,40 @@
+#pragma once
+#include "../../header/UI/UIElement/ButtonView.h"
+
+namespace Gameplay
+{
+ namespace Cell
+ {
+ class CellController;
+
+ class CellView
+ {
+ private:
+ const float cell_top_offset = 274.f;
+ const float cell_left_offset = 583.f;
+
+ const float cell_texture_width = 384;
+ const float cell_texture_height = 32;
+
+ const int tile_size = 32;
+ const int slice_count= 12;
+
+ UI::UIElement::ButtonView* cell_button;
+ CellController* cell_controller;
+
+ void initializeButtonImage(float width, float height);
+ sf::Vector2f getCellScreenPosition(float width, float height);
+ void setCellTexture();
+ void registerButtonCallback();
+ void cellButtonCallback(UI::UIElement::ButtonType button_type);
+
+ public:
+ CellView(CellController* controller);
+ ~CellView();
+
+ void initialize(float width, float height);
+ void update();
+ void render();
+ };
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Gameplay/GameplayController.h b/Array-Minesweeper/header/Gameplay/GameplayController.h
new file mode 100644
index 00000000..5580d6b4
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/GameplayController.h
@@ -0,0 +1,49 @@
+#pragma once
+#include "../../header/Gameplay/Board/BoardService.h"
+#include "../../header/Gameplay/Cell/CellController.h"
+#include "../../header/UI/UIElement/ButtonView.h"
+#include
+
+namespace Gameplay
+{
+ using namespace Gameplay::Board;
+
+ enum class GameResult
+ {
+ NONE,
+ WON,
+ LOST
+ };
+
+ class GameplayController
+ {
+ private:
+ const float max_level_duration = 301.0f;
+ const float game_over_time = 11.f;
+ BoardService* board_service;
+
+ float remaining_time;
+ GameResult game_result;
+
+ void updateRemainingTime();
+ bool isTimeOver();
+ void showCredits();;
+ void beginGameOverTimer();
+
+ void gameWon();
+ void gameLost();
+
+ public:
+ ~GameplayController();
+
+ void initialize();
+ void update();
+ void render();
+
+ void restart();
+ void endGame(GameResult result);
+
+ int getMinesCount();
+ float getRemainingTime();
+ };
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Gameplay/GameplayService.h b/Array-Minesweeper/header/Gameplay/GameplayService.h
new file mode 100644
index 00000000..0b5222af
--- /dev/null
+++ b/Array-Minesweeper/header/Gameplay/GameplayService.h
@@ -0,0 +1,30 @@
+#pragma once
+#include "../../header/Gameplay/GameplayController.h"
+#include "../../header/Gameplay/Cell/CellController.h"
+#include "../../header/UI/UIElement/ButtonView.h"
+
+namespace Gameplay
+{
+ class GameplayService
+ {
+ private:
+ GameplayController* gameplay_controller;
+
+ void createController();
+ void destroy();
+
+ public:
+ GameplayService();
+ ~GameplayService();
+
+ void initialize();
+ void update();
+ void render();
+
+ void startGame();
+ void endGame(GameResult result);
+
+ int getMinesCount();
+ float getRemainingTime();
+ };
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Global/ServiceLocator.h b/Array-Minesweeper/header/Global/ServiceLocator.h
index a397af14..2eae95df 100644
--- a/Array-Minesweeper/header/Global/ServiceLocator.h
+++ b/Array-Minesweeper/header/Global/ServiceLocator.h
@@ -3,6 +3,9 @@
#include "../../header/Event/EventService.h"
#include "../../header/UI/UIService.h"
#include "../../header/Sound/SoundService.h"
+#include "../../header/Gameplay/GameplayService.h"
+#include "../../header/Gameplay/Board/BoardService.h"
+#include "../../header/Time/TimeService.h"
namespace Global
{
@@ -13,6 +16,9 @@ namespace Global
Graphics::GraphicService* graphic_service;
Sound::SoundService* sound_service;
UI::UIService* ui_service;
+ Gameplay::GameplayService* gameplay_service;
+ Time::TimeService* time_service;
+ Gameplay::Board::BoardService* board_service;
ServiceLocator();
~ServiceLocator();
@@ -31,6 +37,9 @@ namespace Global
Graphics::GraphicService* getGraphicService();
Sound::SoundService* getSoundService();
UI::UIService* getUIService();
+ Gameplay::GameplayService* getGameplayService();
+ Time::TimeService* getTimeService();
+ Gameplay::Board::BoardService* getBoardService();
void deleteServiceLocator();
};
}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/Main/GameService.h b/Array-Minesweeper/header/Main/GameService.h
index 19d91570..74ef6216 100644
--- a/Array-Minesweeper/header/Main/GameService.h
+++ b/Array-Minesweeper/header/Main/GameService.h
@@ -9,8 +9,8 @@ namespace Main
BOOT,
SPLASH_SCREEN,
MAIN_MENU,
- GAMEPLAY,
INSTRUCTIONS,
+ GAMEPLAY,
CREDITS,
};
diff --git a/Array-Minesweeper/header/Sound/SoundService.h b/Array-Minesweeper/header/Sound/SoundService.h
index c8ec5d90..33261e07 100644
--- a/Array-Minesweeper/header/Sound/SoundService.h
+++ b/Array-Minesweeper/header/Sound/SoundService.h
@@ -6,6 +6,9 @@ namespace Sound
enum class SoundType
{
BUTTON_CLICK,
+ FLAG,
+ EXPLOSION,
+ GAME_WON
};
class SoundService
@@ -16,6 +19,9 @@ namespace Sound
sf::Music background_music;
sf::Sound sound_effect;
sf::SoundBuffer buffer_button_click;
+ sf::SoundBuffer buffer_flag_sound;
+ sf::SoundBuffer buffer_explosion;
+ sf::SoundBuffer buffer_game_won;
void loadBackgroundMusicFromFile();
void loadSoundFromFile();
diff --git a/Array-Minesweeper/header/Time/TimeService.h b/Array-Minesweeper/header/Time/TimeService.h
new file mode 100644
index 00000000..f201cb2f
--- /dev/null
+++ b/Array-Minesweeper/header/Time/TimeService.h
@@ -0,0 +1,34 @@
+#pragma once
+#include
+
+namespace Time
+{
+ /*
+ // The TimeService class helps keep track of time in game and calculate delta time.
+ // Utilizes the library to calculate delta time.
+ */
+ class TimeService
+ {
+ private:
+ /*
+ // A time point that represents the previous moment in time using the steady clock.
+ // The steady clock is a clock that provides a monotonic and constant time source
+ // that is not subject to system clock adjustments, making it suitable for measuring
+ // time intervals precisely.
+ */
+ std::chrono::time_point previous_time;
+
+ float delta_time;
+
+ void updateDeltaTime();
+ float calculateDeltaTime();
+ void updatePreviousTime();
+
+ public:
+
+ void initialize();
+ void update();
+
+ float getDeltaTime();
+ };
+}
diff --git a/Array-Minesweeper/header/UI/Gameplay/GameplayUIController.h b/Array-Minesweeper/header/UI/Gameplay/GameplayUIController.h
new file mode 100644
index 00000000..13307e5a
--- /dev/null
+++ b/Array-Minesweeper/header/UI/Gameplay/GameplayUIController.h
@@ -0,0 +1,59 @@
+#pragma once
+#include "../../header/UI/Interface/IUIController.h"
+#include "../../header/UI/UIElement/TextView.h"
+#include "../../header/UI/UIElement/ButtonView.h"
+
+namespace UI
+{
+ namespace GameplayUI
+ {
+ class GameplayUIController : public Interface::IUIController
+ {
+ private:
+ const int font_size = 110;
+
+ const float mine_text_top_offset = 65.f;
+ const float mine_text_left_offset = 660.f;
+
+ const float time_text_top_offset = 65.f;
+ const float time_text_left_offset = 1090.f;
+
+ const float restart_button_top_offset = 100.f;
+ const float restart_button_left_offset = 920.f;
+
+ const float button_height = 80.f;
+ const float button_width = 80.f;
+
+ const int tile_height = 32;
+
+ const sf::Color text_color = sf::Color::Red;
+
+ UIElement::TextView* mine_text;
+ UIElement::TextView* time_text;
+ UIElement::ButtonView* restart_button;
+
+ void createButton();
+ void createTexts();
+ void initializeButton();
+ void initializeTexts();
+ void initializeMineText();
+ void initializeTimeText();
+
+ void updateMineText();
+ void updateTimeText();
+ void restartButtonCallback();
+ void registerButtonCallback();
+
+ void destroy();
+
+ public:
+ GameplayUIController();
+ ~GameplayUIController();
+
+ void initialize() override;
+ void update() override;
+ void render() override;
+ void show() override;
+ };
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/header/UI/MainMenu/MainMenuUIController.h b/Array-Minesweeper/header/UI/MainMenu/MainMenuUIController.h
index dcff1cf5..e048dad0 100644
--- a/Array-Minesweeper/header/UI/MainMenu/MainMenuUIController.h
+++ b/Array-Minesweeper/header/UI/MainMenu/MainMenuUIController.h
@@ -15,9 +15,9 @@ namespace UI
const float button_width = 400.f;
const float button_height = 140.f;
- const float play_button_y_position = 500.f;
- const float instructions_button_y_position = 700.f;
- const float quit_button_y_position = 900.f;
+ const float play_button_y_position = 400.f;
+ const float instructions_button_y_position = 600.f;
+ const float quit_button_y_position = 800.f;
const float background_alpha = 85.f;
diff --git a/Array-Minesweeper/header/UI/UIElement/ButtonView.h b/Array-Minesweeper/header/UI/UIElement/ButtonView.h
index b89fc6c0..35683b75 100644
--- a/Array-Minesweeper/header/UI/UIElement/ButtonView.h
+++ b/Array-Minesweeper/header/UI/UIElement/ButtonView.h
@@ -6,11 +6,17 @@ namespace UI
{
namespace UIElement
{
+ enum class ButtonType
+ {
+ LEFT_MOUSE_BUTTON,
+ RIGHT_MOUSE_BUTTON,
+ };
+
class ButtonView : public ImageView
{
private:
// Define a function pointer type for the callback function
- using CallbackFunction = std::function;
+ using CallbackFunction = std::function;
// Store the callback function
CallbackFunction callback_function = nullptr;
@@ -21,7 +27,8 @@ namespace UI
sf::String button_title;
virtual void handleButtonInteraction();
- virtual bool clickedButton(sf::Sprite* button_sprite, sf::Vector2f mouse_position);
+ virtual bool clickedLeftMouseButton(sf::Sprite* button_sprite, sf::Vector2f mouse_position);
+ virtual bool clickedRightMouseButton(sf::Sprite* button_sprite, sf::Vector2f mouse_position);
public:
ButtonView();
diff --git a/Array-Minesweeper/header/UI/UIElement/ImageView.h b/Array-Minesweeper/header/UI/UIElement/ImageView.h
index aab42783..b9751a93 100644
--- a/Array-Minesweeper/header/UI/UIElement/ImageView.h
+++ b/Array-Minesweeper/header/UI/UIElement/ImageView.h
@@ -20,6 +20,7 @@ namespace UI
virtual void render() override;
virtual void setTexture(sf::String texture_path);
+ virtual void setTextureRect(sf::IntRect texture_rect);
virtual void setScale(float width, float height);
virtual void setPosition(sf::Vector2f position);
virtual void setRotation(float rotation_angle);
diff --git a/Array-Minesweeper/header/UI/UIElement/TextView.h b/Array-Minesweeper/header/UI/UIElement/TextView.h
index 8a83a8e9..79261b9e 100644
--- a/Array-Minesweeper/header/UI/UIElement/TextView.h
+++ b/Array-Minesweeper/header/UI/UIElement/TextView.h
@@ -9,6 +9,7 @@ namespace UI
{
BUBBLE_BOBBLE,
DS_DIGIB,
+ ROBOTO,
};
class TextView : public UIView
@@ -18,6 +19,7 @@ namespace UI
static sf::Font font_bubble_bobble;
static sf::Font font_DS_DIGIB;
+ static sf::Font font_roboto;
sf::Text text;
diff --git a/Array-Minesweeper/header/UI/UIService.h b/Array-Minesweeper/header/UI/UIService.h
index 5bbd6347..372097ab 100644
--- a/Array-Minesweeper/header/UI/UIService.h
+++ b/Array-Minesweeper/header/UI/UIService.h
@@ -1,8 +1,9 @@
#pragma once
#include "../../header/UI/MainMenu/MainMenuUIController.h"
#include "../../header/UI/SplashScreen/SplashScreenUIController.h"
-#include "../../header/UI/Credits/CreditsScreenUIController.h"
#include "../../header/UI/Instructions/InstructionsScreenUIController.h"
+#include "../../header/UI/Credits/CreditsScreenUIController.h"
+#include "../../header/UI/Gameplay/GameplayUIController.h"
#include "../../header/UI/Interface/IUIController.h"
namespace UI
@@ -10,10 +11,11 @@ namespace UI
class UIService
{
private:
- SplashScreen::SplashScreenUIController* splash_screen_controller;
- MainMenu::MainMenuUIController* main_menu_controller;
- Credits::CreditsScreenUIController* credit_screen_controller;
- Instructions::InstructionsScreenUIController* instructions_screen_controller;
+ SplashScreen::SplashScreenUIController* splash_screen_ui_controller;
+ MainMenu::MainMenuUIController* main_menu_ui_controller;
+ Instructions::InstructionsScreenUIController* instructions_screen_ui_controller;
+ GameplayUI::GameplayUIController* gameplay_ui_controller;
+ Credits::CreditsScreenUIController* credit_screen_ui_controller;
void createControllers();
void initializeControllers();
diff --git a/Array-Minesweeper/source/Event/EventService.cpp b/Array-Minesweeper/source/Event/EventService.cpp
index 57e2d0c7..caedcfc4 100644
--- a/Array-Minesweeper/source/Event/EventService.cpp
+++ b/Array-Minesweeper/source/Event/EventService.cpp
@@ -19,8 +19,8 @@ namespace Event
void EventService::update()
{
- updateButtonsState(left_mouse_button_state);
- updateButtonsState(right_mouse_button_state);
+ updateButtonsState(left_mouse_button_state, sf::Mouse::Left);
+ updateButtonsState(right_mouse_button_state, sf::Mouse::Right);
}
void EventService::processEvents()
@@ -36,9 +36,9 @@ namespace Event
}
}
- void EventService::updateButtonsState(ButtonState& button_state)
+ void EventService::updateButtonsState(ButtonState& button_state, sf::Mouse::Button button_type)
{
- if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
+ if (sf::Mouse::isButtonPressed(button_type))
{
switch (button_state)
{
diff --git a/Array-Minesweeper/source/Gameplay/Board/BoardController.cpp b/Array-Minesweeper/source/Gameplay/Board/BoardController.cpp
new file mode 100644
index 00000000..ce6ceed0
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/Board/BoardController.cpp
@@ -0,0 +1,361 @@
+#include "../../header/Gameplay/Board/BoardController.h"
+#include "../../header/Gameplay/Board/BoardView.h"
+#include "../../header/Gameplay/Cell/CellController.h"
+#include "../../header/Gameplay/Cell/CellModel.h"
+#include "../../header/Global/ServiceLocator.h"
+#include "../../header/Sound/SoundService.h"
+
+namespace Gameplay
+{
+ namespace Board
+ {
+ using namespace Cell;
+ using namespace Global;
+ using namespace Sound;
+
+ BoardController::BoardController() : random_engine(random_device())
+ {
+ board_view = new BoardView(this);
+ createBoard();
+ }
+
+ BoardController::~BoardController()
+ {
+ destroy();
+ }
+
+ void BoardController::createBoard()
+ {
+ for (int a = 0; a < number_of_rows; a++)
+ {
+ for (int b = 0; b < number_of_colums; b++)
+ {
+ board[a][b] = new CellController(sf::Vector2i(a, b));
+ }
+ }
+ }
+
+ void BoardController::initialize()
+ {
+ board_view->initialize();
+ initializeCells();
+ reset();
+ }
+
+ void BoardController::initializeCells()
+ {
+ float cell_width = board_view->getCellWidth();
+ float cell_height = board_view->getCellHeight();
+
+ for (int a = 0; a < number_of_rows; a++)
+ {
+ for (int b = 0; b < number_of_colums; b++)
+ {
+ board[a][b]->initialize(cell_width, cell_height);
+ }
+ }
+ }
+
+ void BoardController::update()
+ {
+ board_view->update();
+
+ for (int row = 0; row < number_of_rows; ++row)
+ {
+ for (int col = 0; col < number_of_colums; ++col)
+ {
+ board[row][col]->update();
+ }
+ }
+ }
+
+ void BoardController::render()
+ {
+ board_view->render();
+
+ for (int row = 0; row < number_of_rows; ++row)
+ {
+ for (int col = 0; col < number_of_colums; ++col)
+ {
+ board[row][col]->render();
+ }
+ }
+ }
+
+ void BoardController::processCellInput(Cell::CellController* cell_controller, UI::UIElement::ButtonType button_type)
+ {
+ if (board_state == BoardState::COMPLETED)
+ return;
+
+ switch (button_type)
+ {
+ case UI::UIElement::ButtonType::LEFT_MOUSE_BUTTON:
+ openCell(cell_controller->getCellPosition());
+ break;
+ case UI::UIElement::ButtonType::RIGHT_MOUSE_BUTTON:
+ flagCell(cell_controller->getCellPosition());
+ break;
+ }
+ }
+
+ void BoardController::populateBoard(sf::Vector2i cell_position)
+ {
+ populateMines(cell_position);
+ populateCells();
+ }
+
+ void BoardController::populateMines(sf::Vector2i cell_position)
+ {
+ // Co-ordinate distribution i.e. selecting random position for mines.
+ std::uniform_int_distribution x_distribution(0, number_of_colums - 1);
+ std::uniform_int_distribution y_distribution(0, number_of_rows - 1);
+
+ // Generate mines.
+ for (int a = 0; a < mines_count; a++)
+ {
+ int i = static_cast(x_distribution(random_engine));
+ int j = static_cast(y_distribution(random_engine));
+
+ // If the cell is already a mine or it's the same cell that the player wants to open, the loop will run an extra time
+ if (board[i][j]->getCellType() == CellType::MINE || (cell_position.x == i && cell_position.y == j)) a--;
+ else board[i][j]->setCellType(CellType::MINE);
+ }
+ }
+
+ void BoardController::populateCells()
+ {
+ for (int a = 0; a < number_of_rows; a++)
+ {
+ for (int b = 0; b < number_of_colums; b++)
+ {
+ if (board[a][b]->getCellType() != CellType::MINE)
+ {
+ CellType type = static_cast(countMinesAround(sf::Vector2i(a, b)));
+ board[a][b]->setCellType(type);
+ }
+ }
+ }
+ }
+
+ int BoardController::countMinesAround(sf::Vector2i cell_position)
+ {
+ int mines_around = 0;
+
+ for (int a = -1; a < 2; a++)
+ {
+ for (int b = -1; b < 2; b++)
+ {
+ if ((a == 0 && b == 0) || !isValidCellPosition(sf::Vector2i(cell_position.x + a, cell_position.y + b))) continue;
+ if (board[a + cell_position.x][b + cell_position.y]->getCellType() == CellType::MINE) mines_around++;
+ }
+ }
+
+ return mines_around;
+ }
+
+ void BoardController::flagCell(sf::Vector2i cell_position)
+ {
+ switch (board[cell_position.x][cell_position.y]->getCellState())
+ {
+ case::Gameplay::Cell::CellState::FLAGGED:
+ ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::FLAG);
+ flagged_cells--;
+ break;
+ case::Gameplay::Cell::CellState::HIDDEN:
+ ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::FLAG);
+ flagged_cells++;
+ break;
+ }
+
+ board[cell_position.x][cell_position.y]->flagCell();
+ }
+
+ void BoardController::openCell(sf::Vector2i cell_position)
+ {
+ if (board[cell_position.x][cell_position.y]->canOpenCell())
+ {
+ if (board_state == BoardState::FIRST_CELL)
+ {
+ populateBoard(cell_position);
+ board_state = BoardState::PLAYING;
+ }
+
+ processCellType(cell_position);
+ board[cell_position.x][cell_position.y]->openCell();
+
+ if (areAllCellOpen())
+ ServiceLocator::getInstance()->getGameplayService()->endGame(GameResult::WON);
+ }
+ }
+
+ void BoardController::flagAllMines()
+ {
+ for (int row = 0; row < number_of_rows; ++row)
+ {
+ for (int col = 0; col < number_of_colums; ++col)
+ {
+ if (board[row][col]->getCellType() == CellType::MINE && board[row][col]->getCellState() != CellState::FLAGGED)
+ flagCell(sf::Vector2i(row, col));
+ }
+ }
+ }
+
+ void BoardController::processCellType(sf::Vector2i cell_position)
+ {
+ switch (board[cell_position.x][cell_position.y]->getCellType())
+ {
+ case::Gameplay::Cell::CellType::EMPTY:
+ processEmptyCell(cell_position);
+ break;
+ case::Gameplay::Cell::CellType::MINE:
+ processMineCell(cell_position);
+ break;
+ default:
+ ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK);
+ break;
+ }
+ }
+
+ void BoardController::processEmptyCell(sf::Vector2i cell_position)
+ {
+ ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK);
+ openEmptyCells(cell_position);
+ }
+
+ void BoardController::processMineCell(sf::Vector2i cell_position)
+ {
+ ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::EXPLOSION);
+ ServiceLocator::getInstance()->getGameplayService()->endGame(GameResult::LOST);
+ }
+
+ void BoardController::openEmptyCells(sf::Vector2i cell_position)
+ {
+ switch (board[cell_position.x][cell_position.y]->getCellState())
+ {
+ case::Gameplay::Cell::CellState::OPEN:
+ return;
+ case::Gameplay::Cell::CellState::FLAGGED:
+ flagged_cells--;
+ default:
+ board[cell_position.x][cell_position.y]->openCell();
+ }
+
+ for (int a = -1; a < 2; a++)
+ {
+ for (int b = -1; b < 2; b++)
+ {
+ if ((a == 0 && b == 0) || !isValidCellPosition(sf::Vector2i(a + cell_position.x, b + cell_position.y))) continue;
+
+ sf::Vector2i next_cell_position = sf::Vector2i(a + cell_position.x, b + cell_position.y);
+ openCell(next_cell_position);
+ }
+ }
+ }
+
+ void BoardController::openAllCells()
+ {
+ for (int a = 0; a < number_of_rows; ++a)
+ {
+ for (int b = 0; b < number_of_colums; ++b)
+ {
+ board[a][b]->openCell();
+ }
+ }
+ }
+
+ bool BoardController::isValidCellPosition(sf::Vector2i cell_position)
+ {
+ return (cell_position.x >= 0 && cell_position.y >= 0 && cell_position.x < number_of_colums && cell_position.y < number_of_rows);
+ }
+
+ bool BoardController::areAllCellOpen()
+ {
+ int total_cell_count = number_of_rows * number_of_colums;
+ int open_cell_count = 0;
+
+ for (int a = 0; a < number_of_rows; a++)
+ {
+ for (int b = 0; b < number_of_colums; b++)
+ {
+ if (board[a][b]->getCellState() == CellState::OPEN)
+ {
+ open_cell_count++;
+ }
+ }
+ }
+
+ return (total_cell_count - open_cell_count == mines_count);
+ }
+
+ void BoardController::showBoard()
+ {
+
+ switch (ServiceLocator::getInstance()->getBoardService()->getBoardState())
+ {
+ case Gameplay::Board::BoardState::FIRST_CELL:
+ populateBoard(sf::Vector2i(0, 0));
+ openAllCells();
+ break;
+ case Gameplay::Board::BoardState::PLAYING:
+ openAllCells();
+ break;
+ case Gameplay::Board::BoardState::COMPLETED:
+ break;
+ default:
+ break;
+ }
+ }
+
+
+ void BoardController::reset()
+ {
+ resetBoard();
+
+ board_state = BoardState::FIRST_CELL;
+ flagged_cells = 0;
+ }
+
+ void BoardController::resetBoard()
+ {
+ for (int row = 0; row < number_of_rows; ++row)
+ {
+ for (int col = 0; col < number_of_colums; ++col)
+ {
+ board[row][col]->reset();
+ }
+ }
+ }
+
+ void BoardController::deleteBoard()
+ {
+ for (int a = 0; a < number_of_rows; a++)
+ {
+ for (int b = 0; b < number_of_colums; b++)
+ {
+ delete board[a][b];
+ }
+ }
+ }
+
+ void BoardController::destroy()
+ {
+ deleteBoard();
+ delete (board_view);
+ }
+
+ BoardState BoardController::getBoardState()
+ {
+ return board_state;
+ }
+
+ void BoardController::setBoardState(BoardState state)
+ {
+ board_state = state;
+ }
+
+ int BoardController::getMinesCount()
+ {
+ return mines_count - flagged_cells;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/Gameplay/Board/BoardService.cpp b/Array-Minesweeper/source/Gameplay/Board/BoardService.cpp
new file mode 100644
index 00000000..58ef1f62
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/Board/BoardService.cpp
@@ -0,0 +1,74 @@
+#include "../../header/Gameplay/Board/BoardService.h"
+
+#include "../../../header/Gameplay/GameplayController.h"
+
+namespace Gameplay
+{
+ namespace Board
+ {
+ using namespace Cell;
+ using namespace UI;
+ using namespace UI::UIElement;
+
+ BoardService::BoardService()
+ {
+ board_controller = nullptr;
+ }
+
+ BoardService::~BoardService()
+ {
+ destroy();
+ }
+
+ void BoardService::initialize()
+ {
+ board_controller = new BoardController();
+ board_controller->initialize();
+ }
+
+ void BoardService::update()
+ {
+ board_controller->update();
+ }
+
+ void BoardService::render()
+ {
+ board_controller->render();
+ }
+
+ void BoardService::processCellInput(CellController* cell_controller, ButtonType button_type)
+ {
+ board_controller->processCellInput(cell_controller, button_type);
+ }
+
+ BoardState BoardService::getBoardState()
+ {
+ return board_controller->getBoardState();
+ }
+
+ void BoardService::setBoardState(BoardState state)
+ {
+ board_controller->setBoardState(state);
+ }
+
+ void BoardService::resetBoard()
+ {
+ board_controller->reset();
+ }
+
+ int BoardService::getMinesCount()
+ {
+ return board_controller->getMinesCount();
+ }
+
+ void BoardService::flagAllMines() { board_controller->flagAllMines(); }
+
+ void BoardService::showBoard() { board_controller->showBoard(); }
+
+ void BoardService::destroy()
+ {
+ delete(board_controller);
+ }
+
+ }
+}
diff --git a/Array-Minesweeper/source/Gameplay/Board/BoardView.cpp b/Array-Minesweeper/source/Gameplay/Board/BoardView.cpp
new file mode 100644
index 00000000..92099a75
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/Board/BoardView.cpp
@@ -0,0 +1,69 @@
+#include "../../header/Gameplay/Board/BoardView.h"
+#include "../../header/Gameplay/Board/BoardController.h"
+#include "../../header/Global/Config.h"
+#include "../../header/Global/ServiceLocator.h"
+
+namespace Gameplay
+{
+ namespace Board
+ {
+ using namespace UI::UIElement;
+ using namespace Cell;
+ using namespace Global;
+
+ BoardView::BoardView(BoardController* controller)
+ {
+ board_controller = controller;
+ board_image = new ImageView();
+ background_image = new ImageView();
+ }
+
+ BoardView::~BoardView()
+ {
+ delete (board_image);
+ delete (background_image);
+ }
+
+ void BoardView::initialize()
+ {
+ initializeBackgroudImage();
+ initializeBoardImage();
+ }
+
+ void BoardView::initializeBackgroudImage()
+ {
+ sf::RenderWindow* game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow();
+
+ background_image->initialize(Config::background_texture_path, game_window->getSize().x, game_window->getSize().y, sf::Vector2f(0, 0));
+ background_image->setImageAlpha(background_alpha);
+ }
+
+ void BoardView::initializeBoardImage()
+ {
+ board_image->initialize(Config::board_texture_path, board_width, board_height, sf::Vector2f(0, 0));
+ board_image->setCentreAlinged();
+ }
+
+ void BoardView::update()
+ {
+ background_image->update();
+ board_image->update();
+ }
+
+ void BoardView::render()
+ {
+ background_image->render();
+ board_image->render();
+ }
+
+ float BoardView::getCellWidth()
+ {
+ return (board_width - board_width_offset) / static_cast(BoardController::number_of_colums);
+ }
+
+ float BoardView::getCellHeight()
+ {
+ return (board_height - board_height_offset) / static_cast(BoardController::number_of_rows);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/Gameplay/Cell/CellController.cpp b/Array-Minesweeper/source/Gameplay/Cell/CellController.cpp
new file mode 100644
index 00000000..8e0180c3
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/Cell/CellController.cpp
@@ -0,0 +1,110 @@
+#include "../../header/Gameplay/Cell/CellController.h"
+#include "../../header/Gameplay/Cell/CellModel.h"
+#include "../../header/Gameplay/Cell/CellView.h"
+#include "../../header/Sound/SoundService.h"
+#include "../../header/Global/ServiceLocator.h"
+
+namespace Gameplay
+{
+ namespace Cell
+ {
+ using namespace Global;
+ using namespace Sound;
+
+ CellController::CellController(sf::Vector2i grid_position)
+ {
+ cell_model = new CellModel(grid_position);
+ cell_view = new CellView(this);
+ }
+
+ CellController::~CellController()
+ {
+ destroy();
+ }
+
+ void CellController::initialize(float cell_width, float cell_height)
+ {
+ cell_view->initialize(cell_width, cell_height);
+ }
+
+ void CellController::update()
+ {
+ cell_view->update();
+ }
+
+ void CellController::render()
+ {
+ cell_view->render();
+ }
+
+ void CellController::flagCell()
+ {
+ if (ServiceLocator::getInstance()->getBoardService()->getBoardState() == Gameplay::Board::BoardState::COMPLETED)
+ {
+ cell_model->setCellState(CellState::FLAGGED);
+ return;
+ }
+
+ switch (cell_model->getCellState())
+ {
+ case::Gameplay::Cell::CellState::FLAGGED:
+ cell_model->setCellState(CellState::HIDDEN);
+ break;
+ case::Gameplay::Cell::CellState::HIDDEN:
+ cell_model->setCellState(CellState::FLAGGED);
+ break;
+ }
+ }
+
+ void CellController::openCell()
+ {
+ setCellState(CellState::OPEN);
+ }
+
+ bool CellController::canOpenCell()
+ {
+ return cell_model->getCellState() != CellState::FLAGGED && cell_model->getCellState() != CellState::OPEN;
+ }
+
+ CellState CellController::getCellState()
+ {
+ return cell_model->getCellState();
+ }
+
+ void CellController::setCellState(CellState state)
+ {
+ cell_model->setCellState(state);
+ }
+
+ CellType CellController::getCellType()
+ {
+ return cell_model->getCellType();
+ }
+
+ void CellController::setCellType(CellType type)
+ {
+ cell_model->setCellType(type);
+ }
+
+ sf::Vector2i CellController::getCellPosition()
+ {
+ return cell_model->getCellPosition();
+ }
+
+ int CellController::getMinesAround()
+ {
+ return cell_model->getMinesAround();
+ }
+
+ void CellController::reset()
+ {
+ cell_model->reset();
+ }
+
+ void CellController::destroy()
+ {
+ delete (cell_view);
+ delete (cell_model);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/Gameplay/Cell/CellModel.cpp b/Array-Minesweeper/source/Gameplay/Cell/CellModel.cpp
new file mode 100644
index 00000000..8e76e19c
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/Cell/CellModel.cpp
@@ -0,0 +1,62 @@
+#include "../../header/Gameplay/Cell/CellModel.h"
+
+namespace Gameplay
+{
+ namespace Cell
+ {
+ CellModel::CellModel(sf::Vector2i grid_position)
+ {
+ reset();
+ position = grid_position;
+ }
+
+ CellModel::~CellModel() = default;
+
+ CellState CellModel::getCellState()
+ {
+ return cell_state;
+ }
+
+ void CellModel::setCellState(CellState state)
+ {
+ cell_state = state;
+ }
+
+ CellType CellModel::getCellType()
+ {
+ return cell_type;
+ }
+
+ void CellModel::setCellType(CellType type)
+ {
+ cell_type = type;
+ }
+
+ sf::Vector2i CellModel::getCellPosition()
+ {
+ return position;
+ }
+
+ void CellModel::setCellPosition(sf::Vector2i grid_position)
+ {
+ position = grid_position;
+ }
+
+ int CellModel::getMinesAround()
+ {
+ return mines_around;
+ }
+
+ void CellModel::setMinesAround(int mine_count)
+ {
+ mines_around = mine_count;
+ }
+
+ void CellModel::reset()
+ {
+ cell_state = CellState::HIDDEN;
+ cell_type = CellType::EMPTY;
+ mines_around = 0;
+ }
+ }
+}
diff --git a/Array-Minesweeper/source/Gameplay/Cell/CellView.cpp b/Array-Minesweeper/source/Gameplay/Cell/CellView.cpp
new file mode 100644
index 00000000..b247b786
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/Cell/CellView.cpp
@@ -0,0 +1,93 @@
+#include "../../header/Gameplay/Cell/CellView.h"
+
+#include
+
+#include "../../header/Gameplay/Cell/CellModel.h"
+#include "../../header/Gameplay/Cell/CellController.h"
+#include "../../header/Global/Config.h"
+#include "../../header/Global/ServiceLocator.h"
+#include "../../header/Gameplay/GameplayService.h"
+#include "../../header/Sound/SoundService.h"
+
+namespace Gameplay
+{
+ namespace Cell
+ {
+ using namespace UI::UIElement;
+ using namespace Global;
+ using namespace Sound;
+
+ CellView::CellView(CellController* controller)
+ {
+ cell_controller = controller;
+ cell_button = new ButtonView();
+ }
+
+ CellView::~CellView() { delete (cell_button); }
+
+ void CellView::initialize(float width, float height)
+ {
+ initializeButtonImage(width, height);
+ }
+
+ void CellView::initializeButtonImage(float width, float height)
+ {
+ sf::Vector2f cell_screen_position = getCellScreenPosition(width, height);
+
+ cell_button->initialize("Cell", Config::cells_texture_path, width*slice_count, height, cell_screen_position);
+
+ registerButtonCallback();
+ }
+
+ sf::Vector2f CellView::getCellScreenPosition(float width, float height)
+ {
+ sf::Vector2i grid_position = cell_controller->getCellPosition();
+
+ float x_screen_position = cell_left_offset + grid_position.x * width;
+ float y_screen_position = cell_top_offset + grid_position.y * height;
+
+ return sf::Vector2f(x_screen_position, y_screen_position);
+ }
+
+ void CellView::update()
+ {
+ cell_button->update();
+ }
+
+ void CellView::render()
+ {
+ setCellTexture();
+ cell_button->render();
+ }
+
+ void CellView::setCellTexture()
+ {
+ int index = static_cast(cell_controller->getCellType());
+
+ switch (cell_controller->getCellState())
+ {
+ case::Gameplay::Cell::CellState::HIDDEN:
+ cell_button->setTextureRect(sf::IntRect(10 * tile_size, 0, tile_size, tile_size));
+ break;
+
+ case::Gameplay::Cell::CellState::OPEN:
+ cell_button->setTextureRect(sf::IntRect(index * tile_size, 0, tile_size, tile_size));
+ break;
+
+ case::Gameplay::Cell::CellState::FLAGGED:
+ cell_button->setTextureRect(sf::IntRect(11 * tile_size, 0, tile_size, tile_size));
+ break;
+ }
+ }
+
+ void CellView::registerButtonCallback()
+ {
+ cell_button->registerCallbackFuntion(std::bind(&CellView::cellButtonCallback, this, std::placeholders::_1));
+ }
+
+ void CellView::cellButtonCallback(ButtonType button_type)
+ {
+ ServiceLocator::getInstance()->getBoardService()->processCellInput(cell_controller, button_type);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/Gameplay/GameplayController.cpp b/Array-Minesweeper/source/Gameplay/GameplayController.cpp
new file mode 100644
index 00000000..5129721c
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/GameplayController.cpp
@@ -0,0 +1,95 @@
+#include "../../header/Gameplay/GameplayController.h"
+#include "../../header/Gameplay/Board/BoardService.h"
+#include "../../header/Time/TimeService.h"
+#include "../../header/Global/ServiceLocator.h"
+#include "../../header/Main/GameService.h"
+
+namespace Gameplay
+{
+ using namespace Main;
+ using namespace Board;
+ using namespace Global;
+ using namespace Cell;
+ using namespace UI::UIElement;
+ using namespace Time;
+
+ GameplayController::~GameplayController() { board_service = nullptr; }
+
+ void GameplayController::initialize()
+ {
+ board_service = ServiceLocator::getInstance()->getBoardService();
+ }
+
+ void GameplayController::update()
+ {
+ updateRemainingTime();
+
+ if (isTimeOver())
+ endGame(GameResult::LOST);
+ }
+
+ void GameplayController::render() { }
+
+ void GameplayController::updateRemainingTime()
+ {
+ if (game_result == GameResult::WON)
+ return;
+ remaining_time -= ServiceLocator::getInstance()->getTimeService()->getDeltaTime();
+ }
+
+ bool GameplayController::isTimeOver() { return (remaining_time <= 1); }
+
+ void GameplayController::restart()
+ {
+ game_result = GameResult::NONE;
+ board_service->resetBoard();
+ remaining_time = max_level_duration;
+ }
+
+ int GameplayController::getMinesCount() { return board_service->getMinesCount(); }
+
+ float GameplayController::getRemainingTime() { return remaining_time; }
+
+ void GameplayController::endGame(GameResult result)
+ {
+ switch(result)
+ {
+ case GameResult::WON:
+ gameWon();
+ break;
+ case GameResult::LOST:
+ gameLost();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void GameplayController::gameWon()
+ {
+ game_result = GameResult::WON;
+ board_service->flagAllMines();
+ board_service->setBoardState(BoardState::COMPLETED);
+ ServiceLocator::getInstance()->getSoundService()->playSound(Sound::SoundType::GAME_WON);
+ }
+
+ void GameplayController::gameLost()
+ {
+ if(game_result == GameResult::NONE)
+ {
+ game_result = GameResult::LOST;
+ beginGameOverTimer();
+ board_service->showBoard();
+ board_service->setBoardState(BoardState::COMPLETED);
+ }
+ else
+ {
+ showCredits();
+ }
+
+ }
+
+ void GameplayController::beginGameOverTimer() { remaining_time = game_over_time; }
+
+ void GameplayController::showCredits() { GameService::setGameState(GameState::CREDITS); }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/Gameplay/GameplayService.cpp b/Array-Minesweeper/source/Gameplay/GameplayService.cpp
new file mode 100644
index 00000000..71eedafa
--- /dev/null
+++ b/Array-Minesweeper/source/Gameplay/GameplayService.cpp
@@ -0,0 +1,60 @@
+#include "../../header/Gameplay/GameplayService.h"
+
+namespace Gameplay
+{
+ GameplayService::GameplayService()
+ {
+ gameplay_controller = nullptr;
+ createController();
+ }
+
+ GameplayService::~GameplayService()
+ {
+ destroy();
+ }
+
+ void GameplayService::createController()
+ {
+ gameplay_controller = new GameplayController();
+ }
+
+ void GameplayService::initialize()
+ {
+ gameplay_controller->initialize();
+ }
+
+ void GameplayService::update()
+ {
+ gameplay_controller->update();
+ }
+
+ void GameplayService::render()
+ {
+ gameplay_controller->render();
+ }
+
+ void GameplayService::startGame()
+ {
+ gameplay_controller->restart();
+ }
+
+ void GameplayService::endGame(GameResult result)
+ {
+ gameplay_controller->endGame(result);
+ }
+
+ int GameplayService::getMinesCount()
+ {
+ return gameplay_controller->getMinesCount();
+ }
+
+ float GameplayService::getRemainingTime()
+ {
+ return gameplay_controller->getRemainingTime();
+ }
+
+ void GameplayService::destroy()
+ {
+ delete(gameplay_controller);
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/Gobal/ServiceLocator.cpp b/Array-Minesweeper/source/Gobal/ServiceLocator.cpp
index bbe7a26e..f7d640c8 100644
--- a/Array-Minesweeper/source/Gobal/ServiceLocator.cpp
+++ b/Array-Minesweeper/source/Gobal/ServiceLocator.cpp
@@ -1,5 +1,5 @@
#include "../../header/Global/ServiceLocator.h"
-
+#include "../../header/Main/GameService.h"
namespace Global
{
@@ -7,6 +7,10 @@ namespace Global
using namespace Event;
using namespace Sound;
using namespace UI;
+ using namespace Gameplay;
+ using namespace Board;
+ using namespace Main;
+ using namespace Time;
ServiceLocator::ServiceLocator()
{
@@ -14,6 +18,9 @@ namespace Global
event_service = nullptr;
sound_service = nullptr;
ui_service = nullptr;
+ gameplay_service = nullptr;
+ time_service = nullptr;
+ board_service = nullptr;
createServices();
}
@@ -26,27 +33,48 @@ namespace Global
graphic_service = new GraphicService();
sound_service = new SoundService();
ui_service = new UIService();
+ gameplay_service = new GameplayService();
+ time_service = new TimeService();
+ board_service = new BoardService();
}
void ServiceLocator::initialize()
{
graphic_service->initialize();
+ time_service->initialize();
sound_service->initialize();
event_service->initialize();
ui_service->initialize();
+ gameplay_service->initialize();
+ board_service->initialize();
}
void ServiceLocator::update()
{
+ time_service->update();
event_service->update();
- ui_service->update();
graphic_service->update();
+
+ if (GameService::getGameState() == GameState::GAMEPLAY)
+ {
+ gameplay_service->update();
+ board_service->update();
+ }
+
+ ui_service->update();
}
void ServiceLocator::render()
{
- ui_service->render();
graphic_service->render();
+
+ if (GameService::getGameState() == GameState::GAMEPLAY)
+ {
+ gameplay_service->render();
+ board_service->render();
+ }
+
+ ui_service->render();
}
void ServiceLocator::clearAllServices()
@@ -55,6 +83,9 @@ namespace Global
delete(graphic_service);
delete(sound_service);
delete(event_service);
+ delete(gameplay_service);
+ delete(time_service);
+ delete(board_service);
}
ServiceLocator* ServiceLocator::getInstance()
@@ -71,5 +102,12 @@ namespace Global
UIService* ServiceLocator::getUIService() { return ui_service; }
+ GameplayService* ServiceLocator::getGameplayService() { return gameplay_service; }
+
+ Time::TimeService* ServiceLocator::getTimeService() { return time_service; }
+
+ Board::BoardService* ServiceLocator::getBoardService() { return board_service; }
+
+
void ServiceLocator::deleteServiceLocator() { delete(this); }
}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/Sound/SoundService.cpp b/Array-Minesweeper/source/Sound/SoundService.cpp
index ab41f71a..dc2247eb 100644
--- a/Array-Minesweeper/source/Sound/SoundService.cpp
+++ b/Array-Minesweeper/source/Sound/SoundService.cpp
@@ -20,7 +20,13 @@ namespace Sound
void SoundService::loadSoundFromFile()
{
if (!buffer_button_click.loadFromFile(Config::button_click_sound_path))
- printf("Error loading background music file");
+ printf("Error loading sound file");
+ if (!buffer_flag_sound.loadFromFile(Config::flag_sound_path))
+ printf("Error loading sound file");
+ if (!buffer_explosion.loadFromFile(Config::explosion_sound_path))
+ printf("Error loading sound file");
+ if (!buffer_game_won.loadFromFile(Config::game_won_sound_path))
+ printf("Error loading sound file");
}
void SoundService::playSound(SoundType soundType)
@@ -30,6 +36,15 @@ namespace Sound
case SoundType::BUTTON_CLICK:
sound_effect.setBuffer(buffer_button_click);
break;
+ case SoundType::FLAG:
+ sound_effect.setBuffer(buffer_flag_sound);
+ break;
+ case SoundType::EXPLOSION:
+ sound_effect.setBuffer(buffer_explosion);
+ break;
+ case SoundType::GAME_WON:
+ sound_effect.setBuffer(buffer_game_won);
+ break;
default:
printf("Invalid sound type");
return;
diff --git a/Array-Minesweeper/source/Time/TimeService.cpp b/Array-Minesweeper/source/Time/TimeService.cpp
new file mode 100644
index 00000000..6d4231b5
--- /dev/null
+++ b/Array-Minesweeper/source/Time/TimeService.cpp
@@ -0,0 +1,42 @@
+#include "../../header/Time/TimeService.h"
+
+namespace Time
+{
+ void TimeService::initialize()
+ {
+ previous_time = std::chrono::steady_clock::now();
+ delta_time = 0;
+ }
+
+ void TimeService::update()
+ {
+ updateDeltaTime();
+ }
+
+ float TimeService::getDeltaTime()
+ {
+ return delta_time;
+ }
+
+ void TimeService::updateDeltaTime()
+ {
+ delta_time = calculateDeltaTime();
+ updatePreviousTime();
+ }
+
+ float TimeService::calculateDeltaTime()
+ {
+ // Calculate time difference in microseconds between the current and previous frame.
+ int delta = std::chrono::duration_cast(
+ std::chrono::steady_clock::now() - previous_time).count();
+
+ // To convert delta time from microseconds into seconds.
+ return static_cast(delta) / static_cast(1000000);
+ }
+
+ // Update previous_time to the current time
+ void TimeService::updatePreviousTime()
+ {
+ previous_time = std::chrono::steady_clock::now();
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/UI/Gameplay/GameplayUIController.cpp b/Array-Minesweeper/source/UI/Gameplay/GameplayUIController.cpp
new file mode 100644
index 00000000..55e28427
--- /dev/null
+++ b/Array-Minesweeper/source/UI/Gameplay/GameplayUIController.cpp
@@ -0,0 +1,136 @@
+#include "../../header/UI/Gameplay/GameplayUIController.h"
+#include "../../header/Global/Config.h"
+#include "../../header/Global/ServiceLocator.h"
+#include "../../header/Gameplay/GameplayService.h"
+#include "../../header/Sound/SoundService.h"
+#include "../../header/Main/GameService.h"
+#include
+#include
+
+namespace UI
+{
+ namespace GameplayUI
+ {
+ using namespace Main;
+ using namespace Sound;
+ using namespace UIElement;
+ using namespace Global;
+
+ GameplayUIController::GameplayUIController()
+ {
+ createButton();
+ createTexts();
+ }
+
+ GameplayUIController::~GameplayUIController()
+ {
+ destroy();
+ }
+
+ void GameplayUIController::initialize()
+ {
+ initializeButton();
+ initializeTexts();
+ }
+
+ void GameplayUIController::createButton()
+ {
+ restart_button = new ButtonView();
+ }
+
+ void GameplayUIController::createTexts()
+ {
+ mine_text = new TextView();
+ time_text = new TextView();
+ }
+
+ void GameplayUIController::initializeButton()
+ {
+ restart_button->initialize("Restart Button",
+ Config::restart_button_texture_path,
+ button_width, button_height,
+ sf::Vector2f(restart_button_left_offset, restart_button_top_offset));
+
+ registerButtonCallback();
+ }
+
+ void GameplayUIController::initializeTexts()
+ {
+ initializeMineText();
+ initializeTimeText();
+ }
+
+ void GameplayUIController::initializeMineText()
+ {
+ mine_text->initialize("000", sf::Vector2f(mine_text_left_offset, mine_text_top_offset), FontType::ROBOTO, font_size, text_color);
+ }
+
+ void GameplayUIController::initializeTimeText()
+ {
+ time_text->initialize("000", sf::Vector2f(time_text_left_offset, time_text_top_offset), FontType::ROBOTO, font_size, text_color);
+ }
+
+ void GameplayUIController::update()
+ {
+ restart_button->update();
+ updateMineText();
+ updateTimeText();
+ }
+
+ void GameplayUIController::render()
+ {
+ restart_button->render();
+ mine_text->render();
+ time_text->render();
+ }
+
+ void GameplayUIController::show()
+ {
+ restart_button->show();
+ mine_text->show();
+ time_text->show();
+ }
+
+ void GameplayUIController::updateMineText()
+ {
+ int mines_count = ServiceLocator::getInstance()->getGameplayService()->getMinesCount();
+
+ std::stringstream stream;
+ stream << std::setw(3) << std::setfill('0') << mines_count;
+ std::string string_mine_count = stream.str();
+
+ mine_text->setText(string_mine_count);
+ mine_text->update();
+ }
+
+ void GameplayUIController::updateTimeText()
+ {
+ int remaining_time = ServiceLocator::getInstance()->getGameplayService()->getRemainingTime();
+
+ std::stringstream stream;
+ stream << std::setw(3) << std::setfill('0') << remaining_time;
+ std::string string_remaining_time = stream.str();
+
+ time_text->setText(string_remaining_time);
+ time_text->update();
+ }
+
+ void GameplayUIController::restartButtonCallback()
+ {
+ ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK);
+ ServiceLocator::getInstance()->getGameplayService()->startGame();
+ }
+
+ void GameplayUIController::registerButtonCallback()
+ {
+ restart_button->registerCallbackFuntion(std::bind(&GameplayUIController::restartButtonCallback, this));
+ }
+
+ void GameplayUIController::destroy()
+ {
+ delete (restart_button);
+ delete (mine_text);
+ delete (time_text);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Array-Minesweeper/source/UI/MainMenu/MainMenuUIController.cpp b/Array-Minesweeper/source/UI/MainMenu/MainMenuUIController.cpp
index a4e5ac85..e43ccc57 100644
--- a/Array-Minesweeper/source/UI/MainMenu/MainMenuUIController.cpp
+++ b/Array-Minesweeper/source/UI/MainMenu/MainMenuUIController.cpp
@@ -1,10 +1,10 @@
#include "../../header/UI/MainMenu/MainMenuUIController.h"
#include "../../header/Main/GameService.h"
+#include "../../header/Global/ServiceLocator.h"
#include "../../header/Graphics/GraphicService.h"
#include "../../header/Sound/SoundService.h"
#include "../../header/Event/EventService.h"
#include "../../header/Global/Config.h"
-#include "../../header/Global/ServiceLocator.h"
namespace UI
{
@@ -12,9 +12,9 @@ namespace UI
{
using namespace Global;
using namespace Graphics;
+ using namespace Main;
using namespace UIElement;
using namespace Sound;
- using namespace Main;
MainMenuUIController::MainMenuUIController()
{
@@ -74,8 +74,9 @@ namespace UI
void MainMenuUIController::playButtonCallback()
{
- // GameState will change to gameplay state.
ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK);
+ GameService::setGameState(GameState::GAMEPLAY);
+ ServiceLocator::getInstance()->getGameplayService()->startGame();
}
void MainMenuUIController::instructionsButtonCallback()
diff --git a/Array-Minesweeper/source/UI/UIElement/ButtonView.cpp b/Array-Minesweeper/source/UI/UIElement/ButtonView.cpp
index 8490dc4f..044ed297 100644
--- a/Array-Minesweeper/source/UI/UIElement/ButtonView.cpp
+++ b/Array-Minesweeper/source/UI/UIElement/ButtonView.cpp
@@ -44,18 +44,29 @@ namespace UI
{
sf::Vector2f mouse_position = sf::Vector2f(sf::Mouse::getPosition(*game_window));
- if (clickedButton(&image_sprite, mouse_position))
+ if (clickedLeftMouseButton(&image_sprite, mouse_position))
{
- if (callback_function) callback_function();
+ if (callback_function) callback_function(ButtonType::LEFT_MOUSE_BUTTON);
+ }
+
+ if (clickedRightMouseButton(&image_sprite, mouse_position))
+ {
+ if (callback_function) callback_function(ButtonType::RIGHT_MOUSE_BUTTON);
}
}
- bool ButtonView::clickedButton(sf::Sprite* button_sprite, sf::Vector2f mouse_position)
+ bool ButtonView::clickedLeftMouseButton(sf::Sprite* button_sprite, sf::Vector2f mouse_position)
{
return ServiceLocator::getInstance()->getEventService()->pressedLeftMouseButton() &&
button_sprite->getGlobalBounds().contains(mouse_position);
}
+ bool ButtonView::clickedRightMouseButton(sf::Sprite* button_sprite, sf::Vector2f mouse_position)
+ {
+ return ServiceLocator::getInstance()->getEventService()->pressedRightMouseButton() &&
+ button_sprite->getGlobalBounds().contains(mouse_position);
+ }
+
void ButtonView::printButtonClicked()
{
printf("Clicked %s\n", button_title.toAnsiString().c_str());
diff --git a/Array-Minesweeper/source/UI/UIElement/ImageView.cpp b/Array-Minesweeper/source/UI/UIElement/ImageView.cpp
index e19b770d..e6f2e647 100644
--- a/Array-Minesweeper/source/UI/UIElement/ImageView.cpp
+++ b/Array-Minesweeper/source/UI/UIElement/ImageView.cpp
@@ -39,6 +39,11 @@ namespace UI
}
}
+ void ImageView::setTextureRect(sf::IntRect texture_rect)
+ {
+ image_sprite.setTextureRect(texture_rect);
+ }
+
void ImageView::setScale(float width, float height)
{
float scale_x = width / image_sprite.getTexture()->getSize().x;
diff --git a/Array-Minesweeper/source/UI/UIElement/TextView.cpp b/Array-Minesweeper/source/UI/UIElement/TextView.cpp
index ade1cbc4..d21f453f 100644
--- a/Array-Minesweeper/source/UI/UIElement/TextView.cpp
+++ b/Array-Minesweeper/source/UI/UIElement/TextView.cpp
@@ -66,6 +66,9 @@ namespace UI
case FontType::DS_DIGIB:
text.setFont(font_DS_DIGIB);
break;
+ case FontType::ROBOTO:
+ text.setFont(font_DS_DIGIB);
+ break;
}
}
diff --git a/Array-Minesweeper/source/UI/UIService.cpp b/Array-Minesweeper/source/UI/UIService.cpp
index ea77b57e..63b5a883 100644
--- a/Array-Minesweeper/source/UI/UIService.cpp
+++ b/Array-Minesweeper/source/UI/UIService.cpp
@@ -7,27 +7,30 @@ namespace UI
using namespace Main;
using namespace MainMenu;
using namespace SplashScreen;
- using namespace Credits;
- using namespace Instructions;
+ using namespace GameplayUI;
using namespace UIElement;
using namespace Interface;
+ using namespace Instructions;
+ using namespace Credits;
UIService::UIService()
{
- splash_screen_controller = nullptr;
- main_menu_controller = nullptr;
- credit_screen_controller = nullptr;
- instructions_screen_controller = nullptr;
+ splash_screen_ui_controller = nullptr;
+ main_menu_ui_controller = nullptr;
+ instructions_screen_ui_controller = nullptr;
+ gameplay_ui_controller = nullptr;
+ credit_screen_ui_controller = nullptr;
createControllers();
}
void UIService::createControllers()
{
- splash_screen_controller = new SplashScreenUIController();
- main_menu_controller = new MainMenuUIController();
- credit_screen_controller = new CreditsScreenUIController();
- instructions_screen_controller = new InstructionsScreenUIController();
+ splash_screen_ui_controller = new SplashScreenUIController();
+ main_menu_ui_controller = new MainMenuUIController();
+ instructions_screen_ui_controller = new InstructionsScreenUIController();
+ gameplay_ui_controller = new GameplayUIController();
+ credit_screen_ui_controller = new CreditsScreenUIController();
}
UIService::~UIService()
@@ -61,10 +64,11 @@ namespace UI
void UIService::initializeControllers()
{
- splash_screen_controller->initialize();
- main_menu_controller->initialize();
- credit_screen_controller->initialize();
- instructions_screen_controller->initialize();
+ splash_screen_ui_controller->initialize();
+ main_menu_ui_controller->initialize();
+ instructions_screen_ui_controller->initialize();
+ gameplay_ui_controller->initialize();
+ credit_screen_ui_controller->initialize();
}
IUIController* UIService::getCurrentUIController()
@@ -72,16 +76,19 @@ namespace UI
switch (GameService::getGameState())
{
case GameState::SPLASH_SCREEN:
- return splash_screen_controller;
+ return splash_screen_ui_controller;
case GameState::MAIN_MENU:
- return main_menu_controller;
+ return main_menu_ui_controller;
case GameState::INSTRUCTIONS:
- return instructions_screen_controller;
+ return instructions_screen_ui_controller;
+
+ case GameState::GAMEPLAY:
+ return gameplay_ui_controller;
case GameState::CREDITS:
- return credit_screen_controller;
+ return credit_screen_ui_controller;
default:
return nullptr;
@@ -90,9 +97,10 @@ namespace UI
void UIService::destroy()
{
- delete(splash_screen_controller);
- delete(main_menu_controller);
- delete(instructions_screen_controller);
- delete(credit_screen_controller);
+ delete(splash_screen_ui_controller);
+ delete(main_menu_ui_controller);
+ delete(instructions_screen_ui_controller);
+ delete(gameplay_ui_controller);
+ delete(credit_screen_ui_controller);
}
}
\ No newline at end of file