diff --git a/.gitignore b/.gitignore index dd7b397..1c126fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build* .vscode CMakeUserPresets.json +env diff --git a/CMakeLists.txt b/CMakeLists.txt index 62fc3cc..c366236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,30 +4,12 @@ project(stratego LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) - -add_library( - stratego-src - src/AttackInfoBox.cpp - src/BigButton.cpp - src/Board.cpp - src/Box.cpp - src/Button.cpp - src/ButtonInterface.cpp - src/Game.cpp - src/GameController.cpp - src/GameView.cpp - src/MainMenu.cpp - src/Movable.cpp - src/Player.cpp) - -target_include_directories(stratego-src PUBLIC include) - -add_executable(${PROJECT_NAME} src/main.cpp) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(SFML 2.6.1 REQUIRED system window graphics CONFIG) -target_link_libraries(stratego-src PUBLIC sfml-system sfml-window sfml-graphics) -target_link_libraries(${PROJECT_NAME} stratego-src) +add_subdirectory(src) +add_subdirectory(include) install(DIRECTORY font DESTINATION ${CMAKE_BINARY_DIR}) install(DIRECTORY images DESTINATION ${CMAKE_BINARY_DIR}) diff --git a/README.md b/README.md index 0ed2ee3..acaa251 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,25 @@ Created with the help of SFML documentation and sources: - [Setting The Board](https://user-images.githubusercontent.com/62173407/85401972-2f64ad80-b55b-11ea-81bb-2f78c8d047ed.png) - [Scout Move](https://user-images.githubusercontent.com/62173407/85402027-44d9d780-b55b-11ea-9de2-3ff096b19e8b.png) - [Attack Info Box](https://user-images.githubusercontent.com/62173407/85402062-5622e400-b55b-11ea-9d96-9cd896a91d29.png) + + +## Contributing +In case you would like to contribue, please make sure that you format code. + +1. Make sure you are in repo root +2. Install clang-format using pip: +```bash +python3 -m venv env +source env/bin/activate +pip install -r requirements.txt +``` + +3. Now use the formatting script: +```bash +bash infra/scripts/apply_formatting.sh . +``` + +4. You can also install pre-commit hook that will automatically check for correct code-formatting: +```bash +cp infra/hooks/pre-commit .git/hooks/pre-commit +``` diff --git a/include/Array2D.h b/include/Array2D.h index faea24d..6f4d20b 100644 --- a/include/Array2D.h +++ b/include/Array2D.h @@ -6,140 +6,109 @@ #include #include -template -class Array -{ - std::vector data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid COLUMN access"); - } +template class Array { + std::vector data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid COLUMN access"); } + } public: - explicit Array(int size) : data(size) - { - } - T &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const T &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array(int size) : data(size) {} + T &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const T &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; -template -class Array2D -{ - std::vector> data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid ROW access"); - } +template class Array2D { + std::vector> data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid ROW access"); } + } public: - explicit Array2D(int width, int height) : data(height, Array(width)) {} - Array &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const Array &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array2D(int width, int height) : data(height, Array(width)) {} + Array &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const Array &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; -template <> -class Array -{ +template <> class Array { public: - class my_bool - { - public: - bool value; - my_bool(bool val = false) : value(val){}; - inline friend std::ostream &operator<<(std::ostream &stream, my_bool rhs); - inline operator bool() const; - inline operator bool(); - - }; + class my_bool { + public: + bool value; + my_bool(bool val = false) : value(val) {}; + inline friend std::ostream &operator<<(std::ostream &stream, my_bool rhs); + inline operator bool() const; + inline operator bool(); + }; private: - std::vector data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid COLUMN access"); - } + std::vector data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid COLUMN access"); } + } public: - explicit Array(int size) : data(size) - { - } - my_bool &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const my_bool &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array(int size) : data(size) {} + my_bool &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const my_bool &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; -std::ostream &operator<<(std::ostream &stream, Array::my_bool rhs) -{ - stream << rhs.value; - return stream; -} - -Array::my_bool::operator bool() const { - return (const bool)value; +std::ostream &operator<<(std::ostream &stream, Array::my_bool rhs) { + stream << rhs.value; + return stream; } -Array::my_bool::operator bool() { - return value; -} +Array::my_bool::operator bool() const { return (const bool)value; } +Array::my_bool::operator bool() { return value; } -template <> -class Array2D -{ - std::vector::my_bool>> data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid ROW access"); - } +template <> class Array2D { + std::vector::my_bool>> data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid ROW access"); } + } public: - explicit Array2D(int width, int height) : data(height, Array::my_bool>(width)) {} - Array::my_bool> &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const Array::my_bool> &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array2D(int width, int height) + : data(height, Array::my_bool>(width)) {} + Array::my_bool> &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const Array::my_bool> &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; #endif /* ARRAY2D_H_ */ diff --git a/include/AttackInfoBox.hpp b/include/AttackInfoBox.hpp index c2725df..841432e 100644 --- a/include/AttackInfoBox.hpp +++ b/include/AttackInfoBox.hpp @@ -1,46 +1,47 @@ #pragma once -#include #include +#include +#include + +#include "unit/Unit.hpp" -#include "Unit.hpp" +class AttackInfoBox { + const std::string path_to_textures; + float attacking_unit_pos_x; + float attacking_unit_pos_y; + float attacked_unit_pos_x; + float attacked_unit_pos_y; + std::array red_units_sprites_ptrs; + std::array blue_units_sprites_ptrs; + sf::Texture box_texture; + sf::Sprite box_sprite; + sf::Font box_font; + sf::Text box_text; + sf::Sprite attacking_unit; + sf::Sprite attacked_unit; + sf::Sprite &winner_highlight; + const Unit *attacker_ptr; + const Unit *attacked_ptr; -class AttackInfoBox -{ - const std::string path_to_textures; - int attacking_unit_pos_x; - int attacking_unit_pos_y; - int attacked_unit_pos_x; - int attacked_unit_pos_y; - std::array red_units_sprites_ptrs; - std::array blue_units_sprites_ptrs; - sf::Texture box_texture; - sf::Sprite box_sprite; - sf::Font box_font; - sf::Text box_text; - sf::Sprite attacking_unit; - sf::Sprite attacked_unit; - sf::Sprite& winner_highlight; - std::shared_ptr attacker_ptr; - std::shared_ptr attacked_ptr; + int get_unit_sprite_idx(const Unit &unit); + void load_box_texture(); + void load_font(); + void update_attacking_unit_pos(); + void update_attacked_unit_pos(); + void update_box_text_pos(); + const Unit *get_winner(); + void set_winner_highlight(); + void draw_winner_highlight(sf::RenderWindow &win); - int get_unit_sprite_idx(const std::shared_ptr& unit); - void load_box_texture(); - void load_font(); - void update_attacking_unit_pos(); - void update_attacked_unit_pos(); - void update_box_text_pos(); - std::shared_ptr get_winner(); - void set_winner_highlight(); - void draw_winner_highlight(sf::RenderWindow& win); - public: - AttackInfoBox(std::array& red_units_sprites, std::array& blue_units_sprites, sf::Sprite& winning_unit_highlight); - void draw(sf::RenderWindow& win); - void set_position(int x, int y); - void set_attacking_unit(const std::shared_ptr& attacker); - void set_attacked_unit(const std::shared_ptr& victim); - float get_height() const { return box_sprite.getGlobalBounds().height; }; - float get_width() const { return box_sprite.getGlobalBounds().width; }; - - +public: + AttackInfoBox(std::array &red_units_sprites, + std::array &blue_units_sprites, + sf::Sprite &winning_unit_highlight); + void draw(sf::RenderWindow &win); + void set_position(int x, int y); + void set_attacking_unit(const std::optional &attacker); + void set_attacked_unit(const std::optional &victim); + float get_height() const { return box_sprite.getGlobalBounds().height; }; + float get_width() const { return box_sprite.getGlobalBounds().width; }; }; \ No newline at end of file diff --git a/include/BigButton.hpp b/include/BigButton.hpp index 16b357d..fb70a7e 100644 --- a/include/BigButton.hpp +++ b/include/BigButton.hpp @@ -2,16 +2,15 @@ #include "ButtonInterface.hpp" -class BigButton : public ButtonInterface -{ - protected: - sf::Texture button_texture; - sf::Texture highlighted_button_texture; +class BigButton : public ButtonInterface { +protected: + sf::Texture button_texture; + sf::Texture highlighted_button_texture; - void load_button_texture(); - void load_highlighted_button_texture(); - - public: - explicit BigButton(const std::string& button_text = "default"); - void draw(sf::RenderWindow& win); + void load_button_texture(); + void load_highlighted_button_texture(); + +public: + explicit BigButton(const std::string &button_text = "default"); + void draw(sf::RenderWindow &win); }; \ No newline at end of file diff --git a/include/Board.hpp b/include/Board.hpp index 3329656..d8800dc 100644 --- a/include/Board.hpp +++ b/include/Board.hpp @@ -1,74 +1,58 @@ #pragma once + #include #include #include +#include #include #include #include "Array2D.h" - -enum class TURN { - PLAYER_A, - PLAYER_B -}; - -enum class STATE { - UNINITIALIZED, - INITIALIZED, - FULL, +#include "Tile.hpp" +#include "Turn.hpp" +#include "unit/Unit.hpp" + +enum class State { + Uninitialized, + Initialized, + Full, }; constexpr int MAX_UNIT_COUNT = 40; -class Unit; class Board { -public: - class Tile { - public: - int x; - int y; - explicit Tile(int col = 0, int row = 0) { - x = col; - y = row; - }; - bool operator==(const Tile& rhs) const { return x == rhs.x && y == rhs.y; }; - void set_cords(const Board::Tile& rhs) { x = rhs.x; y = rhs.y; }; - void set_cords(int Ax, int Ay) { x = Ax; y = Ay; }; - }; - private: - int height; - int width; - STATE current_state; - int unit_count; - Array2D> units; - std::array obstacles; - const std::map max_count_of_each_unit; - - void set_default_units(); - void set_obstacles(); - Tile point_reflection(int col, int row); - bool out_of_range(int col, int row) const; - void set_state(STATE state); + int height{}; + int width{}; + State current_state{}; + int unit_count{}; + Array2D> units; + std::array obstacles; + + void set_default_units(); + void set_obstacles(); + Tile point_reflection(int col, int row); + bool out_of_range(int col, int row) const; + void set_state(State state); + bool is_unit_set(Tile tile) const; + void unset_unit(Tile tile); public: - Board(); - bool set_unit(int col, int row, TURN player, int choice); - void remove_unit(int col, int row); - void reverse_remove_unit(int col, int row); - std::string get_tile_info(int col, int row, TURN player) const; - std::string get_tile_info(const Tile& tile, TURN player) const; - int get_height() const { return height; }; - int get_width() const { return width; }; - std::shared_ptr get_unit(int col, int row) const; - std::shared_ptr get_unit(const Board::Tile& chosen_unit) const; - bool can_move(const Tile& from, const Tile& to) const; - bool move_unit(const Tile& from, const Tile& to); - void reverse_move_unit(const Tile& from, const Tile& to); - void update(const Board& other_board); - Board& operator=(const Board& rhs); - STATE get_state() const { return current_state; }; - int get_max_unit_count(const std::string& unit_type) const { return max_count_of_each_unit.at(unit_type); }; - int get_max_unit_count(int idx) const; - + Board(); + bool set_unit(int col, int row, Turn player, int choice); + void remove_unit(int col, int row); + void reverse_remove_unit(int col, int row); + std::string get_tile_info(int col, int row, Turn player) const; + std::string get_tile_info(const Tile &tile, Turn player) const; + int get_height() const { return height; }; + int get_width() const { return width; }; + const std::optional &get_unit(int col, int row) const; + const std::optional &get_unit(const Tile &chosen_unit) const; + bool can_move(const Tile &from, const Tile &to) const; + bool move_unit(const Tile &from, const Tile &to); + void reverse_move_unit(const Tile &from, const Tile &to); + void update(const Board &other_board); + Board &operator=(const Board &rhs); + State get_state() const { return current_state; }; + int get_max_unit_count(int idx) const; }; \ No newline at end of file diff --git a/include/BombUnit.hpp b/include/BombUnit.hpp deleted file mode 100644 index c3722bb..0000000 --- a/include/BombUnit.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Unit.hpp" - -enum class TURN; -class BombUnit : public Unit { -public: - BombUnit(TURN player) - : Unit(0, "bomb", player, false){}; - virtual ~BombUnit(){}; -}; diff --git a/include/Box.hpp b/include/Box.hpp index 25b7350..356ab5f 100644 --- a/include/Box.hpp +++ b/include/Box.hpp @@ -4,44 +4,44 @@ #include "Button.hpp" -class Box -{ - protected: - const std::string path_to_textures; - size_t max_char_count_inside_box; - size_t max_number_of_text_lines_inside_box; - int box_text_x_pos; - int box_text_y_pos; - int button_x_pos; - int button_y_pos; - Button button; - sf::Font font; - sf::Text box_text; - sf::Texture box_texture; - sf::Sprite box_sprite; - - void load_box_texture(); - void load_font(); - void set_default_text(const std::string& text); - void update_text_pos(); - void update_button_pos(); - void break_text_into_lines(); - void update_max_char_count(); - public: - explicit Box(const std::string& text = "default"); - void set_position(int x, int y); - void set_position(const sf::Vector2f& coords); - void set_text(const std::string& text); - void set_button_text(const std::string& text = "OK"); - void set_button_highlight_on() { button.highlight_on(); }; - void set_button_highlight_off() { button.highlight_off(); }; - bool button_contains(int x, int y) const { return button.contains(x, y); }; - bool button_is_highlighted() const { return button.is_highlighted(); }; - void draw(sf::RenderWindow& win); - float get_height() const { return box_sprite.getGlobalBounds().height; }; - float get_width() const { return box_sprite.getGlobalBounds().width; }; - sf::Vector2f get_position() const { return box_sprite.getPosition(); }; - size_t get_max_char_count_inside_box() const { return max_char_count_inside_box; }; +class Box { +protected: + const std::string path_to_textures; + size_t max_char_count_inside_box; + size_t max_number_of_text_lines_inside_box; + float box_text_x_pos; + float box_text_y_pos; + float button_x_pos; + float button_y_pos; + Button button; + sf::Font font; + sf::Text box_text; + sf::Texture box_texture; + sf::Sprite box_sprite; + void load_box_texture(); + void load_font(); + void set_default_text(const std::string &text); + void update_text_pos(); + void update_button_pos(); + void break_text_into_lines(); + void update_max_char_count(); +public: + explicit Box(const std::string &text = "default"); + void set_position(int x, int y); + void set_position(const sf::Vector2f &coords); + void set_text(const std::string &text); + void set_button_text(const std::string &text = "OK"); + void set_button_highlight_on() { button.highlight_on(); }; + void set_button_highlight_off() { button.highlight_off(); }; + bool button_contains(int x, int y) const { return button.contains(x, y); }; + bool button_is_highlighted() const { return button.is_highlighted(); }; + void draw(sf::RenderWindow &win); + float get_height() const { return box_sprite.getGlobalBounds().height; }; + float get_width() const { return box_sprite.getGlobalBounds().width; }; + sf::Vector2f get_position() const { return box_sprite.getPosition(); }; + size_t get_max_char_count_inside_box() const { + return max_char_count_inside_box; + }; }; \ No newline at end of file diff --git a/include/Button.hpp b/include/Button.hpp index 1890c5f..4d38c1a 100644 --- a/include/Button.hpp +++ b/include/Button.hpp @@ -4,18 +4,15 @@ #include "ButtonInterface.hpp" -class Button : public ButtonInterface -{ +class Button : public ButtonInterface { protected: - sf::Texture button_texture; - sf::Texture highlighted_button_texture; + sf::Texture button_texture; + sf::Texture highlighted_button_texture; + + void load_button_texture(); + void load_highlighted_button_texture(); - void load_button_texture(); - void load_highlighted_button_texture(); public: - explicit Button(const std::string& text = "default"); - void draw(sf::RenderWindow& win); + explicit Button(const std::string &text = "default"); + void draw(sf::RenderWindow &win); }; - - - diff --git a/include/ButtonInterface.hpp b/include/ButtonInterface.hpp index 7ebb2df..d29731f 100644 --- a/include/ButtonInterface.hpp +++ b/include/ButtonInterface.hpp @@ -4,31 +4,34 @@ class ButtonInterface { protected: - int text_x_pos; - int text_y_pos; - bool highlighted; - const std::string path_to_textures; - sf::Sprite button; - sf::Sprite highlighted_button; - sf::Font font; - sf::Text button_text; + int text_x_pos; + int text_y_pos; + bool highlighted; + const std::string path_to_textures; + sf::Sprite button; + sf::Sprite highlighted_button; + sf::Font font; + sf::Text button_text; - void load_font(); - void set_default_button_text(const std::string& text); - void update_text_pos(); + void load_font(); + void set_default_button_text(const std::string &text); + void update_text_pos(); public: - explicit ButtonInterface(const std::string& text); - void set_text(const std::string& text); - void set_position(int x, int y); - void set_position(sf::Vector2f coords); - virtual void draw(sf::RenderWindow& win) = 0; - float get_height() const { return button.getGlobalBounds().height; }; - float get_width() const { return button.getGlobalBounds().width; }; - bool contains(int x, int y) const { return button.getGlobalBounds().contains(x, y); }; - void highlight_on() { highlighted = true; }; - void highlight_off() { highlighted = false; }; - bool is_highlighted() const { return highlighted; }; - sf::Vector2f get_position() const { return button.getPosition(); }; - sf::String get_text() const { return button_text.getString(); }; + explicit ButtonInterface(const std::string &text); + void set_text(const std::string &text); + void set_position(int x, int y); + void set_position(sf::Vector2f coords); + virtual void draw(sf::RenderWindow &win) = 0; + float get_height() const { return button.getGlobalBounds().height; }; + float get_width() const { return button.getGlobalBounds().width; }; + bool contains(int x, int y) const { + return button.getGlobalBounds().contains(static_cast(x), + static_cast(y)); + }; + void highlight_on() { highlighted = true; }; + void highlight_off() { highlighted = false; }; + bool is_highlighted() const { return highlighted; }; + sf::Vector2f get_position() const { return button.getPosition(); }; + sf::String get_text() const { return button_text.getString(); }; }; \ No newline at end of file diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..77bb3a7 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1 @@ +target_include_directories(stratego-src PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/include/FlagUnit.hpp b/include/FlagUnit.hpp deleted file mode 100644 index 9bcaa37..0000000 --- a/include/FlagUnit.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include "Unit.hpp" - -enum class TURN; -class FlagUnit : public Unit { -public: - FlagUnit(TURN player) - : Unit(-1, "flag", player, false){}; - virtual ~FlagUnit(){}; -}; \ No newline at end of file diff --git a/include/Game.hpp b/include/Game.hpp index 1040558..ee199e0 100644 --- a/include/Game.hpp +++ b/include/Game.hpp @@ -1,17 +1,17 @@ #pragma once -#include "cScreen.hpp" -#include "GameView.hpp" #include "GameController.hpp" +#include "GameView.hpp" +#include "cScreen.hpp" + +class Game : public cScreen { + GameView &game_view; + GameController &game_controller; + sf::Clock clock; + bool clock_started; + void draw(sf::RenderWindow &win); -class Game :public cScreen -{ - GameView& game_view; - GameController& game_controller; - sf::Clock clock; - bool clock_started; - void draw(sf::RenderWindow& win); - public: - Game(GameView& g_view, GameController& g_controller); - std::string run(sf::RenderWindow& win) override; +public: + Game(GameView &g_view, GameController &g_controller); + std::string run(sf::RenderWindow &win) override; }; \ No newline at end of file diff --git a/include/GameController.hpp b/include/GameController.hpp index 39fc77a..9791f8b 100644 --- a/include/GameController.hpp +++ b/include/GameController.hpp @@ -1,99 +1,104 @@ #pragma once #include +#include #include "Board.hpp" struct mouse_data { - float mouse_x; - float mouse_y; - float mouse_object_offset_x; - float mouse_object_offset_y; + float mouse_x; + float mouse_y; + float mouse_object_offset_x; + float mouse_object_offset_y; }; -enum class TURN; +enum class Turn; class Player; class GameView; class GameController { - Player& playerA; - Player& playerB; - GameView& game_view; - Player* current_player; - Player* other_player; - std::shared_ptr attacker; - std::shared_ptr attacked; - sf::Clock clock; - sf::Time total_time_unit_attacked; + Player &playerA; + Player &playerB; + GameView &game_view; + Player *current_player; + Player *other_player; + std::optional attacker; + std::optional attacked; + sf::Clock clock; + sf::Time total_time_unit_attacked; - std::string victorious_player_name; - TURN current_player_turn; - mouse_data m_data; - size_t TILE_SIZE; - size_t selected_unit_idx; + std::string victorious_player_name; + Turn current_player_turn; + mouse_data m_data; + size_t TILE_SIZE; + size_t selected_unit_idx; - bool dragging; - bool board_a_initialized; - bool board_b_initialized; - bool is_active_unit; - bool unit_moved_this_round; - bool end_turn_button_pressed; - bool turn_approved; - bool unit_attacked; - bool remove_button_pressed; - bool done_button_pressed; - bool randomize_button_pressed; - bool end_game_info_box_button_pressed; - bool game_finished; - bool clock_started; + bool dragging; + bool board_a_initialized; + bool board_b_initialized; + bool is_active_unit; + bool unit_moved_this_round; + bool end_turn_button_pressed; + bool turn_approved; + bool unit_attacked; + bool remove_button_pressed; + bool done_button_pressed; + bool randomize_button_pressed; + bool end_game_info_box_button_pressed; + bool game_finished; + bool clock_started; - Board::Tile active_unit; - Board::Tile attacking_unit; - Board::Tile attacked_unit; + Tile active_unit; + Tile attacking_unit; + Tile attacked_unit; - void TEST_SET_RANDOM_UNITS(); - sf::Vector2f return_pixels(int col, int row) const; - Board::Tile return_tile(const sf::Vector2f& coords) const; - Board::Tile return_tile(int x, int y) const; + void TEST_SET_RANDOM_UNITS(); + sf::Vector2f return_pixels(int col, int row) const; + Tile return_tile(const sf::Vector2f &coords) const; + Tile return_tile(int x, int y) const; - void drag_red_player(sf::Event& event); - void drag_blue_player(sf::Event& event); - void change_init_turn(sf::Event& event); - void set_unit(sf::Event& event); - void remove_unit(); - void randomize_units(); - void set_active_unit(sf::Event& event); - void change_player_turn(); - void move_active_unit(sf::Event& event); - bool is_out_of_the_board(int x, int y); - void set_buttons_pressed(); - void resolve_unit_conflict(const Board::Tile& attacked_unit); + void drag_red_player(sf::Event &event); + void drag_blue_player(sf::Event &event); + void change_init_turn(sf::Event &event); + void set_unit(sf::Event &event); + void remove_unit(); + void randomize_units(); + void set_active_unit(sf::Event &event); + void change_player_turn(); + void move_active_unit(sf::Event &event); + bool is_out_of_the_board(int x, int y); + void set_buttons_pressed(); + void resolve_unit_conflict(const Tile &attacked_unit); public: - GameController(Player& pA, Player& pB, GameView& g_view); - bool get_dragging() { return dragging; }; - bool get_board_a_initialized() { return board_a_initialized; }; - bool get_board_b_initialized() { return board_b_initialized; }; - bool get_is_active_unit() { return is_active_unit; }; - bool get_unit_moved_this_round() { return unit_moved_this_round; }; - bool get_end_turn_button_pressed() { return end_turn_button_pressed; }; - bool get_turn_approved() { return turn_approved; }; - bool get_unit_attacked() const { return unit_attacked; }; - bool get_remove_button_pressed() { return remove_button_pressed; }; - bool get_done_button_pressed() { return done_button_pressed; }; - bool get_randomize_button_pressed() { return randomize_button_pressed; }; - bool get_end_game_info_box_button_pressed() { return end_game_info_box_button_pressed; }; - bool get_game_finished() { return game_finished; }; - bool both_boards_set() const; - std::shared_ptr get_attacker() const { return attacker; }; - std::shared_ptr get_attacked() const { return attacked; }; - std::string get_victorious_player_name() const { return victorious_player_name; }; - const Board::Tile& get_active_unit() const { return active_unit; }; - int get_selected_init_unit_idx() const { return selected_unit_idx; }; - const mouse_data& get_mouse_data() const { return m_data; }; - Player* get_current_player() const { return current_player; }; - Player* get_other_player() const { return other_player; }; - void update_unit_attacked(const sf::Time& time_past); + GameController(Player &pA, Player &pB, GameView &g_view); + bool get_dragging() { return dragging; }; + bool get_board_a_initialized() { return board_a_initialized; }; + bool get_board_b_initialized() { return board_b_initialized; }; + bool get_is_active_unit() { return is_active_unit; }; + bool get_unit_moved_this_round() { return unit_moved_this_round; }; + bool get_end_turn_button_pressed() { return end_turn_button_pressed; }; + bool get_turn_approved() { return turn_approved; }; + bool get_unit_attacked() const { return unit_attacked; }; + bool get_remove_button_pressed() { return remove_button_pressed; }; + bool get_done_button_pressed() { return done_button_pressed; }; + bool get_randomize_button_pressed() { return randomize_button_pressed; }; + bool get_end_game_info_box_button_pressed() { + return end_game_info_box_button_pressed; + }; + bool get_game_finished() { return game_finished; }; + bool both_boards_set() const; + std::optional get_attacker() const { return attacker; }; + std::optional get_attacked() const { return attacked; }; + std::string get_victorious_player_name() const { + return victorious_player_name; + }; + const Tile &get_active_unit() const { return active_unit; }; + int get_selected_init_unit_idx() const { return selected_unit_idx; }; + const mouse_data &get_mouse_data() const { return m_data; }; + Player *get_current_player() const { return current_player; }; + Player *get_other_player() const { return other_player; }; + void update_unit_attacked(const sf::Time &time_past); - void handle_events(sf::Event& event); + void handle_events(sf::Event &event); }; \ No newline at end of file diff --git a/include/GameView.hpp b/include/GameView.hpp index dbea522..c85ab78 100644 --- a/include/GameView.hpp +++ b/include/GameView.hpp @@ -11,114 +11,127 @@ #include "GameController.hpp" class Player; -enum class TURN; +enum class Turn; class GameView { - Player& playerA; - Player& playerB; - Player* current_player; - Player* other_player; - TURN current_player_turn; - - const std::string board_textures_path; - const std::string pieces_textures_path; - - int TILE_SIZE; - int X_ADDITIONAL_SPACE; - sf::Vector2f window_size; - sf::Vector2f sprite_initial_position; - - bool clock_started; - - sf::Sprite board_border; - sf::Sprite grass_light; - sf::Sprite grass_dark; - std::array obstacle_sprites; - std::array red_units_sprites; - sf::Sprite red_back_sprite; - std::array blue_units_sprites; - sf::Sprite blue_back_sprite; - sf::Sprite yellow_highlight_sprite; - sf::Sprite white_highlight_sprite; - sf::Sprite green_highlight_sprite; - sf::Sprite red_highlight_sprite; - - sf::Texture board_border_texture; - sf::Texture grass_light_texture; - sf::Texture grass_dark_texture; - std::array obstacle_textures; - std::array red_unit_textures; - sf::Texture red_back_texture; - std::array blue_unit_textures; - sf::Texture blue_back_texture; - sf::Texture yellow_highlight_texture; - sf::Texture white_highlight_texture; - sf::Texture green_highlight_texture; - sf::Texture red_highlight_texture; - - sf::Clock clock; - sf::Font font; - sf::Text text; - Button done_button; - Button randomize_button; - Button remove_button; - Button end_turn_button; - Box info_box; - AttackInfoBox attack_info_box; - Box end_game_info_box; - - void load_obstacle_textures(); - void load_grass_textures(); - void load_board_border_texture(); - void load_red_units_textures(); - void load_blue_units_textures(); - void load_highlight_textures(); - void load_font(); - void set_obstacle_sprites(); - void set_red_units_sprites(); - void set_blue_units_sprites(); - void set_highlight_sprites(); - - sf::Vector2f return_pixels(int col, int row) const; - Board::Tile return_tile(const sf::Vector2f& coords) const; - Board::Tile return_tile(int x, int y) const; - - bool check_if_viable(Board::Tile from, int to_x, int to_y); - void highlight_regular_moves(sf::RenderWindow& win, const Board::Tile& active_unit); - void highlight_scout_moves(sf::RenderWindow& win, const Board::Tile& active_unit); - bool highlight_tile(sf::RenderWindow& win, const Board::Tile& active_unit, int to_x, int to_y); - void draw_red_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); - void draw_blue_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); + Player &playerA; + Player &playerB; + Player *current_player; + Player *other_player; + Turn current_player_turn; + + const std::string board_textures_path; + const std::string pieces_textures_path; + + int TILE_SIZE; + int X_ADDITIONAL_SPACE; + sf::Vector2f window_size; + sf::Vector2f sprite_initial_position; + + bool clock_started; + + sf::Sprite board_border; + sf::Sprite grass_light; + sf::Sprite grass_dark; + std::array obstacle_sprites; + std::array red_units_sprites; + sf::Sprite red_back_sprite; + std::array blue_units_sprites; + sf::Sprite blue_back_sprite; + sf::Sprite yellow_highlight_sprite; + sf::Sprite white_highlight_sprite; + sf::Sprite green_highlight_sprite; + sf::Sprite red_highlight_sprite; + + sf::Texture board_border_texture; + sf::Texture grass_light_texture; + sf::Texture grass_dark_texture; + std::array obstacle_textures; + std::array red_unit_textures; + sf::Texture red_back_texture; + std::array blue_unit_textures; + sf::Texture blue_back_texture; + sf::Texture yellow_highlight_texture; + sf::Texture white_highlight_texture; + sf::Texture green_highlight_texture; + sf::Texture red_highlight_texture; + + sf::Clock clock; + sf::Font font; + sf::Text text; + Button done_button; + Button randomize_button; + Button remove_button; + Button end_turn_button; + Box info_box; + AttackInfoBox attack_info_box; + Box end_game_info_box; + + void load_obstacle_textures(); + void load_grass_textures(); + void load_board_border_texture(); + void load_red_units_textures(); + void load_blue_units_textures(); + void load_highlight_textures(); + void load_font(); + void set_obstacle_sprites(); + void set_red_units_sprites(); + void set_blue_units_sprites(); + void set_highlight_sprites(); + + sf::Vector2f return_pixels(int col, int row) const; + Tile return_tile(const sf::Vector2f &coords) const; + Tile return_tile(int x, int y) const; + + bool check_if_viable(Tile from, int to_x, int to_y); + void highlight_regular_moves(sf::RenderWindow &win, const Tile &active_unit); + void highlight_scout_moves(sf::RenderWindow &win, const Tile &active_unit); + bool highlight_tile(sf::RenderWindow &win, const Tile &active_unit, int to_x, + int to_y); + void draw_red_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, const mouse_data &m_data); + void draw_blue_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, const mouse_data &m_data); public: - GameView(Player& pA, Player& pB); - void update_players(Player* current, Player* other); - void set_button_highlights(int mouse_x, int mouse_y); - - sf::Vector2f get_window_size() { return window_size; }; - const std::array& get_red_units_sprites() const { return red_units_sprites; }; - const std::array& get_blue_units_sprites() const { return blue_units_sprites; }; - const Button& get_done_button() const { return done_button; }; - const Button& get_randomize_button() const { return randomize_button; }; - const Button& get_remove_button() const { return remove_button; }; - const Button& get_end_turn_button() const { return end_turn_button; }; - const Box& get_info_box() const { return info_box; }; - const Box& get_end_game_info_box() const { return end_game_info_box; }; - const AttackInfoBox& get_attack_info_box() const { return attack_info_box; }; - - void draw_board_border(sf::RenderWindow& win); - void draw_grass(sf::RenderWindow& win); - void draw_obstacles(sf::RenderWindow& win); - void draw_units_for_init(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); - void draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int sprite_pos_y); - void draw_done_button(sf::RenderWindow& win); - void draw_randomize_button(sf::RenderWindow& win); - void draw_remove_button(sf::RenderWindow& win); - void draw_end_turn_button(sf::RenderWindow& win); - void draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Board::Tile& active_unit); - void draw_info_box(sf::RenderWindow& win); - void draw_attack_info_box(sf::RenderWindow& win, const std::shared_ptr& attacker, const std::shared_ptr& attacked); - void draw_units(sf::RenderWindow& win); - void draw_unit_highlight(sf::RenderWindow& win, const Board::Tile& active_unit); - void draw_end_game_screen(sf::RenderWindow& win, const std::string& victorious_name); + GameView(Player &pA, Player &pB); + void update_players(Player *current, Player *other); + void set_button_highlights(int mouse_x, int mouse_y); + + sf::Vector2f get_window_size() { return window_size; }; + const std::array &get_red_units_sprites() const { + return red_units_sprites; + }; + const std::array &get_blue_units_sprites() const { + return blue_units_sprites; + }; + const Button &get_done_button() const { return done_button; }; + const Button &get_randomize_button() const { return randomize_button; }; + const Button &get_remove_button() const { return remove_button; }; + const Button &get_end_turn_button() const { return end_turn_button; }; + const Box &get_info_box() const { return info_box; }; + const Box &get_end_game_info_box() const { return end_game_info_box; }; + const AttackInfoBox &get_attack_info_box() const { return attack_info_box; }; + + void draw_board_border(sf::RenderWindow &win); + void draw_grass(sf::RenderWindow &win); + void draw_obstacles(sf::RenderWindow &win); + void draw_units_for_init(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, const mouse_data &m_data); + void draw_sprite(sf::RenderWindow &win, int idx, int sprite_pos_x, + int sprite_pos_y); + void draw_done_button(sf::RenderWindow &win); + void draw_randomize_button(sf::RenderWindow &win); + void draw_remove_button(sf::RenderWindow &win); + void draw_end_turn_button(sf::RenderWindow &win); + void draw_possible_moves_for_active_unit(sf::RenderWindow &win, + const Tile &active_unit); + void draw_info_box(sf::RenderWindow &win); + void draw_attack_info_box(sf::RenderWindow &win, + const std::optional &attacker, + const std::optional &attacked); + void draw_units(sf::RenderWindow &win); + void draw_unit_highlight(sf::RenderWindow &win, const Tile &active_unit); + void draw_end_game_screen(sf::RenderWindow &win, + const std::string &victorious_name); }; \ No newline at end of file diff --git a/include/MainMenu.hpp b/include/MainMenu.hpp index 1ff7d46..a20c6c8 100644 --- a/include/MainMenu.hpp +++ b/include/MainMenu.hpp @@ -2,50 +2,48 @@ #include "BigButton.hpp" #include "Button.hpp" -#include "cScreen.hpp" -#include "Player.hpp" #include "Game.hpp" +#include "Player.hpp" +#include "cScreen.hpp" -class MainMenu : public cScreen -{ - Player& playerA; - Player& playerB; - BigButton start_game_button; - BigButton game_rules_button; - BigButton exit_button; - Button next; - Button prev; - Box player_1_name; - Box player_2_name; - bool names_entered; - bool game_started_button_pressed; - bool rules_button_pressed; - bool exit_button_pressed; - bool next_button_pressed; - bool prev_button_pressed; - bool player_1_name_approved; - bool player_2_name_approved; - bool entering_from_menu; - std::string nickname; - sf::String nickname_drawn; - const std::string path_to_textures; - int idx; - - std::array rules_textures; - sf::Texture logo_texture; - std::array rules_sprites; - sf::Sprite logo_sprite; +class MainMenu : public cScreen { + Player &playerA; + Player &playerB; + BigButton start_game_button; + BigButton game_rules_button; + BigButton exit_button; + Button next; + Button prev; + Box player_1_name; + Box player_2_name; + bool names_entered; + bool game_started_button_pressed; + bool rules_button_pressed; + bool exit_button_pressed; + bool next_button_pressed; + bool prev_button_pressed; + bool player_1_name_approved; + bool player_2_name_approved; + bool entering_from_menu; + std::string nickname; + sf::String nickname_drawn; + const std::string path_to_textures; + int idx; - void draw_menu(sf::RenderWindow& win); - void draw_names(sf::RenderWindow& win); - void draw_rules(sf::RenderWindow& win); - void draw_rule(sf::RenderWindow& win, int idx); - void highlight_buttons(int mouse_x, int mouse_y); - void enter_names(sf::Event& event); - void set_buttons_pressed(); + std::array rules_textures; + sf::Texture logo_texture; + std::array rules_sprites; + sf::Sprite logo_sprite; - public: - MainMenu(Player& pA, Player& pB); - std::string run(sf::RenderWindow& win) override; + void draw_menu(sf::RenderWindow &win); + void draw_names(sf::RenderWindow &win); + void draw_rules(sf::RenderWindow &win); + void draw_rule(sf::RenderWindow &win, int idx); + void highlight_buttons(int mouse_x, int mouse_y); + void enter_names(sf::Event &event); + void set_buttons_pressed(); +public: + MainMenu(Player &pA, Player &pB); + std::string run(sf::RenderWindow &win) override; }; \ No newline at end of file diff --git a/include/MinerUnit.hpp b/include/MinerUnit.hpp deleted file mode 100644 index 9d0b1e7..0000000 --- a/include/MinerUnit.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Movable.hpp" -#include "Unit.hpp" - -enum class TURN; -class MinerUnit : public Unit, public Movable { -public: - MinerUnit(TURN player) - : Unit(3, "miner", player, true), Movable(this){}; - virtual ~MinerUnit(){}; - virtual RESULT attack(const std::shared_ptr& rhs) const override { - if (rhs->get_type() == "bomb") { - return RESULT::WON; - } - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - return Movable::can_move(from_x, from_y, to_x, to_y); - }; -}; diff --git a/include/Movable.hpp b/include/Movable.hpp deleted file mode 100644 index 2755343..0000000 --- a/include/Movable.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "Board.hpp" - -enum class RESULT { - LOST, - DRAW, - WON, -}; -class Unit; - -class Movable { -public: - class Delegate { - public: - virtual int get_value() const = 0; - ~Delegate(){}; - }; - -private: - Delegate* delegate; - -public: - explicit Movable(Delegate* del); - virtual bool can_move(int from_x, int from_y, int to_x, int to_y) const = 0; - virtual bool can_move(const Board::Tile& from, const Board::Tile& to) const { return can_move(from.x, from.y, to.x, to.y); }; - virtual RESULT attack(const std::shared_ptr& rhs) const = 0; - - virtual ~Movable(){}; -}; diff --git a/include/Player.hpp b/include/Player.hpp index 1524d07..d6fa47c 100644 --- a/include/Player.hpp +++ b/include/Player.hpp @@ -3,34 +3,30 @@ #include #include "Board.hpp" +#include "unit/visit/Attack.hpp" -enum class TURN; -enum class RESULT; -class Player -{ - std::string name; - TURN player; - std::unordered_map units_count; - Board board; - - void set_units_count(); - public: - Player(std::string n, TURN p): name(n), player(p), units_count(), board() { set_units_count(); }; - int get_units_count(const std::string& type) const { return units_count.at(type); }; - int get_units_count(int idx); - TURN get_player_number() { return player; }; - std::string get_player_name() { return name; }; - void set_unit(int col, int row, int choice); - void remove_unit(int col, int row); - void remove_unit(Board::Tile chosen_unit); - void reverse_remove_unit(Board::Tile unit); - bool move_unit(Board::Tile from, Board::Tile to); - RESULT attack(Board::Tile attacker, Board::Tile attacked); - void reverse_move_unit(Board::Tile from, Board::Tile to); - void update_board(const Board& other_player_board); - const Board& get_board() { return board; }; - std::string get_tile_info(int col, int row) const; - std::string get_tile_info(Board::Tile tile) const; - bool can_move(Board::Tile from, Board::Tile to); - void set_name(const std::string& n) { name = n; }; +enum class Turn; +class Player { + std::string name; + Turn player; + Board board; + +public: + Player(std::string n, Turn p) : name(n), player(p), board() {}; + int get_units_count(int idx); + Turn get_player_number() { return player; }; + std::string get_player_name() { return name; }; + void set_unit(int col, int row, int choice); + void remove_unit(int col, int row); + void remove_unit(Tile chosen_unit); + void reverse_remove_unit(Tile unit); + bool move_unit(Tile from, Tile to); + attack::Result attack(Tile attacker, Tile attacked); + void reverse_move_unit(Tile from, Tile to); + void update_board(const Board &other_player_board); + const Board &get_board() { return board; }; + std::string get_tile_info(int col, int row) const; + std::string get_tile_info(Tile tile) const; + bool can_move(Tile from, Tile to); + void set_name(const std::string &n) { name = n; }; }; \ No newline at end of file diff --git a/include/RegularUnit.hpp b/include/RegularUnit.hpp deleted file mode 100644 index 8f74a44..0000000 --- a/include/RegularUnit.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "Movable.hpp" -#include "Unit.hpp" - -enum class TURN; -enum class RESULT; -class RegularUnit : public Unit, public Movable { -public: - RegularUnit(int v, TURN player) - : Unit(v, "regular", player, true), Movable(this) {}; - virtual ~RegularUnit() {}; - virtual RESULT attack(const std::shared_ptr& rhs) const override { - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - return Movable::can_move(from_x, from_y, to_x, to_y); - }; -}; diff --git a/include/ScoutUnit.hpp b/include/ScoutUnit.hpp deleted file mode 100644 index 50b6df9..0000000 --- a/include/ScoutUnit.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include "Unit.hpp" -#include "Movable.hpp" - -enum class TURN; -class ScoutUnit : public Unit, public Movable { -public: - ScoutUnit(TURN player) - : Unit(2, "scout", player, true), Movable(this) {}; - virtual ~ScoutUnit() {}; - virtual RESULT attack(const std::shared_ptr& rhs) const override { - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - if (from_x == to_x) { - return true; - } - if (from_y == to_y) { - return true; - } - return false; - }; -}; \ No newline at end of file diff --git a/include/SpyUnit.hpp b/include/SpyUnit.hpp deleted file mode 100644 index dc09935..0000000 --- a/include/SpyUnit.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#pragma once - -#include "Unit.hpp" -#include "Movable.hpp" - -enum class TURN; -class SpyUnit : public Unit, public Movable { -public: - SpyUnit(TURN player) - : Unit(-1, "spy", player, true), Movable(this) {}; - virtual ~SpyUnit() {}; - RESULT attack(const std::shared_ptr& rhs) const override { - if (rhs->get_value() == 10) { - return RESULT::WON; - } - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - return Movable::can_move(from_x, from_y, to_x, to_y); - }; -}; diff --git a/include/Tile.hpp b/include/Tile.hpp new file mode 100644 index 0000000..678f571 --- /dev/null +++ b/include/Tile.hpp @@ -0,0 +1,20 @@ +#pragma once + +class Tile { +public: + int x{}; + int y{}; + explicit Tile(int col = 0, int row = 0) { + x = col; + y = row; + }; + bool operator==(const Tile &rhs) const { return x == rhs.x && y == rhs.y; }; + void set_cords(const Tile &rhs) { + x = rhs.x; + y = rhs.y; + }; + void set_cords(int Ax, int Ay) { + x = Ax; + y = Ay; + }; +}; \ No newline at end of file diff --git a/include/Turn.hpp b/include/Turn.hpp new file mode 100644 index 0000000..0c63f53 --- /dev/null +++ b/include/Turn.hpp @@ -0,0 +1,3 @@ +#pragma once + +enum class Turn { PlayerA, PlayerB }; \ No newline at end of file diff --git a/include/Unit.hpp b/include/Unit.hpp deleted file mode 100644 index 7ef5428..0000000 --- a/include/Unit.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -#include "Movable.hpp" - -class Board; -enum class TURN; - -class Unit : public Movable::Delegate { - int value; - std::string type; - TURN owner; - -public: - Unit(){}; - Unit(int v, const std::string& t, TURN player, bool m) - : value(v), type(t), owner(player) { - }; - inline Unit(const Unit& rhs); - int get_value() const override { return value; }; - std::string get_type() const { return type; }; - TURN get_owner() const { return owner; }; - virtual ~Unit(){}; -}; - -Unit::Unit(const Unit& rhs) { - value = rhs.value; - type = rhs.type; - owner = rhs.owner; -} diff --git a/include/cScreen.hpp b/include/cScreen.hpp index ca6829d..67aa50c 100644 --- a/include/cScreen.hpp +++ b/include/cScreen.hpp @@ -3,8 +3,7 @@ #include #include -class cScreen -{ - public: - virtual std::string run(sf::RenderWindow& win) = 0; +class cScreen { +public: + virtual std::string run(sf::RenderWindow &win) = 0; }; \ No newline at end of file diff --git a/include/unit/BombUnit.hpp b/include/unit/BombUnit.hpp new file mode 100644 index 0000000..d976e7c --- /dev/null +++ b/include/unit/BombUnit.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" + +namespace details { +constexpr const int maxBombCount{6}; +} + +enum class Turn; +class BombUnit { + UnitModel model_; + UnitCounter counter_; + +public: + explicit BombUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } +}; diff --git a/include/unit/FlagUnit.hpp b/include/unit/FlagUnit.hpp new file mode 100644 index 0000000..d59f4e2 --- /dev/null +++ b/include/unit/FlagUnit.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" + +namespace details { +constexpr const int maxFlagCount{1}; +} + +enum class Turn; +class FlagUnit { + UnitModel model_; + UnitCounter counter_; + +public: + explicit FlagUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } +}; \ No newline at end of file diff --git a/include/unit/MinerUnit.hpp b/include/unit/MinerUnit.hpp new file mode 100644 index 0000000..96af010 --- /dev/null +++ b/include/unit/MinerUnit.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" + +namespace details { +constexpr const int maxMinerCount{4}; +} + +enum class Turn; +class MinerUnit { + UnitModel model_; + UnitCounter counter_; + +public: + explicit MinerUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } +}; diff --git a/include/unit/RegularUnit.hpp b/include/unit/RegularUnit.hpp new file mode 100644 index 0000000..806289d --- /dev/null +++ b/include/unit/RegularUnit.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" + +enum class Turn; + +class RegularUnit { + UnitModel model_; + RegularUnitCounter counter_; + +public: + explicit RegularUnit(int value, Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count(int value) { + return RegularUnitCounter::get_count(value); + } + static int get_max_count(int value) { + return RegularUnitCounter::get_max_count(value); + } +}; diff --git a/include/unit/ScoutUnit.hpp b/include/unit/ScoutUnit.hpp new file mode 100644 index 0000000..eccd105 --- /dev/null +++ b/include/unit/ScoutUnit.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" + +namespace details { +constexpr const int maxScoutCount{8}; +} + +enum class Turn; +class ScoutUnit { + UnitModel model_; + UnitCounter counter_; + +public: + explicit ScoutUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } +}; \ No newline at end of file diff --git a/include/unit/SpyUnit.hpp b/include/unit/SpyUnit.hpp new file mode 100644 index 0000000..9f8ffe4 --- /dev/null +++ b/include/unit/SpyUnit.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" + +namespace details { +constexpr const int maxSpyCount{1}; +} + +enum class Turn; + +class SpyUnit { + UnitModel model_; + UnitCounter counter_; + +public: + explicit SpyUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } +}; diff --git a/include/unit/Unit.hpp b/include/unit/Unit.hpp new file mode 100644 index 0000000..68abc67 --- /dev/null +++ b/include/unit/Unit.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "unit/BombUnit.hpp" +#include "unit/FlagUnit.hpp" +#include "unit/MinerUnit.hpp" +#include "unit/RegularUnit.hpp" +#include "unit/ScoutUnit.hpp" +#include "unit/SpyUnit.hpp" + +using Unit = std::variant; + +template struct overloads : Ts... { + using Ts::operator()...; +}; \ No newline at end of file diff --git a/include/unit/UnitConcepts.hpp b/include/unit/UnitConcepts.hpp new file mode 100644 index 0000000..74c56ee --- /dev/null +++ b/include/unit/UnitConcepts.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "Turn.hpp" + +namespace unit { +template +concept Attackable = requires(UnitType unit) { + { unit.get_value() } -> std::same_as; +}; + +template +concept Owned = requires(const UnitType &unit) { + { unit.get_owner() } -> std::same_as; +}; +} // namespace unit \ No newline at end of file diff --git a/include/unit/UnitCounter.hpp b/include/unit/UnitCounter.hpp new file mode 100644 index 0000000..d437afb --- /dev/null +++ b/include/unit/UnitCounter.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +template class UnitCounter { +private: + static int count_; + +public: + UnitCounter() { ++count_; } + UnitCounter(const UnitCounter &) : UnitCounter() {} + UnitCounter(UnitCounter &&) {} + UnitCounter &operator=(const UnitCounter &rhs) { + if (this != &rhs) + ++count_; + return *this; + }; + UnitCounter &operator=(UnitCounter &&) { return *this; } + ~UnitCounter() { --count_; } + + static int get_count() { return count_; } + static int get_max_count() { return MaxCount; } +}; + +template +int UnitCounter::count_ = 0; + +class RegularUnitCounter { +private: + static std::unordered_map count_; + int unit_value_{0}; + +public: + explicit RegularUnitCounter(const int unit_value); + RegularUnitCounter(const RegularUnitCounter &); + RegularUnitCounter(RegularUnitCounter &&); + RegularUnitCounter &operator=(const RegularUnitCounter &); + RegularUnitCounter &operator=(RegularUnitCounter &&); + ~RegularUnitCounter(); + + static int get_count(int unit_value); + static int get_max_count(int unit_value); +}; \ No newline at end of file diff --git a/include/unit/UnitModel.hpp b/include/unit/UnitModel.hpp new file mode 100644 index 0000000..f7b6acb --- /dev/null +++ b/include/unit/UnitModel.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#include "Tile.hpp" + +enum class Turn; + +class UnitModel { +private: + int value_{}; + [[deprecated]] std::string type_{}; + Turn owner_{}; + +public: + static constexpr int MARSHAL_VALUE{10}; + UnitModel(int value, std::string type, Turn player); + int get_value() const noexcept; + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept; + Turn get_owner() const noexcept; +}; diff --git a/include/unit/visit/Attack.hpp b/include/unit/visit/Attack.hpp new file mode 100644 index 0000000..5c02ba6 --- /dev/null +++ b/include/unit/visit/Attack.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include + +#include "Tile.hpp" +#include "unit/Unit.hpp" +#include "unit/UnitConcepts.hpp" + +namespace attack { +enum class Result { + Lost, + Draw, + Won, +}; + +class InvalidUnitError : public std::exception { +public: + const char *what() const noexcept override { + return "Invalid unit attacked or was being attacked\n"; + } +}; + +} // namespace attack + +class Attack { + template + attack::Result regular_attack(const T &lhs, const U &rhs) { + if (lhs.get_value() > rhs.get_value()) { + return attack::Result::Won; + } + if (lhs.get_value() == rhs.get_value()) { + return attack::Result::Draw; + } + return attack::Result::Lost; + } + +public: + attack::Result operator()(const SpyUnit &, const RegularUnit &rhs) { + if (rhs.get_value() == UnitModel::MARSHAL_VALUE) { + return attack::Result::Won; + } + return attack::Result::Lost; + } + attack::Result operator()(const MinerUnit &, const BombUnit &) { + return attack::Result::Won; + } + template + attack::Result operator()(const T &, const BombUnit &) { + return attack::Result::Lost; + } + template + attack::Result operator()(const T &lhs, const U &rhs) { + return regular_attack(lhs, rhs); + } + template + attack::Result operator()(const T &lhs, const U &rhs) { + throw attack::InvalidUnitError(); + } +}; \ No newline at end of file diff --git a/include/unit/visit/CanMove.hpp b/include/unit/visit/CanMove.hpp new file mode 100644 index 0000000..d482810 --- /dev/null +++ b/include/unit/visit/CanMove.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include + +#include "Tile.hpp" +#include "unit/Unit.hpp" + +class CanMove { +private: + Tile from_{}; + Tile to_{}; + + bool regularMove() const { + if (from_.x + 1 == to_.x && from_.y == to_.y) { + return true; + } + if (from_.x - 1 == to_.x && from_.y == to_.y) { + return true; + } + if (from_.x == to_.x && from_.y + 1 == to_.y) { + return true; + } + if (from_.x == to_.x && from_.y - 1 == to_.y) { + return true; + } + return false; + } + + bool scoutMove() const { + if (from_.x == to_.x) { + return true; + } + if (from_.y == to_.y) { + return true; + } + return false; + } + +public: + CanMove(Tile from, Tile to) : from_(from), to_(to) {} + + bool operator()(const ScoutUnit &) { return scoutMove(); } + bool operator()(const MinerUnit &) { return regularMove(); } + bool operator()(const RegularUnit &) { return regularMove(); } + bool operator()(const SpyUnit &) { return regularMove(); } + bool operator()(const FlagUnit &) { return false; } + bool operator()(const BombUnit &) { return false; } +}; \ No newline at end of file diff --git a/include/unit/visit/GetOwner.hpp b/include/unit/visit/GetOwner.hpp new file mode 100644 index 0000000..83f7829 --- /dev/null +++ b/include/unit/visit/GetOwner.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include "unit/UnitConcepts.hpp" + +enum class Turn; +class GetOwner { +public: + template Turn operator()(const T &unit) { + return unit.get_owner(); + } +}; \ No newline at end of file diff --git a/include/unit/visit/GetTileInfo.hpp b/include/unit/visit/GetTileInfo.hpp new file mode 100644 index 0000000..6bb9aa0 --- /dev/null +++ b/include/unit/visit/GetTileInfo.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#include "Turn.hpp" +#include "unit/UnitConcepts.hpp" + +class GetTileInfo { +private: + Turn player_; + +public: + explicit GetTileInfo(Turn player) : player_(player) {} + + template std::string operator()(const UnitType &unit) { + if (unit.get_owner() != player_) { + return "enemy"; + } else { + return unit.get_type(); + } + } +}; \ No newline at end of file diff --git a/include/unit/visit/GetUnitSpriteId.hpp b/include/unit/visit/GetUnitSpriteId.hpp new file mode 100644 index 0000000..870b140 --- /dev/null +++ b/include/unit/visit/GetUnitSpriteId.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "unit/Unit.hpp" + +class GetUnitSpriteId { +public: + int operator()(const RegularUnit &unit) { return unit.get_value() - 2; } + int operator()(const ScoutUnit &) { return 0; } + int operator()(const MinerUnit &) { return 1; } + int operator()(const BombUnit &) { return 9; } + int operator()(const FlagUnit &) { return 10; } + int operator()(const SpyUnit &) { return 11; } +}; \ No newline at end of file diff --git a/infra/hooks/pre-commit b/infra/hooks/pre-commit new file mode 100644 index 0000000..629a96a --- /dev/null +++ b/infra/hooks/pre-commit @@ -0,0 +1,55 @@ +#!/bin/bash +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat < #include "Board.hpp" - -AttackInfoBox::AttackInfoBox(std::array& red_units_sprites, std::array& blue_units_sprites, sf::Sprite& winning_unit_highlight) - : path_to_textures("images/board/"), - attacking_unit_pos_x(-1), - attacking_unit_pos_y(-1), - attacked_unit_pos_x(-1), - attacked_unit_pos_y(-1), - attacking_unit{}, - attacked_unit{}, - attacker_ptr{}, - attacked_ptr{}, - winner_highlight(winning_unit_highlight) { - for (int i = 0; i < red_units_sprites_ptrs.size(); ++i) { - red_units_sprites_ptrs[i] = &red_units_sprites[i]; - } - for (int i = 0; i < blue_units_sprites_ptrs.size(); ++i) { - blue_units_sprites_ptrs[i] = &blue_units_sprites[i]; - } - load_box_texture(); - load_font(); - box_text.setFont(box_font); - box_text.setString("VS"); - box_text.setFillColor(sf::Color::Yellow); - box_text.setCharacterSize(40); - box_sprite.setTexture(box_texture); +#include "unit/visit/Attack.hpp" +#include "unit/visit/GetOwner.hpp" +#include "unit/visit/GetUnitSpriteId.hpp" + +AttackInfoBox::AttackInfoBox(std::array &red_units_sprites, + std::array &blue_units_sprites, + sf::Sprite &winning_unit_highlight) + : path_to_textures("images/board/"), attacking_unit_pos_x(-1.0f), + attacking_unit_pos_y(-1.0f), attacked_unit_pos_x(-1.0f), + attacked_unit_pos_y(-1.0f), attacking_unit{}, attacked_unit{}, + attacker_ptr{}, attacked_ptr{}, winner_highlight(winning_unit_highlight) { + for (int i = 0; i < red_units_sprites_ptrs.size(); ++i) { + red_units_sprites_ptrs[i] = &red_units_sprites[i]; + } + for (int i = 0; i < blue_units_sprites_ptrs.size(); ++i) { + blue_units_sprites_ptrs[i] = &blue_units_sprites[i]; + } + load_box_texture(); + load_font(); + box_text.setFont(box_font); + box_text.setString("VS"); + box_text.setFillColor(sf::Color::Yellow); + box_text.setCharacterSize(40); + box_sprite.setTexture(box_texture); } -void AttackInfoBox::draw(sf::RenderWindow& win) { - update_attacked_unit_pos(); - update_attacking_unit_pos(); - update_box_text_pos(); - set_winner_highlight(); - win.draw(box_sprite); - win.draw(attacking_unit); - win.draw(box_text); - win.draw(attacked_unit); - draw_winner_highlight(win); +void AttackInfoBox::draw(sf::RenderWindow &win) { + update_attacked_unit_pos(); + update_attacking_unit_pos(); + update_box_text_pos(); + set_winner_highlight(); + win.draw(box_sprite); + win.draw(attacking_unit); + win.draw(box_text); + win.draw(attacked_unit); + draw_winner_highlight(win); } void AttackInfoBox::load_box_texture() { - if (!box_texture.loadFromFile(path_to_textures + "attack_info_box.png")) { - std::cerr << "attack info box texture failed to load!\n"; - abort(); - } + if (!box_texture.loadFromFile(path_to_textures + "attack_info_box.png")) { + std::cerr << "attack info box texture failed to load!\n"; + abort(); + } } void AttackInfoBox::load_font() { - if (!box_font.loadFromFile("font/lunchds.ttf")) { - std::cerr << "failed to load attack info box font!\n"; - abort(); - } + if (!box_font.loadFromFile("font/lunchds.ttf")) { + std::cerr << "failed to load attack info box font!\n"; + abort(); + } } -int AttackInfoBox::get_unit_sprite_idx(const std::shared_ptr& unit) { - if (!unit) { - return -1; - } - if (unit->get_type() == "regular") { - return unit->get_value() - 2; - } - if (unit->get_type() == "scout") { - return 0; - } - if (unit->get_type() == "miner") { - return 1; - } - if (unit->get_type() == "bomb") { - return 9; - } - if (unit->get_type() == "flag") { - return 10; - } - if (unit->get_type() == "spy") { - return 11; - } - return -1; +int AttackInfoBox::get_unit_sprite_idx(const Unit &unit) { + return std::visit(GetUnitSpriteId{}, unit); } void AttackInfoBox::set_position(int x, int y) { - box_sprite.setPosition(x, y); - update_attacking_unit_pos(); - update_attacked_unit_pos(); - update_box_text_pos(); - set_winner_highlight(); + box_sprite.setPosition(static_cast(x), static_cast(y)); + update_attacking_unit_pos(); + update_attacked_unit_pos(); + update_box_text_pos(); + set_winner_highlight(); } -void AttackInfoBox::set_attacking_unit(const std::shared_ptr& attacker) { - if (!attacker) { - return; - } - if (attacker->get_owner() == TURN::PLAYER_A) { - attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; - } else { - attacking_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; - } - attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); - attacking_unit.scale(1.5, 1.5); - attacker_ptr = attacker; +void AttackInfoBox::set_attacking_unit(const std::optional &attacker) { + if (!attacker) { + return; + } + const auto attackerUnit = attacker.value(); + if (std::visit(GetOwner{}, attackerUnit) == Turn::PlayerA) { + attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; + } else { + attacking_unit = + *blue_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; + } + attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); + attacking_unit.scale(1.5, 1.5); + attacker_ptr = &attackerUnit; } -void AttackInfoBox::set_attacked_unit(const std::shared_ptr& victim) { - if (!victim) { - return; - } - if (victim->get_owner() == TURN::PLAYER_A) { - attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victim)]; - } else { - attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victim)]; - } - attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); - attacked_unit.scale(1.5, 1.5); - attacked_ptr = victim; +void AttackInfoBox::set_attacked_unit(const std::optional &victim) { + if (!victim) { + return; + } + const auto victimUnit = victim.value(); + if (std::visit(GetOwner{}, victimUnit) == Turn::PlayerA) { + attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; + } else { + attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; + } + attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); + attacked_unit.scale(1.5, 1.5); + attacked_ptr = &victimUnit; } void AttackInfoBox::update_attacking_unit_pos() { - attacking_unit_pos_x = box_sprite.getPosition().x + (get_width() / 4); - attacking_unit_pos_y = box_sprite.getPosition().y + ((get_height() - attacking_unit.getGlobalBounds().height) / 2); - attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); + attacking_unit_pos_x = box_sprite.getPosition().x + (get_width() / 4); + attacking_unit_pos_y = + box_sprite.getPosition().y + + ((get_height() - attacking_unit.getGlobalBounds().height) / 2); + attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); } void AttackInfoBox::update_attacked_unit_pos() { - attacked_unit_pos_x = box_sprite.getPosition().x + get_width() * 3 / 4 - attacked_unit.getGlobalBounds().width; - attacked_unit_pos_y = attacking_unit_pos_y; - attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); + attacked_unit_pos_x = box_sprite.getPosition().x + get_width() * 3 / 4 - + attacked_unit.getGlobalBounds().width; + attacked_unit_pos_y = attacking_unit_pos_y; + attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); } void AttackInfoBox::update_box_text_pos() { - box_text.setPosition(box_sprite.getPosition().x + ((get_width() - box_text.getLocalBounds().width) / 2), - box_sprite.getPosition().y + (get_height() - box_text.getCharacterSize()) / 2); + box_text.setPosition( + box_sprite.getPosition().x + + ((get_width() - box_text.getLocalBounds().width) / 2), + box_sprite.getPosition().y + + (get_height() - box_text.getCharacterSize()) / 2); } -std::shared_ptr AttackInfoBox::get_winner() { - if (!attacked_ptr) { - return std::shared_ptr{}; - } - if (!attacker_ptr) { - return std::shared_ptr{}; - } - if (const Movable* movable = dynamic_cast(attacker_ptr.get())) { - if (movable->attack(attacked_ptr) == RESULT::WON) { - return attacker_ptr; - } - if (movable->attack(attacked_ptr) == RESULT::LOST) { - return attacked_ptr; - } - } - return std::shared_ptr{}; +const Unit *AttackInfoBox::get_winner() { + if (!attacked_ptr || !attacker_ptr) { + return {}; + } + const auto result = std::visit(Attack{}, *attacker_ptr, *attacked_ptr); + if (result == attack::Result::Won) { + return attacker_ptr; + } + if (result == attack::Result::Lost) { + return attacked_ptr; + } + // FIXME: what happens with a Draw? Both are winners then + return {}; } void AttackInfoBox::set_winner_highlight() { - if (get_winner() == attacker_ptr) { - winner_highlight.setPosition(attacking_unit.getPosition()); - } - if (get_winner() == attacked_ptr) { - winner_highlight.setPosition(attacked_unit.getPosition()); - } + if (get_winner() == attacker_ptr) { + winner_highlight.setPosition(attacking_unit.getPosition()); + } + if (get_winner() == attacked_ptr) { + winner_highlight.setPosition(attacked_unit.getPosition()); + } } -void AttackInfoBox::draw_winner_highlight(sf::RenderWindow& win) { - if (!get_winner()) { - return; - } - winner_highlight.setScale(1.5, 1.5); - win.draw(winner_highlight); - winner_highlight.setScale(1, 1); +void AttackInfoBox::draw_winner_highlight(sf::RenderWindow &win) { + if (!get_winner()) { + return; + } + winner_highlight.setScale(1.5f, 1.5f); + win.draw(winner_highlight); + winner_highlight.setScale(1.0f, 1.0f); } \ No newline at end of file diff --git a/src/BigButton.cpp b/src/BigButton.cpp index b60861e..bc3ac7b 100644 --- a/src/BigButton.cpp +++ b/src/BigButton.cpp @@ -2,34 +2,34 @@ #include -BigButton::BigButton(const std::string& text) - : ButtonInterface(text) { - load_button_texture(); - load_highlighted_button_texture(); +BigButton::BigButton(const std::string &text) : ButtonInterface(text) { + load_button_texture(); + load_highlighted_button_texture(); - button.setTexture(button_texture); - highlighted_button.setTexture(highlighted_button_texture); + button.setTexture(button_texture); + highlighted_button.setTexture(highlighted_button_texture); } void BigButton::load_button_texture() { - if (!button_texture.loadFromFile(path_to_textures + "big_button.png")) { - std::cerr << "big button texture failed to load!\n"; - abort(); - } + if (!button_texture.loadFromFile(path_to_textures + "big_button.png")) { + std::cerr << "big button texture failed to load!\n"; + abort(); + } } void BigButton::load_highlighted_button_texture() { - if (!highlighted_button_texture.loadFromFile(path_to_textures + "big_button_highlighted.png")) { - std::cerr << "big button highlighted texture failed to load!\n"; - abort(); - } + if (!highlighted_button_texture.loadFromFile(path_to_textures + + "big_button_highlighted.png")) { + std::cerr << "big button highlighted texture failed to load!\n"; + abort(); + } } -void BigButton::draw(sf::RenderWindow& win) { - if (highlighted) { - win.draw(highlighted_button); - } else { - win.draw(button); - } - win.draw(button_text); +void BigButton::draw(sf::RenderWindow &win) { + if (highlighted) { + win.draw(highlighted_button); + } else { + win.draw(button); + } + win.draw(button_text); } \ No newline at end of file diff --git a/src/Board.cpp b/src/Board.cpp index 164dddc..39c6a08 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -5,293 +5,270 @@ #include #include -#include "BombUnit.hpp" -#include "FlagUnit.hpp" -#include "MinerUnit.hpp" -#include "RegularUnit.hpp" -#include "ScoutUnit.hpp" -#include "SpyUnit.hpp" +#include "unit/BombUnit.hpp" +#include "unit/FlagUnit.hpp" +#include "unit/MinerUnit.hpp" +#include "unit/RegularUnit.hpp" +#include "unit/ScoutUnit.hpp" +#include "unit/SpyUnit.hpp" +#include "unit/visit/CanMove.hpp" +#include "unit/visit/GetTileInfo.hpp" Board::Board() - : height(12), - width(10), - current_state(STATE::UNINITIALIZED), - unit_count(0), - units(width, height), - max_count_of_each_unit({{"flag", 1}, - {"scout", 8}, - {"miner", 5}, - {"bomb", 6}, - {"spy", 1}, - {"regular4", 4}, - {"regular5", 4}, - {"regular6", 4}, - {"regular7", 3}, - {"regular8", 2}, - {"regular9", 1}, - {"regular10", 1}}) { - set_obstacles(); - set_default_units(); + : height(12), width(10), current_state(State::Uninitialized), unit_count(0), + units(width, height) { + set_obstacles(); + set_default_units(); } void Board::set_default_units() { - for (int row = 0; row < height; ++row) { - for (int col = 0; col < width; ++col) { - units[row][col].reset(); - units[row][col] = nullptr; - } + for (int row = 0; row < height; ++row) { + for (int col = 0; col < width; ++col) { + unset_unit(Tile{col, row}); } + } } void Board::set_obstacles() { - int left_obstacle_x = 2; - int obstacle_y = 5; - int right_obstacle_x = 6; - int j = 0; - for (size_t i = 0; i < obstacles.size(); ++i) { - if (i % 2 == 0) { - j = 0; - } - if (i < 2) { - obstacles[i].x = left_obstacle_x + j; - obstacles[i].y = obstacle_y; - } - if (i > 1 && i < 4) { - obstacles[i].x = left_obstacle_x + j; - obstacles[i].y = obstacle_y + 1; - } - if (i > 3 && i < 6) { - obstacles[i].x = right_obstacle_x + j; - obstacles[i].y = obstacle_y; - } - if (i > 5 && i < 8) { - obstacles[i].x = right_obstacle_x + j; - obstacles[i].y = obstacle_y + 1; - } - j++; - } + int left_obstacle_x = 2; + int obstacle_y = 5; + int right_obstacle_x = 6; + int j = 0; + for (size_t i = 0; i < obstacles.size(); ++i) { + if (i % 2 == 0) { + j = 0; + } + if (i < 2) { + obstacles[i].x = left_obstacle_x + j; + obstacles[i].y = obstacle_y; + } + if (i > 1 && i < 4) { + obstacles[i].x = left_obstacle_x + j; + obstacles[i].y = obstacle_y + 1; + } + if (i > 3 && i < 6) { + obstacles[i].x = right_obstacle_x + j; + obstacles[i].y = obstacle_y; + } + if (i > 5 && i < 8) { + obstacles[i].x = right_obstacle_x + j; + obstacles[i].y = obstacle_y + 1; + } + j++; + } +} + +bool Board::is_unit_set(Tile tile) const { + return units[tile.y][tile.x].has_value(); } +void Board::unset_unit(Tile tile) { units[tile.y][tile.x] = std::nullopt; } + bool Board::out_of_range(int col, int row) const { - if (col < 0 || col >= width) { - return true; - } - if (row < 0 || row >= height) { - return true; - } - return false; + if (col < 0 || col >= width) { + return true; + } + if (row < 0 || row >= height) { + return true; + } + return false; } -std::string Board::get_tile_info(int col, int row, TURN player) const { - if (out_of_range(col, row)) { - return "#"; - } - if (std::find_if(obstacles.begin(), obstacles.end(), [col, row](const Board::Tile& tile) { - return tile.x == col && tile.y == row; - }) != obstacles.end()) { - return "O"; - } - if (units[row][col]) { - if (units[row][col]->get_owner() != player) { - return "enemy"; - } else { - return units[row][col]->get_type(); - } - } +std::string Board::get_tile_info(int col, int row, Turn player) const { + if (out_of_range(col, row)) { + return "#"; + } + if (!is_unit_set(Tile{col, row})) { return " "; + } + if (std::find_if(obstacles.begin(), obstacles.end(), + [col, row](const Tile &tile) { + return tile.x == col && tile.y == row; + }) != obstacles.end()) { + return "O"; + } + return std::visit(GetTileInfo{player}, units[row][col].value()); } -std::string Board::get_tile_info(const Tile& tile, TURN player) const { - return get_tile_info(tile.x, tile.y, player); +std::string Board::get_tile_info(const Tile &tile, Turn player) const { + return get_tile_info(tile.x, tile.y, player); } int Board::get_max_unit_count(int idx) const { - switch (idx) { - case 0: - return max_count_of_each_unit.at("scout"); - case 1: - return max_count_of_each_unit.at("miner"); - case 2: - return max_count_of_each_unit.at("regular4"); - case 3: - return max_count_of_each_unit.at("regular5"); - case 4: - return max_count_of_each_unit.at("regular6"); - case 5: - return max_count_of_each_unit.at("regular7"); - case 6: - return max_count_of_each_unit.at("regular8"); - case 7: - return max_count_of_each_unit.at("regular9"); - case 8: - return max_count_of_each_unit.at("regular10"); - case 9: - return max_count_of_each_unit.at("bomb"); - case 10: - return max_count_of_each_unit.at("flag"); - case 11: - return max_count_of_each_unit.at("spy"); - } - return -1; + switch (idx) { + case 0: + return ScoutUnit::get_max_count(); + case 1: + return MinerUnit::get_max_count(); + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return RegularUnit::get_max_count(idx + 2); + case 9: + return BombUnit::get_max_count(); + case 10: + return FlagUnit::get_max_count(); + case 11: + return SpyUnit::get_max_count(); + } + return -1; } -void Board::set_state(STATE state) { - current_state = state; -} +void Board::set_state(State state) { current_state = state; } -bool Board::set_unit(int col, int row, TURN player, int choice) { - if (col < 0 || col >= width) { - return false; - } - if (row < (height - 4) || row >= height) { - return false; - } - if (choice < 0 && choice >= 12) { - return false; - } - if (get_tile_info(col, row, player) != " ") { - return false; - } - if (current_state == STATE::FULL) { - return false; - } +bool Board::set_unit(int col, int row, Turn player, int choice) { + if (col < 0 || col >= width) { + return false; + } + if (row < (height - 4) || row >= height) { + return false; + } + if (choice < 0 && choice >= 12) { + return false; + } + if (get_tile_info(col, row, player) != " ") { + return false; + } + if (current_state == State::Full) { + return false; + } - switch (choice + 2) { - case 2: { - units[row][col] = std::make_shared(player); - } break; - case 3: { - units[row][col] = std::make_shared(player); - } break; - case 11: { - units[row][col] = std::make_shared(player); - } break; - case 12: { - units[row][col] = std::make_shared(player); - } break; - case 13: { - units[row][col] = std::make_shared(player); - } - } - if (choice + 2 > 3 && choice + 2 < 11) { - units[row][col] = std::make_shared(choice + 2, player); - } - unit_count++; - if (unit_count == MAX_UNIT_COUNT) { - current_state = STATE::FULL; - } - return true; + switch (choice + 2) { + case 2: { + units[row][col] = ScoutUnit(player); + } break; + case 3: { + units[row][col] = MinerUnit(player); + } break; + case 11: { + units[row][col] = BombUnit(player); + } break; + case 12: { + units[row][col] = FlagUnit(player); + } break; + case 13: { + units[row][col] = SpyUnit(player); + } + } + if (choice + 2 > 3 && choice + 2 < 11) { + units[row][col] = RegularUnit(choice + 2, player); + } + unit_count++; + if (unit_count == MAX_UNIT_COUNT) { + current_state = State::Full; + } + return true; } void Board::remove_unit(int col, int row) { - units[row][col].reset(); - unit_count--; - if (current_state == STATE::FULL) { - current_state = STATE::UNINITIALIZED; - } + unset_unit(Tile{col, row}); + unit_count--; + if (current_state == State::Full) { + current_state = State::Uninitialized; + } } void Board::reverse_remove_unit(int col, int row) { - Board::Tile unit = point_reflection(col, row); - units[unit.y][unit.x].reset(); + Tile unit = point_reflection(col, row); + unset_unit(unit); } -bool Board::can_move(const Tile& from, const Tile& to) const { - if (out_of_range(from.x, from.y)) { - return false; - } - if (!units[from.y][from.x]) { - return false; - } - if (const Movable* movable = dynamic_cast(units[from.y][from.x].get()) ) { - return movable->can_move(from, to); - } +bool Board::can_move(const Tile &from, const Tile &to) const { + if (out_of_range(from.x, from.y)) { return false; + } + if (!is_unit_set(from)) { + return false; + } + return std::visit(CanMove{from, to}, units[from.y][from.x].value()); } -bool Board::move_unit(const Tile& from, const Tile& to) { - if (can_move(from, to)) { - units[from.y][from.x].swap(units[to.y][to.x]); - return true; - } - return false; +bool Board::move_unit(const Tile &from, const Tile &to) { + using std::swap; + if (can_move(from, to)) { + swap(units[from.y][from.x], units[to.y][to.x]); + return true; + } + return false; } -void Board::reverse_move_unit(const Tile& from, const Tile& to) { - Tile rev_from = point_reflection(from.x, from.y); - Tile rev_to = point_reflection(to.x, to.y); - std::shared_ptr temp_ptr = units[rev_from.y][rev_from.x]; //<---- this does! (whaaat?) - units[rev_from.y][rev_from.x] = units[rev_to.y][rev_to.x]; - units[rev_to.y][rev_to.x] = temp_ptr; - // units[rev_from.y][rev_from.y].swap(units[rev_to.y][rev_to.x]); <---- this doesnt work! +void Board::reverse_move_unit(const Tile &from, const Tile &to) { + using std::swap; + Tile rev_from = point_reflection(from.x, from.y); + Tile rev_to = point_reflection(to.x, to.y); + swap(units[rev_from.y][rev_from.x], units[rev_to.y][rev_to.x]); } -Board::Tile Board::point_reflection(int col, int row) { - Board::Tile distance; - Board::Tile distance_point; - Board::Tile reflection; - Board::Tile reflection_point; - if (col >= 5 && row <= 5) { //first quarter of the board - distance_point = Board::Tile(4, 6); - reflection_point = Board::Tile(5, 5); - } - if (col <= 4 && row <= 5) { //second quarter of the board - distance_point = Board::Tile(5, 6); - reflection_point = Board::Tile(4, 5); - } - if (col <= 4 && row >= 6) { //third quarter of the board - distance_point = Board::Tile(5, 5); - reflection_point = Board::Tile(4, 6); - } - if (col >= 5 && row >= 6) { //fourth quarter of the board - distance_point = Board::Tile(4, 5); - reflection_point = Board::Tile(5, 6); - } - distance.x = col - distance_point.x; - distance.y = row - distance_point.y; - reflection.x = -distance.x; - reflection.y = -distance.y; - return Board::Tile(reflection_point.x + reflection.x, reflection_point.y + reflection.y); +Tile Board::point_reflection(int col, int row) { + Tile distance; + Tile distance_point; + Tile reflection; + Tile reflection_point; + if (col >= 5 && row <= 5) { // first quarter of the board + distance_point = Tile(4, 6); + reflection_point = Tile(5, 5); + } + if (col <= 4 && row <= 5) { // second quarter of the board + distance_point = Tile(5, 6); + reflection_point = Tile(4, 5); + } + if (col <= 4 && row >= 6) { // third quarter of the board + distance_point = Tile(5, 5); + reflection_point = Tile(4, 6); + } + if (col >= 5 && row >= 6) { // fourth quarter of the board + distance_point = Tile(4, 5); + reflection_point = Tile(5, 6); + } + distance.x = col - distance_point.x; + distance.y = row - distance_point.y; + reflection.x = -distance.x; + reflection.y = -distance.y; + return Tile(reflection_point.x + reflection.x, + reflection_point.y + reflection.y); } -Board& Board::operator=(const Board& rhs) { - if (this == &rhs) { - return *this; - } - height = rhs.height; - width = rhs.width; - for (int row = 0; row < height; ++row) { - for (int col = 0; col < width; ++col) { - units[row][col] = rhs.units[row][col]; - } - } - for (size_t i = 0; i < obstacles.size(); ++i) { - obstacles[i] = rhs.obstacles[i]; - } +Board &Board::operator=(const Board &rhs) { + if (this == &rhs) { return *this; + } + height = rhs.height; + width = rhs.width; + for (int row = 0; row < height; ++row) { + for (int col = 0; col < width; ++col) { + units[row][col] = rhs.units[row][col]; + } + } + for (size_t i = 0; i < obstacles.size(); ++i) { + obstacles[i] = rhs.obstacles[i]; + } + return *this; } -void Board::update(const Board& other_board) { - Board::Tile other_unit; - *this = other_board; - for (int row = 0; row < height / 2; ++row) { - for (int col = 0; col < width; ++col) { - other_unit = point_reflection(col, row); - units[other_unit.y][other_unit.x].swap(units[row][col]); - } - } +void Board::update(const Board &other_board) { + using std::swap; + Tile other_unit; + *this = other_board; + for (int row = 0; row < height / 2; ++row) { + for (int col = 0; col < width; ++col) { + other_unit = point_reflection(col, row); + swap(units[other_unit.y][other_unit.x], units[row][col]); + } + } } -std::shared_ptr Board::get_unit(int col, int row) const { - if (out_of_range(col, row)) { - return std::shared_ptr{}; - } - return units[row][col]; +const std::optional &Board::get_unit(int col, int row) const { + if (out_of_range(col, row)) { + // TODO: maybe more sophisticated error handling? + return std::nullopt; + } + return units[row][col]; } -std::shared_ptr Board::get_unit(const Board::Tile& chosen_unit) const { - if (out_of_range(chosen_unit.x, chosen_unit.y)) { - return std::shared_ptr{}; - } - return units[chosen_unit.y][chosen_unit.x]; +const std::optional &Board::get_unit(const Tile &chosen_unit) const { + return get_unit(chosen_unit.x, chosen_unit.y); } \ No newline at end of file diff --git a/src/Box.cpp b/src/Box.cpp index 24a8ce4..1441669 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -3,125 +3,137 @@ #include #include -Box::Box(const std::string& text) - : path_to_textures("images/board/"), - max_char_count_inside_box(12), - max_number_of_text_lines_inside_box(3), - box_text_x_pos(-1), - box_text_y_pos(-1), - button_x_pos(-1), - button_y_pos(-1) { - load_box_texture(); - load_font(); - set_default_text(text); - update_max_char_count(); - set_button_text(); - box_sprite.setTexture(box_texture); - update_button_pos(); - update_text_pos(); +Box::Box(const std::string &text) + : path_to_textures("images/board/"), max_char_count_inside_box(12), + max_number_of_text_lines_inside_box(3), box_text_x_pos(-1.0f), + box_text_y_pos(-1.0f), button_x_pos(-1.0f), button_y_pos(-1.0f) { + load_box_texture(); + load_font(); + set_default_text(text); + update_max_char_count(); + set_button_text(); + box_sprite.setTexture(box_texture); + update_button_pos(); + update_text_pos(); } void Box::load_box_texture() { - if (!box_texture.loadFromFile(path_to_textures + "box.png")) { - std::cerr << "box texture failed to load!\n"; - abort(); - } + if (!box_texture.loadFromFile(path_to_textures + "box.png")) { + std::cerr << "box texture failed to load!\n"; + abort(); + } } void Box::load_font() { - if (!font.loadFromFile("font/chandas1-2.ttf")) { - std::cerr << "font failed to load inside Box class!\n"; - abort(); - } + if (!font.loadFromFile("font/chandas1-2.ttf")) { + std::cerr << "font failed to load inside Box class!\n"; + abort(); + } } -void Box::set_default_text(const std::string& text) { - box_text.setFont(font); - box_text.setString(text); - update_text_pos(); +void Box::set_default_text(const std::string &text) { + box_text.setFont(font); + box_text.setString(text); + update_text_pos(); } void Box::update_text_pos() { - box_text_x_pos = (box_sprite.getPosition().x + (box_sprite.getGlobalBounds().width - box_text.getLocalBounds().width) / 2); - box_text_y_pos = (box_sprite.getPosition().y + 2 * box_text.getCharacterSize()); - box_text.setPosition(box_text_x_pos, box_text_y_pos); + box_text_x_pos = + (box_sprite.getPosition().x + + (box_sprite.getGlobalBounds().width - box_text.getLocalBounds().width) / + 2); + box_text_y_pos = static_cast(box_sprite.getPosition().y + + 2 * box_text.getCharacterSize()); + box_text.setPosition(box_text_x_pos, box_text_y_pos); } void Box::update_button_pos() { - button_x_pos = box_sprite.getPosition().x + (box_sprite.getGlobalBounds().width - button.get_width()) / 2; - button_y_pos = box_sprite.getPosition().y + box_sprite.getGlobalBounds().height - 2 * box_text.getCharacterSize() - button.get_height(); - button.set_position(button_x_pos, button_y_pos); + button_x_pos = box_sprite.getPosition().x + + (box_sprite.getGlobalBounds().width - button.get_width()) / 2; + button_y_pos = static_cast( + box_sprite.getPosition().y + box_sprite.getGlobalBounds().height - + 2 * box_text.getCharacterSize() - button.get_height()); + button.set_position(button_x_pos, button_y_pos); } void Box::set_position(int x, int y) { - box_sprite.setPosition(x, y); - update_text_pos(); - box_text.setPosition(box_text_x_pos, box_text_y_pos); - update_button_pos(); - button.set_position(button_x_pos, button_y_pos); + box_sprite.setPosition(x, y); + update_text_pos(); + box_text.setPosition(box_text_x_pos, box_text_y_pos); + update_button_pos(); + button.set_position(button_x_pos, button_y_pos); } -void Box::set_position(const sf::Vector2f& coords) { - set_position(coords.x, coords.y); +void Box::set_position(const sf::Vector2f &coords) { + set_position(coords.x, coords.y); } -void Box::set_text(const std::string& text) { - box_text.setString(text); - break_text_into_lines(); - update_text_pos(); +void Box::set_text(const std::string &text) { + box_text.setString(text); + break_text_into_lines(); + update_text_pos(); } -void Box::set_button_text(const std::string& text) { - button.set_text(text); -} +void Box::set_button_text(const std::string &text) { button.set_text(text); } -void Box::draw(sf::RenderWindow& win) { - win.draw(box_sprite); - win.draw(box_text); - button.draw(win); +void Box::draw(sf::RenderWindow &win) { + win.draw(box_sprite); + win.draw(box_text); + button.draw(win); } void Box::update_max_char_count() { - int max_chars_per_line = box_sprite.getLocalBounds().width / box_text.getCharacterSize(); - max_char_count_inside_box = max_chars_per_line * max_number_of_text_lines_inside_box; + int max_chars_per_line = static_cast(box_sprite.getLocalBounds().width / + box_text.getCharacterSize()); + max_char_count_inside_box = + max_chars_per_line * max_number_of_text_lines_inside_box; } void Box::break_text_into_lines() { - if (box_text.getString().getSize() * box_text.getCharacterSize() < box_sprite.getLocalBounds().width) { - return; + if (box_text.getString().getSize() * box_text.getCharacterSize() < + box_sprite.getLocalBounds().width) { + return; + } + std::istringstream temp_stream(box_text.getString()); + std::vector words( + (std::istream_iterator(temp_stream)), + std::istream_iterator()); + std::string temp_text; + size_t char_count_inside_line = 0; + size_t line_count = 0; + size_t space_count_in_line = 0; + size_t char_count_that_will_fit_in_line = 0; + size_t char_count_of_next_word = 0; + size_t idx_of_the_first_char_in_new_line = 0; + for (size_t i = 0; i < words.size() - 1; ++i) { + char_count_of_next_word = words[i + 1].size(); + char_count_inside_line += words[i].size(); + if (char_count_inside_line * box_text.getCharacterSize() > get_width()) { + temp_text += (words[i] + "\n"); + line_count++; + idx_of_the_first_char_in_new_line = char_count_inside_line + 2; + char_count_inside_line = 0; + } else { + char_count_that_will_fit_in_line = + static_cast(box_sprite.getLocalBounds().width) - + char_count_inside_line * box_text.getCharacterSize(); + if (char_count_of_next_word > char_count_that_will_fit_in_line || + i == words.size() - 2) { + float denting = (box_sprite.getLocalBounds().width - + char_count_inside_line * box_text.getCharacterSize()) / + 2; + int spaces = + static_cast(denting / box_text.getCharacterSize() + 0.5); + temp_text.insert(idx_of_the_first_char_in_new_line, spaces, ' '); + } + temp_text += (words[i] + " "); + } + if (line_count > 3) { + break; } - std::istringstream temp_stream(box_text.getString()); - std::vector words((std::istream_iterator(temp_stream)), std::istream_iterator()); - std::string temp_text; - size_t char_count_inside_line = 0; - size_t line_count = 0; - size_t space_count_in_line = 0; - size_t char_count_that_will_fit_in_line = 0; - size_t char_count_of_next_word = 0; - size_t idx_of_the_first_char_in_new_line = 0; - for (size_t i = 0; i < words.size() - 1; ++i) { - char_count_of_next_word = words[i + 1].size(); - char_count_inside_line += words[i].size(); - if (char_count_inside_line * box_text.getCharacterSize() > get_width()) { - temp_text += (words[i] + "\n"); - line_count++; - idx_of_the_first_char_in_new_line = char_count_inside_line + 2; - char_count_inside_line = 0; - } else { - char_count_that_will_fit_in_line = box_sprite.getLocalBounds().width - char_count_inside_line * box_text.getCharacterSize(); - if (char_count_of_next_word > char_count_that_will_fit_in_line || i == words.size() - 2) { - float denting = (box_sprite.getLocalBounds().width - char_count_inside_line * box_text.getCharacterSize()) / 2; - int spaces = (denting / box_text.getCharacterSize() + 0.5); - temp_text.insert(idx_of_the_first_char_in_new_line, spaces, ' '); - } - temp_text += (words[i] + " "); - } - if (line_count > 3) { - break; - } - if (i == words.size() - 2) { - temp_text += words[i + 1]; - } + if (i == words.size() - 2) { + temp_text += words[i + 1]; } - box_text.setString(temp_text); + } + box_text.setString(temp_text); } diff --git a/src/Button.cpp b/src/Button.cpp index 13f2319..1284e03 100644 --- a/src/Button.cpp +++ b/src/Button.cpp @@ -2,34 +2,34 @@ #include -Button::Button(const std::string& text) -:ButtonInterface(text) -{ - load_button_texture(); - load_highlighted_button_texture(); - button.setTexture(button_texture); - highlighted_button.setTexture(highlighted_button_texture); +Button::Button(const std::string &text) : ButtonInterface(text) { + load_button_texture(); + load_highlighted_button_texture(); + button.setTexture(button_texture); + highlighted_button.setTexture(highlighted_button_texture); } void Button::load_button_texture() { - if (!button_texture.loadFromFile(path_to_textures + "button.png")) { - std::cerr << "wooden texture loading inside Button class failed!\n"; - abort(); - } + if (!button_texture.loadFromFile(path_to_textures + "button.png")) { + std::cerr << "wooden texture loading inside Button class failed!\n"; + abort(); + } } void Button::load_highlighted_button_texture() { - if (!highlighted_button_texture.loadFromFile(path_to_textures + "button_highlighted.png")) { - std::cerr << "highlighted wooden texture loading inside Button class failed!\n"; - abort(); - } + if (!highlighted_button_texture.loadFromFile(path_to_textures + + "button_highlighted.png")) { + std::cerr << "highlighted wooden texture loading inside Button class " + "failed!\n"; + abort(); + } } -void Button::draw(sf::RenderWindow& win) { - if (highlighted) { - win.draw(highlighted_button); - } else { - win.draw(button); - } - win.draw(button_text); +void Button::draw(sf::RenderWindow &win) { + if (highlighted) { + win.draw(highlighted_button); + } else { + win.draw(button); + } + win.draw(button_text); } diff --git a/src/ButtonInterface.cpp b/src/ButtonInterface.cpp index ed4c67c..69d7182 100644 --- a/src/ButtonInterface.cpp +++ b/src/ButtonInterface.cpp @@ -2,44 +2,48 @@ #include -ButtonInterface::ButtonInterface(const std::string& text) +ButtonInterface::ButtonInterface(const std::string &text) : path_to_textures("images/board/") { - load_font(); - set_default_button_text(text); - update_text_pos(); - highlighted = false; + load_font(); + set_default_button_text(text); + update_text_pos(); + highlighted = false; } void ButtonInterface::load_font() { - if (!font.loadFromFile("font/chandas1-2.ttf")) { - std::cerr << "font failed loading inside ButtonInterface class!\n"; - abort(); - } + if (!font.loadFromFile("font/chandas1-2.ttf")) { + std::cerr << "font failed loading inside ButtonInterface class!\n"; + abort(); + } } -void ButtonInterface::set_default_button_text(const std::string& text) { - button_text.setFont(font); - button_text.setString(text); - button_text.setFillColor(sf::Color::Yellow); +void ButtonInterface::set_default_button_text(const std::string &text) { + button_text.setFont(font); + button_text.setString(text); + button_text.setFillColor(sf::Color::Yellow); } void ButtonInterface::update_text_pos() { - text_x_pos = (button.getPosition().x + (button.getGlobalBounds().width - button_text.getLocalBounds().width) / 2); - text_y_pos = (button.getPosition().y + (button.getGlobalBounds().height - button_text.getCharacterSize()) / 2); - button_text.setPosition(text_x_pos, text_y_pos); + text_x_pos = (button.getPosition().x + (button.getGlobalBounds().width - + button_text.getLocalBounds().width) / + 2); + text_y_pos = + (button.getPosition().y + + (button.getGlobalBounds().height - button_text.getCharacterSize()) / 2); + button_text.setPosition(text_x_pos, text_y_pos); } void ButtonInterface::set_position(int x, int y) { - button.setPosition(x, y); - highlighted_button.setPosition(x, y); - update_text_pos(); + button.setPosition(x, y); + highlighted_button.setPosition(x, y); + update_text_pos(); } void ButtonInterface::set_position(sf::Vector2f coords) { - set_position(coords.x, coords.y); + set_position(coords.x, coords.y); } -void ButtonInterface::set_text(const std::string& text) { - button_text.setString(text); - update_text_pos(); +void ButtonInterface::set_text(const std::string &text) { + button_text.setString(text); + update_text_pos(); } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..32a5ed2 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,27 @@ +add_library( + stratego-src + AttackInfoBox.cpp + BigButton.cpp + Board.cpp + Box.cpp + Button.cpp + ButtonInterface.cpp + Game.cpp + GameController.cpp + GameView.cpp + MainMenu.cpp + Player.cpp + unit/BombUnit.cpp + unit/FlagUnit.cpp + unit/MinerUnit.cpp + unit/RegularUnit.cpp + unit/ScoutUnit.cpp + unit/SpyUnit.cpp + unit/Unit.cpp + unit/UnitCounter.cpp + unit/UnitModel.cpp) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(stratego-src PUBLIC sfml-system sfml-window sfml-graphics) +target_link_libraries(${PROJECT_NAME} stratego-src) diff --git a/src/Game.cpp b/src/Game.cpp index d9bd233..7de1a07 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1,73 +1,75 @@ #include "Game.hpp" -Game::Game(GameView& g_view, GameController& g_controller) - : game_view(g_view), - game_controller(g_controller), - clock_started(false) { -} +Game::Game(GameView &g_view, GameController &g_controller) + : game_view(g_view), game_controller(g_controller), clock_started(false) {} -std::string Game::run(sf::RenderWindow& win) { - - while (win.isOpen()) { - sf::Event event; - game_view.update_players(game_controller.get_current_player(), game_controller.get_other_player()); - while (win.pollEvent(event)) { - if (event.type == sf::Event::Closed) { - win.close(); - return "exit"; - } - if (event.type == sf::Event::KeyPressed) { - if (event.key.code == sf::Keyboard::Escape) { - return "menu"; - } - } - if (event.type == sf::Event::MouseButtonPressed) { - if(game_controller.get_end_game_info_box_button_pressed()) { - return "menu"; - } - } - game_controller.handle_events(event); +std::string Game::run(sf::RenderWindow &win) { + while (win.isOpen()) { + sf::Event event; + game_view.update_players(game_controller.get_current_player(), + game_controller.get_other_player()); + while (win.pollEvent(event)) { + if (event.type == sf::Event::Closed) { + win.close(); + return "exit"; + } + if (event.type == sf::Event::KeyPressed) { + if (event.key.code == sf::Keyboard::Escape) { + return "menu"; + } + } + if (event.type == sf::Event::MouseButtonPressed) { + if (game_controller.get_end_game_info_box_button_pressed()) { + return "menu"; } - win.clear(); - draw(win); - win.display(); + } + game_controller.handle_events(event); } - return "exit"; + win.clear(); + draw(win); + win.display(); + } + return "exit"; } -void Game::draw(sf::RenderWindow& win) { - if (game_controller.get_game_finished()) { - game_view.draw_end_game_screen(win, game_controller.get_victorious_player_name()); - return; - } - game_view.draw_board_border(win); - game_view.draw_grass(win); - game_view.draw_obstacles(win); - if (game_controller.get_end_turn_button_pressed()) { - game_view.draw_info_box(win); - return; - } - game_controller.update_unit_attacked(clock.restart()); - if (game_controller.get_unit_attacked()) { - game_view.draw_attack_info_box(win, game_controller.get_attacker(), game_controller.get_attacked()); - return; - } - game_view.draw_units(win); +void Game::draw(sf::RenderWindow &win) { + if (game_controller.get_game_finished()) { + game_view.draw_end_game_screen( + win, game_controller.get_victorious_player_name()); + return; + } + game_view.draw_board_border(win); + game_view.draw_grass(win); + game_view.draw_obstacles(win); + if (game_controller.get_end_turn_button_pressed()) { + game_view.draw_info_box(win); + return; + } + game_controller.update_unit_attacked(clock.restart()); + if (game_controller.get_unit_attacked()) { + game_view.draw_attack_info_box(win, game_controller.get_attacker(), + game_controller.get_attacked()); + return; + } + game_view.draw_units(win); + if (game_controller.get_is_active_unit()) { + game_view.draw_unit_highlight(win, game_controller.get_active_unit()); + } + if (!game_controller.both_boards_set()) { + game_view.draw_units_for_init(win, game_controller.get_dragging(), + game_controller.get_selected_init_unit_idx(), + game_controller.get_mouse_data()); + game_view.draw_done_button(win); + game_view.draw_randomize_button(win); if (game_controller.get_is_active_unit()) { - game_view.draw_unit_highlight(win, game_controller.get_active_unit()); + game_view.draw_remove_button(win); } - if (!game_controller.both_boards_set()) { - game_view.draw_units_for_init(win, game_controller.get_dragging(), - game_controller.get_selected_init_unit_idx(), game_controller.get_mouse_data()); - game_view.draw_done_button(win); - game_view.draw_randomize_button(win); - if (game_controller.get_is_active_unit()) { - game_view.draw_remove_button(win); - } - } else { - game_view.draw_end_turn_button(win); - if (game_controller.get_is_active_unit() && !game_controller.get_unit_moved_this_round()) { - game_view.draw_possible_moves_for_active_unit(win, game_controller.get_active_unit()); - } + } else { + game_view.draw_end_turn_button(win); + if (game_controller.get_is_active_unit() && + !game_controller.get_unit_moved_this_round()) { + game_view.draw_possible_moves_for_active_unit( + win, game_controller.get_active_unit()); } + } } diff --git a/src/GameController.cpp b/src/GameController.cpp index b669106..c2efd38 100644 --- a/src/GameController.cpp +++ b/src/GameController.cpp @@ -4,308 +4,311 @@ #include "GameView.hpp" #include "Player.hpp" +#include "unit/visit/GetOwner.hpp" -GameController::GameController(Player& pA, Player& pB, GameView& g_view) - : playerA(pA), - playerB(pB), - game_view(g_view), - current_player(&pA), - other_player(&pB), - attacker{}, - attacked{}, - victorious_player_name("none"), - current_player_turn(TURN::PLAYER_A), - TILE_SIZE(64), - selected_unit_idx(0), - dragging(false), - board_a_initialized(false), - board_b_initialized(false), - is_active_unit(false), - unit_moved_this_round(false), - end_turn_button_pressed(false), - turn_approved(false), - unit_attacked(false), - remove_button_pressed(false), - done_button_pressed(false), - randomize_button_pressed(false), - end_game_info_box_button_pressed(false), - game_finished(false), - active_unit(-1, -1), - attacking_unit(-1, -1), - attacked_unit(-1, -1) { -} +GameController::GameController(Player &pA, Player &pB, GameView &g_view) + : playerA(pA), playerB(pB), game_view(g_view), current_player(&pA), + other_player(&pB), attacker{}, attacked{}, victorious_player_name("none"), + current_player_turn(Turn::PlayerA), TILE_SIZE(64), selected_unit_idx(0), + dragging(false), board_a_initialized(false), board_b_initialized(false), + is_active_unit(false), unit_moved_this_round(false), + end_turn_button_pressed(false), turn_approved(false), + unit_attacked(false), remove_button_pressed(false), + done_button_pressed(false), randomize_button_pressed(false), + end_game_info_box_button_pressed(false), game_finished(false), + active_unit(-1, -1), attacking_unit(-1, -1), attacked_unit(-1, -1) {} -void GameController::update_unit_attacked(const sf::Time& time_past) { - if (unit_attacked) { - total_time_unit_attacked += time_past; - } - if (total_time_unit_attacked.asSeconds() > 1.5) { - total_time_unit_attacked = sf::Time(); - unit_attacked = false; - } +void GameController::update_unit_attacked(const sf::Time &time_past) { + if (unit_attacked) { + total_time_unit_attacked += time_past; + } + if (total_time_unit_attacked.asSeconds() > 1.5) { + total_time_unit_attacked = sf::Time(); + unit_attacked = false; + } } -void GameController::drag_red_player(sf::Event& event) { - const auto unit_selected = std::find_if(game_view.get_red_units_sprites().cbegin(), game_view.get_red_units_sprites().cend(), - [&event](const sf::Sprite& unit_sprite) { - return unit_sprite.getGlobalBounds().contains(event.mouseButton.x, event.mouseButton.y); - }); - if (unit_selected != game_view.get_red_units_sprites().cend()) { - dragging = true; - m_data.mouse_object_offset_x = event.mouseButton.x - unit_selected->getGlobalBounds().left; - m_data.mouse_object_offset_y = event.mouseButton.y - unit_selected->getGlobalBounds().top; - } - selected_unit_idx = std::distance(std::cbegin(game_view.get_red_units_sprites()), unit_selected); +void GameController::drag_red_player(sf::Event &event) { + const auto unit_selected = + std::find_if(game_view.get_red_units_sprites().cbegin(), + game_view.get_red_units_sprites().cend(), + [&event](const sf::Sprite &unit_sprite) { + return unit_sprite.getGlobalBounds().contains( + event.mouseButton.x, event.mouseButton.y); + }); + if (unit_selected != game_view.get_red_units_sprites().cend()) { + dragging = true; + m_data.mouse_object_offset_x = + event.mouseButton.x - unit_selected->getGlobalBounds().left; + m_data.mouse_object_offset_y = + event.mouseButton.y - unit_selected->getGlobalBounds().top; + } + selected_unit_idx = std::distance( + std::cbegin(game_view.get_red_units_sprites()), unit_selected); } -void GameController::drag_blue_player(sf::Event& event) { - const auto unit_selected = std::find_if(game_view.get_blue_units_sprites().cbegin(), game_view.get_blue_units_sprites().cend(), - [&event](const sf::Sprite& unit_sprite) { - return unit_sprite.getGlobalBounds().contains(event.mouseButton.x, event.mouseButton.y); - }); - if (unit_selected != game_view.get_blue_units_sprites().cend()) { - dragging = true; - m_data.mouse_object_offset_x = event.mouseButton.x - unit_selected->getGlobalBounds().left; - m_data.mouse_object_offset_y = event.mouseButton.y - unit_selected->getGlobalBounds().top; - } - selected_unit_idx = std::distance(std::cbegin(game_view.get_blue_units_sprites()), unit_selected); +void GameController::drag_blue_player(sf::Event &event) { + const auto unit_selected = + std::find_if(game_view.get_blue_units_sprites().cbegin(), + game_view.get_blue_units_sprites().cend(), + [&event](const sf::Sprite &unit_sprite) { + return unit_sprite.getGlobalBounds().contains( + event.mouseButton.x, event.mouseButton.y); + }); + if (unit_selected != game_view.get_blue_units_sprites().cend()) { + dragging = true; + m_data.mouse_object_offset_x = + event.mouseButton.x - unit_selected->getGlobalBounds().left; + m_data.mouse_object_offset_y = + event.mouseButton.y - unit_selected->getGlobalBounds().top; + } + selected_unit_idx = std::distance( + std::cbegin(game_view.get_blue_units_sprites()), unit_selected); } void GameController::change_player_turn() { - if (unit_moved_this_round && turn_approved) { - if (current_player_turn == TURN::PLAYER_A) { - current_player_turn = TURN::PLAYER_B; - current_player = &playerB; - other_player = &playerA; - } else { - current_player_turn = TURN::PLAYER_A; - current_player = &playerA; - other_player = &playerB; - } - unit_moved_this_round = false; - turn_approved = false; - is_active_unit = false; + if (unit_moved_this_round && turn_approved) { + if (current_player_turn == Turn::PlayerA) { + current_player_turn = Turn::PlayerB; + current_player = &playerB; + other_player = &playerA; + } else { + current_player_turn = Turn::PlayerA; + current_player = &playerA; + other_player = &playerB; } + unit_moved_this_round = false; + turn_approved = false; + is_active_unit = false; + } } -void GameController::change_init_turn(sf::Event& event) { - if (done_button_pressed) { - if (current_player_turn == TURN::PLAYER_A) { - if (playerA.get_board().get_state() == STATE::FULL) { - board_a_initialized = true; - current_player_turn = TURN::PLAYER_B; - current_player = &playerB; - other_player = &playerA; - playerB.update_board(playerA.get_board()); - } - } else { - if (playerB.get_board().get_state() == STATE::FULL) { - board_b_initialized = true; - current_player_turn = TURN::PLAYER_A; - current_player = &playerA; - other_player = &playerB; - playerA.update_board(playerB.get_board()); - } - } - is_active_unit = false; - done_button_pressed = false; +void GameController::change_init_turn(sf::Event &event) { + if (done_button_pressed) { + if (current_player_turn == Turn::PlayerA) { + if (playerA.get_board().get_state() == State::Full) { + board_a_initialized = true; + current_player_turn = Turn::PlayerB; + current_player = &playerB; + other_player = &playerA; + playerB.update_board(playerA.get_board()); + } + } else { + if (playerB.get_board().get_state() == State::Full) { + board_b_initialized = true; + current_player_turn = Turn::PlayerA; + current_player = &playerA; + other_player = &playerB; + playerA.update_board(playerB.get_board()); + } } + is_active_unit = false; + done_button_pressed = false; + } } -void GameController::set_unit(sf::Event& event) { - dragging = false; - Board::Tile tile(return_tile(event.mouseButton.x, event.mouseButton.y)); - if (current_player->get_units_count(selected_unit_idx) < current_player->get_board().get_max_unit_count(selected_unit_idx)) { - current_player->set_unit(tile.x, tile.y, selected_unit_idx); - } +void GameController::set_unit(sf::Event &event) { + dragging = false; + Tile tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + if (current_player->get_units_count(selected_unit_idx) < + current_player->get_board().get_max_unit_count(selected_unit_idx)) { + current_player->set_unit(tile.x, tile.y, selected_unit_idx); + } } -void GameController::set_active_unit(sf::Event& event) { - Board::Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); - if (!current_player->get_board().get_unit(chosen_tile)) { - return; - } - if (current_player->get_board().get_unit(chosen_tile)->get_owner() != current_player->get_player_number()) { - return; - } +void GameController::set_active_unit(sf::Event &event) { + Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + if (!current_player->get_board().get_unit(chosen_tile)) { + return; + } + if (std::visit(GetOwner{}, + current_player->get_board().get_unit(chosen_tile).value()) != + current_player->get_player_number()) { + return; + } - if (active_unit == chosen_tile && is_active_unit) { - active_unit.set_cords(-1, -1); - is_active_unit = false; - } else { - active_unit.set_cords(chosen_tile); - is_active_unit = true; - } + if (active_unit == chosen_tile && is_active_unit) { + active_unit.set_cords(-1, -1); + is_active_unit = false; + } else { + active_unit.set_cords(chosen_tile); + is_active_unit = true; + } } void GameController::remove_unit() { - if (is_active_unit && remove_button_pressed) { - current_player->remove_unit(active_unit.x, active_unit.y); - active_unit.set_cords(-1, -1); - is_active_unit = false; - remove_button_pressed = false; - } -} - -void GameController::resolve_unit_conflict(const Board::Tile& attacked_unit) { - switch (current_player->attack(active_unit, attacked_unit)) { - case RESULT::WON: - current_player->remove_unit(attacked_unit); - other_player->reverse_remove_unit(attacked_unit); - break; - case RESULT::DRAW: - current_player->remove_unit(active_unit); - current_player->remove_unit(attacked_unit); - other_player->reverse_remove_unit(active_unit); - other_player->reverse_remove_unit(attacked_unit); - active_unit.set_cords(-1, -1); - break; - case RESULT::LOST: - current_player->remove_unit(active_unit); - other_player->reverse_remove_unit(active_unit); - active_unit.set_cords(-1, -1); - break; - } + if (is_active_unit && remove_button_pressed) { + current_player->remove_unit(active_unit.x, active_unit.y); + active_unit.set_cords(-1, -1); is_active_unit = false; + remove_button_pressed = false; + } } -void GameController::move_active_unit(sf::Event& event) { - Board::Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); - if (!is_active_unit) { - return; - } - if (unit_moved_this_round) { - return; - } - if (!current_player->can_move(active_unit, chosen_tile)) { - return; - } - if (current_player->get_tile_info(chosen_tile) == "enemy") { - if (current_player->get_board().get_unit(chosen_tile)->get_type() == "flag") { - game_finished = true; - victorious_player_name = current_player->get_player_name(); - } - attacker = current_player->get_board().get_unit(active_unit); - attacked = current_player->get_board().get_unit(chosen_tile); - resolve_unit_conflict(chosen_tile); - unit_attacked = true; - unit_moved_this_round = true; +void GameController::resolve_unit_conflict(const Tile &attacked_unit) { + switch (current_player->attack(active_unit, attacked_unit)) { + case attack::Result::Won: + current_player->remove_unit(attacked_unit); + other_player->reverse_remove_unit(attacked_unit); + break; + case attack::Result::Draw: + current_player->remove_unit(active_unit); + current_player->remove_unit(attacked_unit); + other_player->reverse_remove_unit(active_unit); + other_player->reverse_remove_unit(attacked_unit); + active_unit.set_cords(-1, -1); + break; + case attack::Result::Lost: + current_player->remove_unit(active_unit); + other_player->reverse_remove_unit(active_unit); + active_unit.set_cords(-1, -1); + break; + } + is_active_unit = false; +} +void GameController::move_active_unit(sf::Event &event) { + Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + if (!is_active_unit) { + return; + } + if (unit_moved_this_round) { + return; + } + if (!current_player->can_move(active_unit, chosen_tile)) { + return; + } + if (current_player->get_tile_info(chosen_tile) == "enemy") { + if (std::holds_alternative( + current_player->get_board().get_unit(chosen_tile).value())) { + game_finished = true; + victorious_player_name = current_player->get_player_name(); } - if (current_player->move_unit(active_unit, chosen_tile)) { - other_player->reverse_move_unit(active_unit, chosen_tile); - active_unit.set_cords(-1, -1); - unit_moved_this_round = true; - is_active_unit = false; - } + attacker = current_player->get_board().get_unit(active_unit); + attacked = current_player->get_board().get_unit(chosen_tile); + resolve_unit_conflict(chosen_tile); + unit_attacked = true; + unit_moved_this_round = true; + } + if (current_player->move_unit(active_unit, chosen_tile)) { + other_player->reverse_move_unit(active_unit, chosen_tile); + active_unit.set_cords(-1, -1); + unit_moved_this_round = true; + is_active_unit = false; + } } void GameController::randomize_units() { - if (!randomize_button_pressed) { - return; + if (!randomize_button_pressed) { + return; + } + for (int row = 8; row < current_player->get_board().get_height(); ++row) { + for (int col = 0; col < current_player->get_board().get_width(); ++col) { + current_player->remove_unit(col, row); } + } + while (current_player->get_board().get_state() != State::Full) { for (int row = 8; row < current_player->get_board().get_height(); ++row) { - for (int col = 0; col < current_player->get_board().get_width(); ++col) { - current_player->remove_unit(col, row); - } - } - while (current_player->get_board().get_state() != STATE::FULL) { - for (int row = 8; row < current_player->get_board().get_height(); ++row) { - for (int col = 0; col < current_player->get_board().get_width(); ++col) { - int idx = rand() % 12; - if (current_player->get_units_count(idx) < current_player->get_board().get_max_unit_count(idx)) - current_player->set_unit(col, row, idx); - } - } + for (int col = 0; col < current_player->get_board().get_width(); ++col) { + int idx = rand() % 12; + if (current_player->get_units_count(idx) < + current_player->get_board().get_max_unit_count(idx)) + current_player->set_unit(col, row, idx); + } } - randomize_button_pressed = false; + } + randomize_button_pressed = false; } void GameController::set_buttons_pressed() { - if (game_view.get_end_turn_button().is_highlighted() && unit_moved_this_round) { - end_turn_button_pressed = true; + if (game_view.get_end_turn_button().is_highlighted() && + unit_moved_this_round) { + end_turn_button_pressed = true; + } + if (game_view.get_info_box().button_is_highlighted() && + end_turn_button_pressed) { + turn_approved = true; + end_turn_button_pressed = false; + } + if (!(board_a_initialized && board_b_initialized)) { + if (game_view.get_done_button().is_highlighted()) { + done_button_pressed = true; } - if (game_view.get_info_box().button_is_highlighted() && end_turn_button_pressed) { - turn_approved = true; - end_turn_button_pressed = false; - } - if (!(board_a_initialized && board_b_initialized)) { - if (game_view.get_done_button().is_highlighted()) { - done_button_pressed = true; - } - if (game_view.get_randomize_button().is_highlighted()) { - randomize_button_pressed = true; - } - if (game_view.get_remove_button().is_highlighted()) { - remove_button_pressed = true; - } + if (game_view.get_randomize_button().is_highlighted()) { + randomize_button_pressed = true; } - if (game_finished && game_view.get_end_game_info_box().button_is_highlighted()) { - end_game_info_box_button_pressed = true; + if (game_view.get_remove_button().is_highlighted()) { + remove_button_pressed = true; } + } + if (game_finished && + game_view.get_end_game_info_box().button_is_highlighted()) { + end_game_info_box_button_pressed = true; + } } -void GameController::handle_events(sf::Event& event) { - if (event.type == sf::Event::MouseButtonPressed) { - set_buttons_pressed(); - if (!(board_a_initialized && board_b_initialized)) { - if (current_player_turn == TURN::PLAYER_A) { - drag_red_player(event); - } else { - drag_blue_player(event); - } - remove_unit(); - randomize_units(); - change_init_turn(event); - } - if (!is_out_of_the_board(event.mouseButton.x, event.mouseButton.y)) { - set_active_unit(event); - } - if (board_a_initialized && board_b_initialized) { - change_player_turn(); - move_active_unit(event); - } +void GameController::handle_events(sf::Event &event) { + if (event.type == sf::Event::MouseButtonPressed) { + set_buttons_pressed(); + if (!(board_a_initialized && board_b_initialized)) { + if (current_player_turn == Turn::PlayerA) { + drag_red_player(event); + } else { + drag_blue_player(event); + } + remove_unit(); + randomize_units(); + change_init_turn(event); } - if (event.type == sf::Event::MouseButtonReleased) { - if (!(board_a_initialized && board_b_initialized)) { - set_unit(event); - } + if (!is_out_of_the_board(event.mouseButton.x, event.mouseButton.y)) { + set_active_unit(event); } - if (event.type == sf::Event::MouseMoved) { - m_data.mouse_x = event.mouseMove.x; - m_data.mouse_y = event.mouseMove.y; - game_view.set_button_highlights(m_data.mouse_x, m_data.mouse_y); + if (board_a_initialized && board_b_initialized) { + change_player_turn(); + move_active_unit(event); } + } + if (event.type == sf::Event::MouseButtonReleased) { + if (!(board_a_initialized && board_b_initialized)) { + set_unit(event); + } + } + if (event.type == sf::Event::MouseMoved) { + m_data.mouse_x = event.mouseMove.x; + m_data.mouse_y = event.mouseMove.y; + game_view.set_button_highlights(m_data.mouse_x, m_data.mouse_y); + } } sf::Vector2f GameController::return_pixels(int col, int row) const { - if (col < 0 && row < 0) { - return sf::Vector2f{-1, -1}; - } - return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); + if (col < 0 && row < 0) { + return sf::Vector2f{-1, -1}; + } + return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); } -Board::Tile GameController::return_tile(const sf::Vector2f& coords) const { - return Board::Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); +Tile GameController::return_tile(const sf::Vector2f &coords) const { + return Tile((coords.x - TILE_SIZE) / TILE_SIZE, + (coords.y - TILE_SIZE) / TILE_SIZE); } -Board::Tile GameController::return_tile(int x, int y) const { - if (x < 0 && y < 0) { - return Board::Tile{-1, -1}; - } - return return_tile(sf::Vector2f(x, y)); +Tile GameController::return_tile(int x, int y) const { + if (x < 0 && y < 0) { + return Tile{-1, -1}; + } + return return_tile(sf::Vector2f(x, y)); } bool GameController::is_out_of_the_board(int x, int y) { - if (current_player->get_tile_info(return_tile(x, y)) == "#") { - return true; - } - return false; + if (current_player->get_tile_info(return_tile(x, y)) == "#") { + return true; + } + return false; } bool GameController::both_boards_set() const { - if (board_a_initialized && board_b_initialized) { - return true; - } - return false; + if (board_a_initialized && board_b_initialized) { + return true; + } + return false; }; diff --git a/src/GameView.cpp b/src/GameView.cpp index 585f080..91bec4e 100644 --- a/src/GameView.cpp +++ b/src/GameView.cpp @@ -4,503 +4,544 @@ #include "Player.hpp" -GameView::GameView(Player& pA, Player& pB) - : playerA(pA), - playerB(pB), - current_player(&playerA), - other_player(&playerB), - current_player_turn(TURN::PLAYER_A), +GameView::GameView(Player &pA, Player &pB) + : playerA(pA), playerB(pB), current_player(&playerA), + other_player(&playerB), current_player_turn(Turn::PlayerA), board_textures_path("images/board/"), - pieces_textures_path("images/pieces/"), - TILE_SIZE(64), + pieces_textures_path("images/pieces/"), TILE_SIZE(64), X_ADDITIONAL_SPACE(512), window_size(12 * TILE_SIZE + X_ADDITIONAL_SPACE, 14 * TILE_SIZE), - sprite_initial_position(-1, -1), - clock_started(false), - done_button("Done"), - randomize_button("Randomize"), - remove_button("Remove"), - end_turn_button("End Turn"), + sprite_initial_position(-1, -1), clock_started(false), + done_button("Done"), randomize_button("Randomize"), + remove_button("Remove"), end_turn_button("End Turn"), info_box("End of Turn"), - attack_info_box(red_units_sprites, blue_units_sprites, yellow_highlight_sprite), + attack_info_box(red_units_sprites, blue_units_sprites, + yellow_highlight_sprite), end_game_info_box("None") { - load_obstacle_textures(); - load_grass_textures(); - load_board_border_texture(); - load_red_units_textures(); - load_blue_units_textures(); - load_highlight_textures(); + load_obstacle_textures(); + load_grass_textures(); + load_board_border_texture(); + load_red_units_textures(); + load_blue_units_textures(); + load_highlight_textures(); - set_obstacle_sprites(); - set_red_units_sprites(); - set_blue_units_sprites(); - set_highlight_sprites(); + set_obstacle_sprites(); + set_red_units_sprites(); + set_blue_units_sprites(); + set_highlight_sprites(); - load_font(); - text.setFont(font); + load_font(); + text.setFont(font); - board_border.setTexture(board_border_texture); - grass_light.setTexture(grass_light_texture); - grass_dark.setTexture(grass_dark_texture); + board_border.setTexture(board_border_texture); + grass_light.setTexture(grass_light_texture); + grass_dark.setTexture(grass_dark_texture); } void GameView::set_obstacle_sprites() { - for (size_t i = 0; i < obstacle_sprites.size(); i++) { - obstacle_sprites[i].setTexture(obstacle_textures[i]); - } + for (size_t i = 0; i < obstacle_sprites.size(); i++) { + obstacle_sprites[i].setTexture(obstacle_textures[i]); + } } void GameView::load_board_border_texture() { - if (!board_border_texture.loadFromFile("images/board/border_scaled.png")) { - std::cerr << "board border error loading from file!\n"; - abort(); - } + if (!board_border_texture.loadFromFile("images/board/border_scaled.png")) { + std::cerr << "board border error loading from file!\n"; + abort(); + } } void GameView::load_grass_textures() { - if (!grass_light_texture.loadFromFile("images/board/grass1_scaled.png")) { - std::cerr << "grass light error loading from file!\n"; - abort(); - } - if (!grass_dark_texture.loadFromFile("images/board/grass2_scaled.png")) { - std::cerr << "grass dark error loading from file!\n"; - abort(); - } + if (!grass_light_texture.loadFromFile("images/board/grass1_scaled.png")) { + std::cerr << "grass light error loading from file!\n"; + abort(); + } + if (!grass_dark_texture.loadFromFile("images/board/grass2_scaled.png")) { + std::cerr << "grass dark error loading from file!\n"; + abort(); + } } void GameView::load_obstacle_textures() { - for (size_t i = 0; i < obstacle_textures.size(); ++i) { - if (i <= 3) { - if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake1_" + std::to_string(i + 1) + ".png")) { - std::cerr << "obstacle texture lake1_" + std::to_string(i + 1) + "failed to load!\n"; - abort(); - } - } else { - if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake2_" + std::to_string(i - 3) + ".png")) { - std::cerr << "obstacle texture lake2_" + std::to_string(i + 1) + "failed to load!\n"; - abort(); - } - } + for (size_t i = 0; i < obstacle_textures.size(); ++i) { + if (i <= 3) { + if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake1_" + + std::to_string(i + 1) + ".png")) { + std::cerr << "obstacle texture lake1_" + std::to_string(i + 1) + + "failed to load!\n"; + abort(); + } + } else { + if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake2_" + + std::to_string(i - 3) + ".png")) { + std::cerr << "obstacle texture lake2_" + std::to_string(i + 1) + + "failed to load!\n"; + abort(); + } } + } } void GameView::load_font() { - if (!font.loadFromFile("font/chandas1-2.ttf")) { - std::cerr << "font loading failed!\n"; - abort(); - } + if (!font.loadFromFile("font/chandas1-2.ttf")) { + std::cerr << "font loading failed!\n"; + abort(); + } } void GameView::load_highlight_textures() { - if (!red_highlight_texture.loadFromFile(board_textures_path + "highlight_red.png")) { - std::cerr << "red highlight texture failed!\n"; - abort(); - } - if (!yellow_highlight_texture.loadFromFile(board_textures_path + "highlight_yellow.png")) { - std::cerr << "yellow highlight texture failed!\n"; - abort(); - } - if (!green_highlight_texture.loadFromFile(board_textures_path + "highlight_green.png")) { - std::cerr << "green highlight texture failed!\n"; - abort(); - } + if (!red_highlight_texture.loadFromFile(board_textures_path + + "highlight_red.png")) { + std::cerr << "red highlight texture failed!\n"; + abort(); + } + if (!yellow_highlight_texture.loadFromFile(board_textures_path + + "highlight_yellow.png")) { + std::cerr << "yellow highlight texture failed!\n"; + abort(); + } + if (!green_highlight_texture.loadFromFile(board_textures_path + + "highlight_green.png")) { + std::cerr << "green highlight texture failed!\n"; + abort(); + } } void GameView::set_highlight_sprites() { - yellow_highlight_sprite.setTexture(yellow_highlight_texture); - green_highlight_sprite.setTexture(green_highlight_texture); - red_highlight_sprite.setTexture(red_highlight_texture); + yellow_highlight_sprite.setTexture(yellow_highlight_texture); + green_highlight_sprite.setTexture(green_highlight_texture); + red_highlight_sprite.setTexture(red_highlight_texture); } void GameView::load_blue_units_textures() { - for (size_t i = 0; i < 9; ++i) { - if (!blue_unit_textures[i].loadFromFile("images/pieces/blue/blue_" + std::to_string(i + 2) + ".png")) { - std::cerr << "blue unit" + std::to_string(i + 2) + "failed to load a texture!\n"; - abort(); - } - } - if (!blue_unit_textures[9].loadFromFile("images/pieces/blue/blue_bomb.png")) { - std::cerr << "blue bomb loading texture failed! \n"; - abort(); - } - if (!blue_unit_textures[10].loadFromFile("images/pieces/blue/blue_flag.png")) { - std::cerr << "blue flag loading texture failed! \n"; - abort(); - } - if (!blue_unit_textures[11].loadFromFile("images/pieces/blue/blue_spy.png")) { - std::cerr << "blue spy loading texture failed! \n"; - abort(); - } - if (!blue_back_texture.loadFromFile("images/pieces/blue/blue_back.png")) { - std::cerr << "blue back loading texture failed! \n"; - abort(); - } + for (size_t i = 0; i < 9; ++i) { + if (!blue_unit_textures[i].loadFromFile("images/pieces/blue/blue_" + + std::to_string(i + 2) + ".png")) { + std::cerr << "blue unit" + std::to_string(i + 2) + + "failed to load a texture!\n"; + abort(); + } + } + if (!blue_unit_textures[9].loadFromFile("images/pieces/blue/blue_bomb.png")) { + std::cerr << "blue bomb loading texture failed! \n"; + abort(); + } + if (!blue_unit_textures[10].loadFromFile( + "images/pieces/blue/blue_flag.png")) { + std::cerr << "blue flag loading texture failed! \n"; + abort(); + } + if (!blue_unit_textures[11].loadFromFile("images/pieces/blue/blue_spy.png")) { + std::cerr << "blue spy loading texture failed! \n"; + abort(); + } + if (!blue_back_texture.loadFromFile("images/pieces/blue/blue_back.png")) { + std::cerr << "blue back loading texture failed! \n"; + abort(); + } } void GameView::set_blue_units_sprites() { - for (size_t i = 0; i < blue_units_sprites.size(); ++i) { - blue_units_sprites[i].setTexture(blue_unit_textures[i]); - } - blue_back_sprite.setTexture(blue_back_texture); + for (size_t i = 0; i < blue_units_sprites.size(); ++i) { + blue_units_sprites[i].setTexture(blue_unit_textures[i]); + } + blue_back_sprite.setTexture(blue_back_texture); } void GameView::load_red_units_textures() { - for (size_t i = 0; i < 9; ++i) { - if (!red_unit_textures[i].loadFromFile("images/pieces/red/red_" + std::to_string(i + 2) + ".png")) { - std::cerr << "red unit" + std::to_string(i + 2) + " failed to load a texture!\n"; - abort(); - } - } - if (!red_unit_textures[9].loadFromFile("images/pieces/red/red_bomb.png")) { - std::cerr << "red bomb loading texture failed! \n"; - abort(); - } - if (!red_unit_textures[10].loadFromFile("images/pieces/red/red_flag.png")) { - std::cerr << "red flag loading texture failed! \n"; - abort(); - } - if (!red_unit_textures[11].loadFromFile("images/pieces/red/red_spy.png")) { - std::cerr << "red spy loading texture failed! \n"; - abort(); - } - if (!red_back_texture.loadFromFile("images/pieces/red/red_back.png")) { - std::cerr << "red back loading texture failed! \n"; - abort(); - } + for (size_t i = 0; i < 9; ++i) { + if (!red_unit_textures[i].loadFromFile("images/pieces/red/red_" + + std::to_string(i + 2) + ".png")) { + std::cerr << "red unit" + std::to_string(i + 2) + + " failed to load a texture!\n"; + abort(); + } + } + if (!red_unit_textures[9].loadFromFile("images/pieces/red/red_bomb.png")) { + std::cerr << "red bomb loading texture failed! \n"; + abort(); + } + if (!red_unit_textures[10].loadFromFile("images/pieces/red/red_flag.png")) { + std::cerr << "red flag loading texture failed! \n"; + abort(); + } + if (!red_unit_textures[11].loadFromFile("images/pieces/red/red_spy.png")) { + std::cerr << "red spy loading texture failed! \n"; + abort(); + } + if (!red_back_texture.loadFromFile("images/pieces/red/red_back.png")) { + std::cerr << "red back loading texture failed! \n"; + abort(); + } } void GameView::set_red_units_sprites() { - for (size_t i = 0; i < red_units_sprites.size(); ++i) { - red_units_sprites[i].setTexture(red_unit_textures[i]); - } - red_back_sprite.setTexture(red_back_texture); -} - -void GameView::update_players(Player* current, Player* other) { - current_player = current; - other_player = other; - current_player_turn = current_player->get_player_number(); -} - -void GameView::draw_grass(sf::RenderWindow& win) { - for (int row = 0; row < playerA.get_board().get_height(); ++row) { - int tile_y_pos = (row + 1) * TILE_SIZE; - for (int col = 0; col < playerA.get_board().get_width(); ++col) { - int tile_x_pos = (col + 1) * TILE_SIZE; - grass_light.setPosition(tile_x_pos, tile_y_pos); - grass_dark.setPosition(tile_x_pos, tile_y_pos); - if (col % 2) { - if (row % 2) { - win.draw(grass_light); - } else { - win.draw(grass_dark); - } - - } else { - if (row % 2) { - win.draw(grass_dark); - } else { - win.draw(grass_light); - } - } - } - } -} - -void GameView::draw_obstacles(sf::RenderWindow& win) { - int i = 0; - int j = 4; - for (size_t row = 5; row < 7; ++row) { - int obstacle_y_pos = TILE_SIZE * (row + 1); - for (size_t col = 2; col < 4; ++col) { - size_t obstacle_x_pos = TILE_SIZE * (col + 1); - obstacle_sprites[i].setPosition(obstacle_x_pos, obstacle_y_pos); - win.draw(obstacle_sprites[i]); - i++; - } - for (size_t col = 6; col < 8; ++col) { - size_t obstacle_x_pos = TILE_SIZE * (col + 1); - obstacle_sprites[j].setPosition(obstacle_x_pos, obstacle_y_pos); - win.draw(obstacle_sprites[j]); - j++; - } - } -} - -void GameView::draw_units_for_init(sf::RenderWindow& win, bool is_dragging, int selected_units_idx, const mouse_data& m_data) { - if (current_player_turn == TURN::PLAYER_A) { - draw_red_init_units(win, is_dragging, selected_units_idx, m_data); - } else { - draw_blue_init_units(win, is_dragging, selected_units_idx, m_data); - } - -} - -void GameView::draw_red_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data) { - const int x_denting = board_border.getGlobalBounds().width; - const int y_denting = TILE_SIZE; - int col_count = 0; - int row_count = 0; - for (size_t i = 0; i < red_units_sprites.size(); ++i) { - if (i != 0 && i % 4 == 0) { - col_count = 0; - row_count++; - } - red_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, y_denting + row_count * TILE_SIZE); - text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); - text.setString("x" + std::to_string(playerA.get_board().get_max_unit_count(i) - playerA.get_units_count(i))); - if (is_dragging == true) { - red_units_sprites[selected_unit_idx].setPosition(m_data.mouse_x - m_data.mouse_object_offset_x, m_data.mouse_y - m_data.mouse_object_offset_y); - } - win.draw(red_units_sprites[i]); - win.draw(text); - col_count++; - } -} - -void GameView::draw_blue_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data) { - const int x_denting = board_border.getGlobalBounds().width; - const int y_denting = TILE_SIZE; - int col_count = 0; - int row_count = 0; - for (size_t i = 0; i < blue_units_sprites.size(); ++i) { - if (i != 0 && i % 4 == 0) { - col_count = 0; - row_count++; - } - blue_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, y_denting + row_count * TILE_SIZE); - text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); - text.setString("x" + std::to_string(playerB.get_board().get_max_unit_count(i) - playerB.get_units_count(i))); - if (is_dragging == true) { - blue_units_sprites[selected_unit_idx].setPosition(m_data.mouse_x - m_data.mouse_object_offset_x, m_data.mouse_y - m_data.mouse_object_offset_y); - } - win.draw(blue_units_sprites[i]); - win.draw(text); - col_count++; - } -} - -void GameView::draw_done_button(sf::RenderWindow& win) { - const int x_denting = board_border.getGlobalBounds().width; - done_button.set_position(x_denting + (X_ADDITIONAL_SPACE - done_button.get_width()) / 2, TILE_SIZE * 6); - done_button.draw(win); -} -void GameView::draw_randomize_button(sf::RenderWindow& win) { - randomize_button.set_position(done_button.get_position().x, done_button.get_position().y + done_button.get_height() + TILE_SIZE); - randomize_button.draw(win); -} - -void GameView::draw_remove_button(sf::RenderWindow& win) { - remove_button.set_position(randomize_button.get_position().x, randomize_button.get_position().y + randomize_button.get_height() + TILE_SIZE); - remove_button.draw(win); -} - -void GameView::draw_end_turn_button(sf::RenderWindow& win) { - end_turn_button.set_position(done_button.get_position()); - end_turn_button.draw(win); -} - -void GameView::draw_info_box(sf::RenderWindow& win) { - info_box.set_text(other_player->get_player_name() + "'s turn!"); - info_box.set_position((win.getSize().x - info_box.get_width()) / 2, (win.getSize().y - info_box.get_height()) / 2); - info_box.draw(win); -} - -void GameView::draw_attack_info_box(sf::RenderWindow& win, const std::shared_ptr& attacker, const std::shared_ptr& attacked) { - if (!clock_started) { - clock.restart(); - clock_started = true; - } - sf::Time time_past = clock.getElapsedTime(); - attack_info_box.set_position((window_size.x - attack_info_box.get_width()) / 2, (window_size.y - attack_info_box.get_height()) / 2); - attack_info_box.set_attacking_unit(attacker); - attack_info_box.set_attacked_unit(attacked); - attack_info_box.draw(win); - if (time_past.asSeconds() > 1.5) { - clock_started = false; - } -} - -void GameView::draw_units(sf::RenderWindow& win) { - int object_x_pos = -1; - int object_y_pos = -1; - int unit_idx = -1; - for (int row = 0; row < current_player->get_board().get_height(); ++row) { - object_y_pos = (row + 1) * TILE_SIZE; - for (int col = 0; col < current_player->get_board().get_width(); ++col) { - object_x_pos = (col + 1) * TILE_SIZE; - if (current_player->get_tile_info(col, row) == "regular") { - unit_idx = current_player->get_board().get_unit(col, row)->get_value() - 2; - draw_sprite(win, unit_idx, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "scout") { - draw_sprite(win, 0, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "miner") { - draw_sprite(win, 1, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "bomb") { - draw_sprite(win, 9, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "flag") { - draw_sprite(win, 10, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "spy") { - draw_sprite(win, 11, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "enemy") { - draw_sprite(win, 12, object_x_pos, object_y_pos); - } - } - } -} - -void GameView::draw_unit_highlight(sf::RenderWindow& win, const Board::Tile& active_unit) { - yellow_highlight_sprite.setPosition(return_pixels(active_unit.x, active_unit.y)); - win.draw(yellow_highlight_sprite); -} - -void GameView::draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int sprite_pos_y) { - if (idx == 12) { - if (current_player_turn == TURN::PLAYER_A) { - blue_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); - win.draw(blue_back_sprite); + for (size_t i = 0; i < red_units_sprites.size(); ++i) { + red_units_sprites[i].setTexture(red_unit_textures[i]); + } + red_back_sprite.setTexture(red_back_texture); +} + +void GameView::update_players(Player *current, Player *other) { + current_player = current; + other_player = other; + current_player_turn = current_player->get_player_number(); +} + +void GameView::draw_grass(sf::RenderWindow &win) { + for (int row = 0; row < playerA.get_board().get_height(); ++row) { + int tile_y_pos = (row + 1) * TILE_SIZE; + for (int col = 0; col < playerA.get_board().get_width(); ++col) { + int tile_x_pos = (col + 1) * TILE_SIZE; + grass_light.setPosition(tile_x_pos, tile_y_pos); + grass_dark.setPosition(tile_x_pos, tile_y_pos); + if (col % 2) { + if (row % 2) { + win.draw(grass_light); } else { - red_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); - win.draw(red_back_sprite); + win.draw(grass_dark); } - } else { - if (current_player_turn == TURN::PLAYER_A) { - sprite_initial_position = red_units_sprites[idx].getPosition(); - red_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); - win.draw(red_units_sprites[idx]); - red_units_sprites[idx].setPosition(sprite_initial_position); + } else { + if (row % 2) { + win.draw(grass_dark); } else { - sprite_initial_position = blue_units_sprites[idx].getPosition(); - blue_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); - win.draw(blue_units_sprites[idx]); - blue_units_sprites[idx].setPosition(sprite_initial_position); + win.draw(grass_light); } - } -} - -void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Board::Tile& active_unit) { - if (!current_player->get_board().get_unit(active_unit.x, active_unit.y)) { - return; - } - if (current_player->get_board().get_unit(active_unit.x, active_unit.y)->get_type() == "scout") { - highlight_scout_moves(win, active_unit); + } + } + } +} + +void GameView::draw_obstacles(sf::RenderWindow &win) { + int i = 0; + int j = 4; + for (size_t row = 5; row < 7; ++row) { + int obstacle_y_pos = TILE_SIZE * (row + 1); + for (size_t col = 2; col < 4; ++col) { + size_t obstacle_x_pos = TILE_SIZE * (col + 1); + obstacle_sprites[i].setPosition(obstacle_x_pos, obstacle_y_pos); + win.draw(obstacle_sprites[i]); + i++; + } + for (size_t col = 6; col < 8; ++col) { + size_t obstacle_x_pos = TILE_SIZE * (col + 1); + obstacle_sprites[j].setPosition(obstacle_x_pos, obstacle_y_pos); + win.draw(obstacle_sprites[j]); + j++; + } + } +} + +void GameView::draw_units_for_init(sf::RenderWindow &win, bool is_dragging, + int selected_units_idx, + const mouse_data &m_data) { + if (current_player_turn == Turn::PlayerA) { + draw_red_init_units(win, is_dragging, selected_units_idx, m_data); + } else { + draw_blue_init_units(win, is_dragging, selected_units_idx, m_data); + } +} + +void GameView::draw_red_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, + const mouse_data &m_data) { + const int x_denting = board_border.getGlobalBounds().width; + const int y_denting = TILE_SIZE; + int col_count = 0; + int row_count = 0; + for (size_t i = 0; i < red_units_sprites.size(); ++i) { + if (i != 0 && i % 4 == 0) { + col_count = 0; + row_count++; + } + red_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, + y_denting + row_count * TILE_SIZE); + text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, + y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); + text.setString("x" + + std::to_string(playerA.get_board().get_max_unit_count(i) - + playerA.get_units_count(i))); + if (is_dragging == true) { + red_units_sprites[selected_unit_idx].setPosition( + m_data.mouse_x - m_data.mouse_object_offset_x, + m_data.mouse_y - m_data.mouse_object_offset_y); + } + win.draw(red_units_sprites[i]); + win.draw(text); + col_count++; + } +} + +void GameView::draw_blue_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, + const mouse_data &m_data) { + const int x_denting = board_border.getGlobalBounds().width; + const int y_denting = TILE_SIZE; + int col_count = 0; + int row_count = 0; + for (size_t i = 0; i < blue_units_sprites.size(); ++i) { + if (i != 0 && i % 4 == 0) { + col_count = 0; + row_count++; + } + blue_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, + y_denting + row_count * TILE_SIZE); + text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, + y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); + text.setString("x" + + std::to_string(playerB.get_board().get_max_unit_count(i) - + playerB.get_units_count(i))); + if (is_dragging == true) { + blue_units_sprites[selected_unit_idx].setPosition( + m_data.mouse_x - m_data.mouse_object_offset_x, + m_data.mouse_y - m_data.mouse_object_offset_y); + } + win.draw(blue_units_sprites[i]); + win.draw(text); + col_count++; + } +} + +void GameView::draw_done_button(sf::RenderWindow &win) { + const int x_denting = board_border.getGlobalBounds().width; + done_button.set_position( + x_denting + (X_ADDITIONAL_SPACE - done_button.get_width()) / 2, + TILE_SIZE * 6); + done_button.draw(win); +} +void GameView::draw_randomize_button(sf::RenderWindow &win) { + randomize_button.set_position(done_button.get_position().x, + done_button.get_position().y + + done_button.get_height() + TILE_SIZE); + randomize_button.draw(win); +} + +void GameView::draw_remove_button(sf::RenderWindow &win) { + remove_button.set_position(randomize_button.get_position().x, + randomize_button.get_position().y + + randomize_button.get_height() + TILE_SIZE); + remove_button.draw(win); +} + +void GameView::draw_end_turn_button(sf::RenderWindow &win) { + end_turn_button.set_position(done_button.get_position()); + end_turn_button.draw(win); +} + +void GameView::draw_info_box(sf::RenderWindow &win) { + info_box.set_text(other_player->get_player_name() + "'s turn!"); + info_box.set_position((win.getSize().x - info_box.get_width()) / 2, + (win.getSize().y - info_box.get_height()) / 2); + info_box.draw(win); +} + +void GameView::draw_attack_info_box(sf::RenderWindow &win, + const std::optional &attacker, + const std::optional &attacked) { + if (!clock_started) { + clock.restart(); + clock_started = true; + } + sf::Time time_past = clock.getElapsedTime(); + attack_info_box.set_position( + (window_size.x - attack_info_box.get_width()) / 2, + (window_size.y - attack_info_box.get_height()) / 2); + attack_info_box.set_attacking_unit(attacker); + attack_info_box.set_attacked_unit(attacked); + attack_info_box.draw(win); + if (time_past.asSeconds() > 1.5) { + clock_started = false; + } +} + +void GameView::draw_units(sf::RenderWindow &win) { + for (int row = 0; row < current_player->get_board().get_height(); ++row) { + const int object_y_pos = (row + 1) * TILE_SIZE; + for (int col = 0; col < current_player->get_board().get_width(); ++col) { + const int object_x_pos = (col + 1) * TILE_SIZE; + const auto &unit = current_player->get_board().get_unit(col, row); + int unit_idx = std::visit( + overloads{ + [](const RegularUnit &runit) { return runit.get_value() - 2; }, + [](const ScoutUnit &) { return 0; }, + [](const MinerUnit &) { return 1; }, + [](const BombUnit &) { return 9; }, + [](const FlagUnit &) { return 10; }, + [](const SpyUnit &) { return 11; }, + }, + unit.value()); + if (current_player->get_tile_info(col, row) == "enemy") { + unit_idx = 12; + } + draw_sprite(win, unit_idx, object_x_pos, object_y_pos); + } + } +} + +void GameView::draw_unit_highlight(sf::RenderWindow &win, + const Tile &active_unit) { + yellow_highlight_sprite.setPosition( + return_pixels(active_unit.x, active_unit.y)); + win.draw(yellow_highlight_sprite); +} + +void GameView::draw_sprite(sf::RenderWindow &win, int idx, int sprite_pos_x, + int sprite_pos_y) { + if (idx == 12) { + if (current_player_turn == Turn::PlayerA) { + blue_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); + win.draw(blue_back_sprite); } else { - highlight_regular_moves(win, active_unit); - } -} - -void GameView::highlight_regular_moves(sf::RenderWindow& win, const Board::Tile& active_unit) { - highlight_tile(win, active_unit, active_unit.x - 1, active_unit.y); - highlight_tile(win, active_unit, active_unit.x + 1, active_unit.y); - highlight_tile(win, active_unit, active_unit.x, active_unit.y + 1); - highlight_tile(win, active_unit, active_unit.x, active_unit.y - 1); -} - -void GameView::highlight_scout_moves(sf::RenderWindow& win, const Board::Tile& active_unit) { - for (int col = active_unit.x + 1; col < current_player->get_board().get_width(); ++col) { - if (!highlight_tile(win, active_unit, col, active_unit.y)) { - break; - } - } - for (int col = active_unit.x - 1; col >= 0; --col) { - if (!highlight_tile(win, active_unit, col, active_unit.y)) { - break; - } - } - for (int row = active_unit.y + 1; row < current_player->get_board().get_height(); ++row) { - if (!highlight_tile(win, active_unit, active_unit.x, row)) { - break; - } - } - for (int row = active_unit.y - 1; row >= 0; --row) { - if (!highlight_tile(win, active_unit, active_unit.x, row)) { - break; - } - } -} - -bool GameView::highlight_tile(sf::RenderWindow& win, const Board::Tile& active_unit, int to_x, int to_y) { - if (check_if_viable(active_unit, to_x, to_y)) { - if (current_player->get_tile_info(to_x, to_y) == "enemy") { - red_highlight_sprite.setPosition(return_pixels(to_x, to_y)); - win.draw(red_highlight_sprite); - return false; - } else { - green_highlight_sprite.setPosition(return_pixels(to_x, to_y)); - win.draw(green_highlight_sprite); - } - return true; + red_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); + win.draw(red_back_sprite); + } + } else { + if (current_player_turn == Turn::PlayerA) { + sprite_initial_position = red_units_sprites[idx].getPosition(); + red_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); + win.draw(red_units_sprites[idx]); + red_units_sprites[idx].setPosition(sprite_initial_position); + } else { + sprite_initial_position = blue_units_sprites[idx].getPosition(); + blue_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); + win.draw(blue_units_sprites[idx]); + blue_units_sprites[idx].setPosition(sprite_initial_position); + } + } +} + +void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow &win, + const Tile &active_unit) { + const auto &unit = + current_player->get_board().get_unit(active_unit.x, active_unit.y); + if (!unit) { + return; + } + std::visit(overloads{ + [this, &win, &active_unit](const ScoutUnit &) { + highlight_scout_moves(win, active_unit); + }, + [this, &win, &active_unit](const auto &) { + highlight_regular_moves(win, active_unit); + }, + }, + unit.value()); +} + +void GameView::highlight_regular_moves(sf::RenderWindow &win, + const Tile &active_unit) { + highlight_tile(win, active_unit, active_unit.x - 1, active_unit.y); + highlight_tile(win, active_unit, active_unit.x + 1, active_unit.y); + highlight_tile(win, active_unit, active_unit.x, active_unit.y + 1); + highlight_tile(win, active_unit, active_unit.x, active_unit.y - 1); +} + +void GameView::highlight_scout_moves(sf::RenderWindow &win, + const Tile &active_unit) { + for (int col = active_unit.x + 1; + col < current_player->get_board().get_width(); ++col) { + if (!highlight_tile(win, active_unit, col, active_unit.y)) { + break; + } + } + for (int col = active_unit.x - 1; col >= 0; --col) { + if (!highlight_tile(win, active_unit, col, active_unit.y)) { + break; + } + } + for (int row = active_unit.y + 1; + row < current_player->get_board().get_height(); ++row) { + if (!highlight_tile(win, active_unit, active_unit.x, row)) { + break; + } + } + for (int row = active_unit.y - 1; row >= 0; --row) { + if (!highlight_tile(win, active_unit, active_unit.x, row)) { + break; + } + } +} + +bool GameView::highlight_tile(sf::RenderWindow &win, const Tile &active_unit, + int to_x, int to_y) { + if (check_if_viable(active_unit, to_x, to_y)) { + if (current_player->get_tile_info(to_x, to_y) == "enemy") { + red_highlight_sprite.setPosition(return_pixels(to_x, to_y)); + win.draw(red_highlight_sprite); + return false; + } else { + green_highlight_sprite.setPosition(return_pixels(to_x, to_y)); + win.draw(green_highlight_sprite); } - return false; + return true; + } + return false; } -bool GameView::check_if_viable(Board::Tile from, int to_x, int to_y) { - return current_player->can_move(from, Board::Tile(to_x, to_y)); +bool GameView::check_if_viable(Tile from, int to_x, int to_y) { + return current_player->can_move(from, Tile(to_x, to_y)); } -void GameView::draw_end_game_screen(sf::RenderWindow& win, const std::string& victorious_name) { - end_game_info_box.set_text("Congratulations " + victorious_name + " you won!\n"); - end_game_info_box.set_position(info_box.get_position()); - end_game_info_box.draw(win); +void GameView::draw_end_game_screen(sf::RenderWindow &win, + const std::string &victorious_name) { + end_game_info_box.set_text("Congratulations " + victorious_name + + " you won!\n"); + end_game_info_box.set_position(info_box.get_position()); + end_game_info_box.draw(win); } -void GameView::draw_board_border(sf::RenderWindow& win) { - win.draw(board_border); +void GameView::draw_board_border(sf::RenderWindow &win) { + win.draw(board_border); } sf::Vector2f GameView::return_pixels(int col, int row) const { - if (col < 0 && row < 0) { - return sf::Vector2f{-1, -1}; - } - return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); + if (col < 0 && row < 0) { + return sf::Vector2f{-1, -1}; + } + return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); } -Board::Tile GameView::return_tile(const sf::Vector2f& coords) const { - return Board::Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); +Tile GameView::return_tile(const sf::Vector2f &coords) const { + return Tile((coords.x - TILE_SIZE) / TILE_SIZE, + (coords.y - TILE_SIZE) / TILE_SIZE); } -Board::Tile GameView::return_tile(int x, int y) const { - if (x < 0 && y < 0) { - return Board::Tile{-1, -1}; - } - return return_tile(sf::Vector2f(x, y)); +Tile GameView::return_tile(int x, int y) const { + if (x < 0 && y < 0) { + return Tile{-1, -1}; + } + return return_tile(sf::Vector2f(x, y)); } void GameView::set_button_highlights(int mouse_x, int mouse_y) { - if (done_button.contains(mouse_x, mouse_y)) { - done_button.highlight_on(); - } else { - done_button.highlight_off(); - } - if (randomize_button.contains(mouse_x, mouse_y)) { - randomize_button.highlight_on(); - } else { - randomize_button.highlight_off(); - } - if (remove_button.contains(mouse_x, mouse_y)) { - remove_button.highlight_on(); - } else { - remove_button.highlight_off(); - } - if (end_turn_button.contains(mouse_x, mouse_y)) { - end_turn_button.highlight_on(); - } else { - end_turn_button.highlight_off(); - } - if (info_box.button_contains(mouse_x, mouse_y)) { - info_box.set_button_highlight_on(); - } else { - info_box.set_button_highlight_off(); - } - if (end_game_info_box.button_contains(mouse_x, mouse_y)) { - end_game_info_box.set_button_highlight_on(); - } else { - end_game_info_box.set_button_highlight_off(); - } + if (done_button.contains(mouse_x, mouse_y)) { + done_button.highlight_on(); + } else { + done_button.highlight_off(); + } + if (randomize_button.contains(mouse_x, mouse_y)) { + randomize_button.highlight_on(); + } else { + randomize_button.highlight_off(); + } + if (remove_button.contains(mouse_x, mouse_y)) { + remove_button.highlight_on(); + } else { + remove_button.highlight_off(); + } + if (end_turn_button.contains(mouse_x, mouse_y)) { + end_turn_button.highlight_on(); + } else { + end_turn_button.highlight_off(); + } + if (info_box.button_contains(mouse_x, mouse_y)) { + info_box.set_button_highlight_on(); + } else { + info_box.set_button_highlight_off(); + } + if (end_game_info_box.button_contains(mouse_x, mouse_y)) { + end_game_info_box.set_button_highlight_on(); + } else { + end_game_info_box.set_button_highlight_off(); + } } \ No newline at end of file diff --git a/src/MainMenu.cpp b/src/MainMenu.cpp index eb8d7d7..eeda44a 100644 --- a/src/MainMenu.cpp +++ b/src/MainMenu.cpp @@ -1,240 +1,247 @@ #include "MainMenu.hpp" -MainMenu::MainMenu(Player& pA, Player& pB) - : playerA(pA), - playerB(pB), - start_game_button("Start Game"), - game_rules_button("Game Rules"), - exit_button("Exit The Game"), - next("Next"), - prev("Previous"), - names_entered(false), - game_started_button_pressed(false), - rules_button_pressed(false), - exit_button_pressed(false), - next_button_pressed(false), - prev_button_pressed(false), - player_1_name_approved(false), - player_2_name_approved(false), - entering_from_menu(true), - path_to_textures("images/board/"), - idx(0) { - for (size_t i = 0; i < rules_textures.size(); ++i) { - if (!rules_textures[i].loadFromFile(path_to_textures + "rules#" + std::to_string(i + 1) + ".png")) { - std::cerr << "rules#" + std::to_string(i + 1) + " texture failed to load!\n"; - abort(); - } - rules_sprites[i].setTexture(rules_textures[i]); - } - if (!logo_texture.loadFromFile(path_to_textures + "stratego_logo.png")) { - std::cerr << "logo texture failed to load!\n"; - abort(); - } - logo_sprite.setTexture(logo_texture); +MainMenu::MainMenu(Player &pA, Player &pB) + : playerA(pA), playerB(pB), start_game_button("Start Game"), + game_rules_button("Game Rules"), exit_button("Exit The Game"), + next("Next"), prev("Previous"), names_entered(false), + game_started_button_pressed(false), rules_button_pressed(false), + exit_button_pressed(false), next_button_pressed(false), + prev_button_pressed(false), player_1_name_approved(false), + player_2_name_approved(false), entering_from_menu(true), + path_to_textures("images/board/"), idx(0) { + for (size_t i = 0; i < rules_textures.size(); ++i) { + if (!rules_textures[i].loadFromFile(path_to_textures + "rules#" + + std::to_string(i + 1) + ".png")) { + std::cerr << "rules#" + std::to_string(i + 1) + + " texture failed to load!\n"; + abort(); + } + rules_sprites[i].setTexture(rules_textures[i]); + } + if (!logo_texture.loadFromFile(path_to_textures + "stratego_logo.png")) { + std::cerr << "logo texture failed to load!\n"; + abort(); + } + logo_sprite.setTexture(logo_texture); } -std::string MainMenu::run(sf::RenderWindow& win) { - while (true) { - sf::Event event; - while (win.pollEvent(event)) { - if (event.type == sf::Event::Closed) { - return "exit"; //will exit the application in the main function - } - if (event.type == sf::Event::MouseButtonPressed) { - set_buttons_pressed(); - if (names_entered && game_started_button_pressed) { - game_started_button_pressed = false; - return "game"; - } - if (exit_button.is_highlighted() && exit_button_pressed) { - return "exit"; - } - } - if (event.type == sf::Event::MouseMoved) { - highlight_buttons(event.mouseMove.x, event.mouseMove.y); - } - enter_names(event); - } - win.clear(); - if (rules_button_pressed) { - draw_rules(win); - } - if (!game_started_button_pressed && !rules_button_pressed) { - draw_menu(win); - } - if (game_started_button_pressed) { - draw_names(win); +std::string MainMenu::run(sf::RenderWindow &win) { + while (true) { + sf::Event event; + while (win.pollEvent(event)) { + if (event.type == sf::Event::Closed) { + return "exit"; // will exit the application in the main function + } + if (event.type == sf::Event::MouseButtonPressed) { + set_buttons_pressed(); + if (names_entered && game_started_button_pressed) { + game_started_button_pressed = false; + return "game"; } - - win.display(); - } -} - -void MainMenu::set_buttons_pressed() { - if (start_game_button.is_highlighted() && !rules_button_pressed && !exit_button_pressed) { - game_started_button_pressed = true; - } - if (player_1_name.button_is_highlighted() && !player_1_name_approved) { - if (nickname.size() > 3) { - playerA.set_name(nickname); - nickname.clear(); - player_1_name_approved = true; + if (exit_button.is_highlighted() && exit_button_pressed) { + return "exit"; } + } + if (event.type == sf::Event::MouseMoved) { + highlight_buttons(event.mouseMove.x, event.mouseMove.y); + } + enter_names(event); } - if (player_2_name.button_is_highlighted() && !player_2_name_approved) { - if (nickname.size() > 3) { - playerB.set_name(nickname); - nickname.clear(); - player_2_name_approved = true; - names_entered = true; - } - } - if (game_rules_button.is_highlighted() && !game_started_button_pressed && !exit_button_pressed) { - rules_button_pressed = true; - } + win.clear(); if (rules_button_pressed) { - if (next.is_highlighted()) { - next_button_pressed = true; - } - if (prev.is_highlighted()) { - prev_button_pressed = true; - } + draw_rules(win); + } + if (!game_started_button_pressed && !rules_button_pressed) { + draw_menu(win); } - if (exit_button.is_highlighted() && !game_started_button_pressed && !rules_button_pressed) { - exit_button_pressed = true; + if (game_started_button_pressed) { + draw_names(win); } + + win.display(); + } } -void MainMenu::draw_menu(sf::RenderWindow& win) { - logo_sprite.setPosition((win.getSize().x - logo_sprite.getLocalBounds().width) / 2, - 0.8 * start_game_button.get_height()); - start_game_button.set_position((win.getSize().x - start_game_button.get_width()) / 2, - (logo_sprite.getPosition().y + 1.5 * start_game_button.get_height())); - game_rules_button.set_position(start_game_button.get_position().x, - start_game_button.get_position().y + 1.25 * game_rules_button.get_height()); - exit_button.set_position(game_rules_button.get_position().x, - game_rules_button.get_position().y + 1.25 * exit_button.get_height()); +void MainMenu::set_buttons_pressed() { + if (start_game_button.is_highlighted() && !rules_button_pressed && + !exit_button_pressed) { + game_started_button_pressed = true; + } + if (player_1_name.button_is_highlighted() && !player_1_name_approved) { + if (nickname.size() > 3) { + playerA.set_name(nickname); + nickname.clear(); + player_1_name_approved = true; + } + } + if (player_2_name.button_is_highlighted() && !player_2_name_approved) { + if (nickname.size() > 3) { + playerB.set_name(nickname); + nickname.clear(); + player_2_name_approved = true; + names_entered = true; + } + } + if (game_rules_button.is_highlighted() && !game_started_button_pressed && + !exit_button_pressed) { + rules_button_pressed = true; + } + if (rules_button_pressed) { + if (next.is_highlighted()) { + next_button_pressed = true; + } + if (prev.is_highlighted()) { + prev_button_pressed = true; + } + } + if (exit_button.is_highlighted() && !game_started_button_pressed && + !rules_button_pressed) { + exit_button_pressed = true; + } +} - win.draw(logo_sprite); - start_game_button.draw(win); - game_rules_button.draw(win); - exit_button.draw(win); +void MainMenu::draw_menu(sf::RenderWindow &win) { + logo_sprite.setPosition( + (win.getSize().x - logo_sprite.getLocalBounds().width) / 2, + 0.8 * start_game_button.get_height()); + start_game_button.set_position( + (win.getSize().x - start_game_button.get_width()) / 2, + (logo_sprite.getPosition().y + 1.5 * start_game_button.get_height())); + game_rules_button.set_position(start_game_button.get_position().x, + start_game_button.get_position().y + + 1.25 * game_rules_button.get_height()); + exit_button.set_position(game_rules_button.get_position().x, + game_rules_button.get_position().y + + 1.25 * exit_button.get_height()); + + win.draw(logo_sprite); + start_game_button.draw(win); + game_rules_button.draw(win); + exit_button.draw(win); } -void MainMenu::draw_names(sf::RenderWindow& win) { - if (!player_1_name_approved) { - player_1_name.set_text("Red Player's Name: " + nickname); - player_1_name.set_position((win.getSize().x - player_1_name.get_width()) / 2, - (win.getSize().y - player_1_name.get_height()) / 2); - player_1_name.draw(win); - } - if (player_1_name_approved && !player_2_name_approved) { - player_2_name.set_text("Blue Player's Name: " + nickname); - player_2_name.set_position(player_1_name.get_position()); - player_2_name.draw(win); - } +void MainMenu::draw_names(sf::RenderWindow &win) { + if (!player_1_name_approved) { + player_1_name.set_text("Red Player's Name: " + nickname); + player_1_name.set_position( + (win.getSize().x - player_1_name.get_width()) / 2, + (win.getSize().y - player_1_name.get_height()) / 2); + player_1_name.draw(win); + } + if (player_1_name_approved && !player_2_name_approved) { + player_2_name.set_text("Blue Player's Name: " + nickname); + player_2_name.set_position(player_1_name.get_position()); + player_2_name.draw(win); + } } -void MainMenu::draw_rules(sf::RenderWindow& win) { - if (entering_from_menu) { - entering_from_menu = false; - idx = 0; - prev.set_text("Menu"); - } - if (idx > 0) { - prev.set_text("Previous"); - } - if (idx == 0) { - prev.set_text("Menu"); - } - next.set_position(win.getSize().x - 1.25 * next.get_width(), win.getSize().y - 1.75 * next.get_height()); - prev.set_position(0.25 * next.get_width(), win.getSize().y - 1.75 * next.get_height()); - draw_rule(win, idx); - if (next_button_pressed) { - if (idx < 4) { - idx++; - } - next_button_pressed = false; - } - if (prev_button_pressed && prev.get_text() != "Menu") { - if (idx > 0) { - idx--; - } else if (idx == 0) { - prev.set_text("Menu"); - } - prev_button_pressed = false; - } - if (prev_button_pressed && prev.get_text() == "Menu") { - prev_button_pressed = false; - rules_button_pressed = false; - game_started_button_pressed = false; - entering_from_menu = true; - return; - } +void MainMenu::draw_rules(sf::RenderWindow &win) { + if (entering_from_menu) { + entering_from_menu = false; + idx = 0; + prev.set_text("Menu"); + } + if (idx > 0) { + prev.set_text("Previous"); + } + if (idx == 0) { + prev.set_text("Menu"); + } + next.set_position(win.getSize().x - 1.25 * next.get_width(), + win.getSize().y - 1.75 * next.get_height()); + prev.set_position(0.25 * next.get_width(), + win.getSize().y - 1.75 * next.get_height()); + draw_rule(win, idx); + if (next_button_pressed) { if (idx < 4) { - next.draw(win); + idx++; } - prev.draw(win); + next_button_pressed = false; + } + if (prev_button_pressed && prev.get_text() != "Menu") { + if (idx > 0) { + idx--; + } else if (idx == 0) { + prev.set_text("Menu"); + } + prev_button_pressed = false; + } + if (prev_button_pressed && prev.get_text() == "Menu") { + prev_button_pressed = false; + rules_button_pressed = false; + game_started_button_pressed = false; + entering_from_menu = true; + return; + } + if (idx < 4) { + next.draw(win); + } + prev.draw(win); } -void MainMenu::draw_rule(sf::RenderWindow& win, int idx) { - if (idx < 0) { - return; - } - int rules_x_pos = (win.getSize().x - rules_sprites[idx].getLocalBounds().width) / 2; - int rules_y_pos = (win.getSize().y - rules_sprites[idx].getLocalBounds().height) / 2; - rules_sprites[idx].setPosition(rules_x_pos, rules_y_pos); - win.draw(rules_sprites[idx]); +void MainMenu::draw_rule(sf::RenderWindow &win, int idx) { + if (idx < 0) { + return; + } + int rules_x_pos = + (win.getSize().x - rules_sprites[idx].getLocalBounds().width) / 2; + int rules_y_pos = + (win.getSize().y - rules_sprites[idx].getLocalBounds().height) / 2; + rules_sprites[idx].setPosition(rules_x_pos, rules_y_pos); + win.draw(rules_sprites[idx]); } void MainMenu::highlight_buttons(int mouse_x, int mouse_y) { - if (start_game_button.contains(mouse_x, mouse_y)) { - start_game_button.highlight_on(); - } else { - start_game_button.highlight_off(); - } - if (game_rules_button.contains(mouse_x, mouse_y)) { - game_rules_button.highlight_on(); - } else { - game_rules_button.highlight_off(); - } - if (exit_button.contains(mouse_x, mouse_y)) { - exit_button.highlight_on(); - } else { - exit_button.highlight_off(); - } - if (player_1_name.button_contains(mouse_x, mouse_y) && game_started_button_pressed) { - player_1_name.set_button_highlight_on(); - } else { - player_1_name.set_button_highlight_off(); - } - if (player_2_name.button_contains(mouse_x, mouse_y) && player_1_name_approved) { - player_2_name.set_button_highlight_on(); - } else { - player_2_name.set_button_highlight_off(); - } - if (next.contains(mouse_x, mouse_y)) { - next.highlight_on(); - } else { - next.highlight_off(); - } - if (prev.contains(mouse_x, mouse_y)) { - prev.highlight_on(); - } else { - prev.highlight_off(); - } + if (start_game_button.contains(mouse_x, mouse_y)) { + start_game_button.highlight_on(); + } else { + start_game_button.highlight_off(); + } + if (game_rules_button.contains(mouse_x, mouse_y)) { + game_rules_button.highlight_on(); + } else { + game_rules_button.highlight_off(); + } + if (exit_button.contains(mouse_x, mouse_y)) { + exit_button.highlight_on(); + } else { + exit_button.highlight_off(); + } + if (player_1_name.button_contains(mouse_x, mouse_y) && + game_started_button_pressed) { + player_1_name.set_button_highlight_on(); + } else { + player_1_name.set_button_highlight_off(); + } + if (player_2_name.button_contains(mouse_x, mouse_y) && + player_1_name_approved) { + player_2_name.set_button_highlight_on(); + } else { + player_2_name.set_button_highlight_off(); + } + if (next.contains(mouse_x, mouse_y)) { + next.highlight_on(); + } else { + next.highlight_off(); + } + if (prev.contains(mouse_x, mouse_y)) { + prev.highlight_on(); + } else { + prev.highlight_off(); + } } -void MainMenu::enter_names(sf::Event& event) { - if (!game_started_button_pressed) { - return; - } - if (event.type == sf::Event::TextEntered) { - if (event.text.unicode > 31 && event.text.unicode < 128 && nickname.size() < 21) { - nickname += event.text.unicode; - } - if (event.text.unicode == '\b' && !nickname.empty()) { - nickname.pop_back(); - } - } +void MainMenu::enter_names(sf::Event &event) { + if (!game_started_button_pressed) { + return; + } + if (event.type == sf::Event::TextEntered) { + if (event.text.unicode > 31 && event.text.unicode < 128 && + nickname.size() < 21) { + nickname += event.text.unicode; + } + if (event.text.unicode == '\b' && !nickname.empty()) { + nickname.pop_back(); + } + } } diff --git a/src/Movable.cpp b/src/Movable.cpp deleted file mode 100644 index 96a6f87..0000000 --- a/src/Movable.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "Movable.hpp" - -#include "Unit.hpp" - -Movable::Movable(Movable::Delegate* del) : delegate(del) {} - -bool Movable::can_move(int from_x, int from_y, int to_x, int to_y) const -{ - if (from_x + 1 == to_x && from_y == to_y) { - return true; - } - if (from_x - 1 == to_x && from_y == to_y) { - return true; - } - if (from_x == to_x && from_y + 1 == to_y) { - return true; - } - if (from_x == to_x && from_y - 1 == to_y) { - return true; - } - return false; -} - -RESULT Movable::attack(const std::shared_ptr& rhs) const -{ - if (!rhs) { - throw std::invalid_argument( - "Movable.cpp:27 - unit you try to attack doesn't exist"); - } - if (rhs->get_type() == "bomb") { - return RESULT::LOST; - } - if (delegate->get_value() > rhs->get_value()) { - return RESULT::WON; - } - if (delegate->get_value() == rhs->get_value()) { - return RESULT::DRAW; - } - return RESULT::LOST; -} diff --git a/src/Player.cpp b/src/Player.cpp index f134318..15e41af 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1,126 +1,93 @@ -#include "Movable.hpp" -#include "Unit.hpp" #include "Player.hpp" + #include -void Player::set_units_count() { - units_count.insert(std::pair{"regular4", 0}); - units_count.insert(std::pair{"regular5", 0}); - units_count.insert(std::pair{"regular6", 0}); - units_count.insert(std::pair{"regular7", 0}); - units_count.insert(std::pair{"regular8", 0}); - units_count.insert(std::pair{"regular9", 0}); - units_count.insert(std::pair{"regular10", 0}); - units_count.insert(std::pair{"bomb", 0}); - units_count.insert(std::pair{"miner", 0}); - units_count.insert(std::pair{"flag", 0}); - units_count.insert(std::pair{"spy", 0}); - units_count.insert(std::pair{"scout", 0}); - units_count.insert(std::pair{"marshal", 0}); -} +#include "unit/Unit.hpp" +#include "unit/visit/Attack.hpp" +#include "unit/visit/GetOwner.hpp" void Player::set_unit(int col, int row, int choice) { - if (board.set_unit(col, row, player, choice)) { - std::shared_ptr chosen_unit = board.get_unit(col, row); - if (chosen_unit->get_type() == "regular") { - units_count[chosen_unit->get_type() + std::to_string(chosen_unit->get_value())]++; - } - units_count[chosen_unit->get_type()]++; - } + board.set_unit(col, row, player, choice); } void Player::remove_unit(int col, int row) { - if (board.get_unit(col, row)) { - std::shared_ptr temp_unit = board.get_unit(col, row); - if (temp_unit->get_type() == "regular") { - units_count[temp_unit->get_type() + std::to_string(temp_unit->get_value())]--; - } - units_count[board.get_unit(col, row)->get_type()]--; - board.remove_unit(col, row); - } + if (board.get_unit(col, row)) { + board.remove_unit(col, row); + } } -void Player::remove_unit(Board::Tile chosen_unit) { - remove_unit(chosen_unit.x, chosen_unit.y); +void Player::remove_unit(Tile chosen_unit) { + remove_unit(chosen_unit.x, chosen_unit.y); } -void Player::reverse_remove_unit(Board::Tile unit) { - board.reverse_remove_unit(unit.x, unit.y); +void Player::reverse_remove_unit(Tile unit) { + board.reverse_remove_unit(unit.x, unit.y); } -bool Player::move_unit(Board::Tile from, Board::Tile to) { - return board.move_unit(from, to); -} +bool Player::move_unit(Tile from, Tile to) { return board.move_unit(from, to); } -RESULT Player::attack(Board::Tile attacker, Board::Tile attacked) { - const Movable* movable = dynamic_cast(board.get_unit(attacker).get()); - if (!movable) { - throw std::logic_error("Player.cpp:58 - unit you wish to attack with cannot move"); - } - return movable->attack(board.get_unit(attacked)); +attack::Result Player::attack(Tile attacker, Tile attacked) { + // TODO: make the actual implementation a strategy (use dependency injection) + const auto &attacker_unit = board.get_unit(attacker); + const auto &attacked_unit = board.get_unit(attacked); + return std::visit(Attack{}, attacker_unit.value(), attacked_unit.value()); } -void Player::reverse_move_unit(Board::Tile from, Board::Tile to) { - board.reverse_move_unit(from, to); +void Player::reverse_move_unit(Tile from, Tile to) { + board.reverse_move_unit(from, to); } -bool Player::can_move(Board::Tile from, Board::Tile to) { - if (board.get_tile_info(to.x, to.y, player) == "#") { - return false; - } - if (board.get_tile_info(to.x, to.y, player) == "O") { - return false; - } - if (board.get_unit(to.x, to.y)) { - if (board.get_unit(to.x, to.y)->get_owner() == player) { - return false; - } - } - if (!board.can_move(from, to)) { - return false; +bool Player::can_move(Tile from, Tile to) { + if (board.get_tile_info(to.x, to.y, player) == "#") { + return false; + } + if (board.get_tile_info(to.x, to.y, player) == "O") { + return false; + } + if (board.get_unit(to.x, to.y)) { + if (std::visit(GetOwner{}, board.get_unit(to.x, to.y).value()) == player) { + return false; } + } + if (!board.can_move(from, to)) { + return false; + } - return true; + return true; } -void Player::update_board(const Board& other_player_board) { - board.update(other_player_board); +void Player::update_board(const Board &other_player_board) { + board.update(other_player_board); } std::string Player::get_tile_info(int col, int row) const { - return board.get_tile_info(col, row, player); + return board.get_tile_info(col, row, player); } -std::string Player::get_tile_info(Board::Tile tile) const { - return board.get_tile_info(tile, player); +std::string Player::get_tile_info(Tile tile) const { + return board.get_tile_info(tile, player); } int Player::get_units_count(int idx) { - switch (idx) { - case 0: - return units_count.at("scout"); - case 1: - return units_count.at("miner"); - case 2: - return units_count.at("regular4"); - case 3: - return units_count.at("regular5"); - case 4: - return units_count.at("regular6"); - case 5: - return units_count.at("regular7"); - case 6: - return units_count.at("regular8"); - case 7: - return units_count.at("regular9"); - case 8: - return units_count.at("regular10"); - case 9: - return units_count.at("bomb"); - case 10: - return units_count.at("flag"); - case 11: - return units_count.at("spy"); - } - return -1; + switch (idx) { + case 0: + return ScoutUnit::get_count(); + case 1: + return MinerUnit::get_count(); + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return RegularUnit::get_count(idx + 2); + case 9: + return BombUnit::get_count(); + case 10: + return FlagUnit::get_count(); + case 11: + return SpyUnit::get_count(); + } + return -1; } diff --git a/src/main.cpp b/src/main.cpp index 249cdaa..6e3cb8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,24 +5,26 @@ #include "Game.hpp" #include "MainMenu.hpp" #include "Player.hpp" -#include "RegularUnit.hpp" +#include "unit/RegularUnit.hpp" int main() { - Board board; - Player playerA("Red-A", TURN::PLAYER_A); - Player playerB("Blue-B", TURN::PLAYER_B); - GameView game_view(playerA, playerB); - GameController game_controller(playerA, playerB, game_view); - Game game(game_view, game_controller); - MainMenu menu(playerA, playerB); - std::map screens; - screens["menu"] = &menu; - screens["game"] = &game; - std::string screen = "menu"; - const unsigned int width = static_cast(game_view.get_window_size().x); - const unsigned int height = static_cast(game_view.get_window_size().y); - sf::RenderWindow window(sf::VideoMode(width, height), "stratego"); - while(screen != "exit") { - screen = screens[screen]->run(window); - } + Board board; + Player playerA("Red-A", Turn::PlayerA); + Player playerB("Blue-B", Turn::PlayerB); + GameView game_view(playerA, playerB); + GameController game_controller(playerA, playerB, game_view); + Game game(game_view, game_controller); + MainMenu menu(playerA, playerB); + std::map screens; + screens["menu"] = &menu; + screens["game"] = &game; + std::string screen = "menu"; + const unsigned int width = + static_cast(game_view.get_window_size().x); + const unsigned int height = + static_cast(game_view.get_window_size().y); + sf::RenderWindow window(sf::VideoMode(width, height), "stratego"); + while (screen != "exit") { + screen = screens[screen]->run(window); + } } diff --git a/src/unit/BombUnit.cpp b/src/unit/BombUnit.cpp new file mode 100644 index 0000000..f0a36dc --- /dev/null +++ b/src/unit/BombUnit.cpp @@ -0,0 +1,3 @@ +#include "unit/BombUnit.hpp" + +BombUnit::BombUnit(Turn player) : model_(-1, "bomb", player) {}; diff --git a/src/unit/FlagUnit.cpp b/src/unit/FlagUnit.cpp new file mode 100644 index 0000000..d73cde0 --- /dev/null +++ b/src/unit/FlagUnit.cpp @@ -0,0 +1,3 @@ +#include "unit/FlagUnit.hpp" + +FlagUnit::FlagUnit(Turn player) : model_(-1, "flag", player) {}; diff --git a/src/unit/MinerUnit.cpp b/src/unit/MinerUnit.cpp new file mode 100644 index 0000000..3c39bff --- /dev/null +++ b/src/unit/MinerUnit.cpp @@ -0,0 +1,3 @@ +#include "unit/MinerUnit.hpp" + +MinerUnit::MinerUnit(Turn player) : model_(3, "miner", player) {} diff --git a/src/unit/RegularUnit.cpp b/src/unit/RegularUnit.cpp new file mode 100644 index 0000000..0204e80 --- /dev/null +++ b/src/unit/RegularUnit.cpp @@ -0,0 +1,4 @@ +#include "unit/RegularUnit.hpp" + +RegularUnit::RegularUnit(int value, Turn player) + : model_(value, "regular", player), counter_(value) {}; diff --git a/src/unit/ScoutUnit.cpp b/src/unit/ScoutUnit.cpp new file mode 100644 index 0000000..8b1fd80 --- /dev/null +++ b/src/unit/ScoutUnit.cpp @@ -0,0 +1,3 @@ +#include "unit/ScoutUnit.hpp" + +ScoutUnit::ScoutUnit(Turn player) : model_(2, "scout", player) {}; diff --git a/src/unit/SpyUnit.cpp b/src/unit/SpyUnit.cpp new file mode 100644 index 0000000..fb37f14 --- /dev/null +++ b/src/unit/SpyUnit.cpp @@ -0,0 +1,3 @@ +#include "unit/SpyUnit.hpp" + +SpyUnit::SpyUnit(Turn player) : model_(1, "spy", player) {}; diff --git a/src/unit/Unit.cpp b/src/unit/Unit.cpp new file mode 100644 index 0000000..e69de29 diff --git a/src/unit/UnitCounter.cpp b/src/unit/UnitCounter.cpp new file mode 100644 index 0000000..d22a7ef --- /dev/null +++ b/src/unit/UnitCounter.cpp @@ -0,0 +1,58 @@ +#pragma once + +#include "unit/UnitCounter.hpp" + +#include +#include + +#include "unit/RegularUnit.hpp" + +std::unordered_map RegularUnitCounter::count_ = {}; + +struct RegularUnitMaxCount { + int operator()(int unit_value) { + switch (unit_value) { + case 4: + case 5: + case 6: + return 4; + case 7: + return 3; + case 8: + return 2; + case 9: + return 1; + case 10: + return 1; + default: + break; + } + std::cerr << "Unexpected unit value: " << unit_value + << ", returning max count 0\n"; + return 0; + } +}; + +RegularUnitCounter::RegularUnitCounter(const int unit_value) + : unit_value_(unit_value) { + ++count_[unit_value]; +} +RegularUnitCounter::RegularUnitCounter(const RegularUnitCounter &rhs) + : RegularUnitCounter(rhs.unit_value_) {} +RegularUnitCounter & +RegularUnitCounter::operator=(const RegularUnitCounter &rhs) { + if (this != &rhs) { + unit_value_ = rhs.unit_value_; + ++count_[unit_value_]; + } + return *this; +}; +RegularUnitCounter::RegularUnitCounter(RegularUnitCounter &&) = default; +RegularUnitCounter & +RegularUnitCounter::operator=(RegularUnitCounter &&) = default; +RegularUnitCounter::~RegularUnitCounter() { --count_[unit_value_]; } + +int RegularUnitCounter::get_count(const int value) { return count_[value]; } +int RegularUnitCounter::get_max_count(const int value) { + return RegularUnitMaxCount{}(value); +} \ No newline at end of file diff --git a/src/unit/UnitModel.cpp b/src/unit/UnitModel.cpp new file mode 100644 index 0000000..fb8c7b1 --- /dev/null +++ b/src/unit/UnitModel.cpp @@ -0,0 +1,11 @@ +#include "unit/UnitModel.hpp" + +UnitModel::UnitModel(int value, std::string type, Turn player) + : value_(value), type_(std::move(type)), owner_(player) {} + +int UnitModel::get_value() const noexcept { return value_; } +[[deprecated("Future refactoring will remove get_type()")]] +std::string UnitModel::get_type() const noexcept { + return type_; +} +Turn UnitModel::get_owner() const noexcept { return owner_; } \ No newline at end of file