diff --git a/Linked-List-Snake/Linked-List-Snake.vcxproj b/Linked-List-Snake/Linked-List-Snake.vcxproj index 99de33c33..f6751b972 100644 --- a/Linked-List-Snake/Linked-List-Snake.vcxproj +++ b/Linked-List-Snake/Linked-List-Snake.vcxproj @@ -1,4 +1,4 @@ - + @@ -134,9 +134,23 @@ + + + + + + + + + + + + + + @@ -148,14 +162,35 @@ + + + + + + + + + + + + + + + + + + + + + @@ -168,6 +203,7 @@ + diff --git a/Linked-List-Snake/include/Element/ElementData.h b/Linked-List-Snake/include/Element/ElementData.h new file mode 100644 index 000000000..da32c7314 --- /dev/null +++ b/Linked-List-Snake/include/Element/ElementData.h @@ -0,0 +1,22 @@ +#pragma once +#include + +namespace Element +{ + enum class ElementType + { + OBSTACLE, + }; + + struct ElementData + { + ElementData(ElementType type, sf::Vector2i pos) + { + element_type = type; + position = pos; + } + + ElementType element_type; + sf::Vector2i position; + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Element/ElementService.h b/Linked-List-Snake/include/Element/ElementService.h new file mode 100644 index 000000000..8ea07e0c8 --- /dev/null +++ b/Linked-List-Snake/include/Element/ElementService.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include + +namespace Element +{ + class Obstacle; + struct ElementData; + + class ElementService + { + private: + std::vector obstacle_list; + + void spawnObstacle(sf::Vector2i position, float cell_width, float cell_height); + + public: + ElementService(); + ~ElementService(); + + void initialize(); + void update(); + void render(); + + const void spawnElements(std::vector& element_data_list, float cell_width, float cell_height); + std::vector getElementsPositionList(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Element/Obstacle.h b/Linked-List-Snake/include/Element/Obstacle.h new file mode 100644 index 000000000..2b50a983d --- /dev/null +++ b/Linked-List-Snake/include/Element/Obstacle.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include "UI/UIElement/ImageView.h" + +namespace Element +{ + class Obstacle + { + private: + UI::UIElement::ImageView* obstacle_image; + + sf::Vector2i grid_position; + + float cell_width; + float cell_height; + + void initializeObstacleImage(); + sf::Vector2f getObstacleImagePosition(); + + public: + Obstacle(); + ~Obstacle(); + + void initialize(sf::Vector2i grid_pos, float width, float height); + void update(); + void render(); + + sf::Vector2i getObstaclePosition(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Food/FoodItem.h b/Linked-List-Snake/include/Food/FoodItem.h new file mode 100644 index 000000000..2a23ee13f --- /dev/null +++ b/Linked-List-Snake/include/Food/FoodItem.h @@ -0,0 +1,37 @@ +#pragma once +#include +#include "UI/UIElement/ImageView.h" + +namespace Food +{ + enum class FoodType; + + class FoodItem + { + private: + UI::UIElement::ImageView* food_image; + + sf::Vector2i grid_position; + + float cell_width; + float cell_height; + + FoodType food_type; + + void initializeFoodImage(); + sf::String getFoodTexturePath(); + sf::Vector2f getFoodImagePosition(); + + public: + static const int number_of_foods = 8; + + FoodItem(); + ~FoodItem(); + + void initialize(sf::Vector2i grid_pos, float width, float height, FoodType type); + void update(); + void render(); + + FoodType getFoodType(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Food/FoodService.h b/Linked-List-Snake/include/Food/FoodService.h new file mode 100644 index 000000000..b6e4225be --- /dev/null +++ b/Linked-List-Snake/include/Food/FoodService.h @@ -0,0 +1,61 @@ +#pragma once +#include +#include +#include + +namespace Food +{ + enum class FoodType; + class FoodItem; + + enum FoodSpawningStatus + { + ACTIVE, + IN_ACTIVE, + }; + + class FoodService + { + private: + const float spawn_duration = 4.f; + + float elapsed_duration; + + FoodSpawningStatus current_spawning_status; + FoodItem* current_food_item; + + float cell_width; + float cell_height; + + // To generate random values. + std::default_random_engine random_engine; + + // To give random seed to generator. + std::random_device random_device; + + FoodItem* createFood(sf::Vector2i position, FoodType type); + void spawnFood(); + + sf::Vector2i getValidSpawnPosition(); + sf::Vector2i getRandomPosition(); + FoodType getRandomFoodType(); + + bool isValidPosition(std::vector position_data, sf::Vector2i food_position); + + void destroyFood(); + void updateElapsedDuration(); + void handleFoodSpawning(); + void reset(); + + public: + FoodService(); + ~FoodService(); + + void initialize(); + void update(); + void render(); + + void startFoodSpawning(); + void stopFoodSpawning(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Food/FoodType.h b/Linked-List-Snake/include/Food/FoodType.h new file mode 100644 index 000000000..404675ff9 --- /dev/null +++ b/Linked-List-Snake/include/Food/FoodType.h @@ -0,0 +1,16 @@ +#pragma once + +namespace Food +{ + enum class FoodType + { + APPLE, + MANGO, + ORANGE, + PIZZA, + BURGER, + CHEESE, + POISION, + ALCOHOL, + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Global/ServiceLocator.h b/Linked-List-Snake/include/Global/ServiceLocator.h index b73213ab9..ddd22fcea 100644 --- a/Linked-List-Snake/include/Global/ServiceLocator.h +++ b/Linked-List-Snake/include/Global/ServiceLocator.h @@ -3,7 +3,11 @@ #include "Event/EventService.h" #include "UI/UIService.h" #include "Sound/SoundService.h" +#include "Level/LevelService.h" +#include "Element/ElementService.h" #include "Time/TimeService.h" +#include "Player/PlayerService.h" +#include "Food/FoodService.h" namespace Global { @@ -13,6 +17,10 @@ namespace Global Event::EventService* event_service; Graphics::GraphicService* graphic_service; Sound::SoundService* sound_service; + Level::LevelService* level_service; + Element::ElementService* element_service; + Player::PlayerService* player_service; + Food::FoodService* food_service; UI::UIService* ui_service; Time::TimeService* time_service; @@ -32,7 +40,11 @@ namespace Global Event::EventService* getEventService(); Graphics::GraphicService* getGraphicService(); Sound::SoundService* getSoundService(); + Level::LevelService* getLevelService(); + Element::ElementService* getElementService(); + Player::PlayerService* getPlayerService(); UI::UIService* getUIService(); + Food::FoodService* getFoodService(); Time::TimeService* getTimeService(); void deleteServiceLocator(); }; diff --git a/Linked-List-Snake/include/Level/LevelController.h b/Linked-List-Snake/include/Level/LevelController.h new file mode 100644 index 000000000..864ea25e3 --- /dev/null +++ b/Linked-List-Snake/include/Level/LevelController.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include "LevelModel.h" + +namespace Level +{ + class LevelView; + + class LevelController + { + private: + LevelModel* level_model; + LevelView* level_view; + + public: + LevelController(); + ~LevelController(); + + void initialize(); + void update(); + void render(); + + float getCellWidth(); + float getCellHeight(); + + const std::vector& getElementDataList(int level_to_load); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Level/LevelData.h b/Linked-List-Snake/include/Level/LevelData.h new file mode 100644 index 000000000..7ae0f2a2b --- /dev/null +++ b/Linked-List-Snake/include/Level/LevelData.h @@ -0,0 +1,18 @@ +#pragma once +#include "Level/LevelService.h" +#include "Element/ElementData.h" + +namespace Level +{ + struct LevelData + { + LevelData(LevelNumber ind, std::vector* data_list) + { + level_index = ind; + element_data_list = data_list; + } + + LevelNumber level_index; + std::vector* element_data_list; + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Level/LevelModel.h b/Linked-List-Snake/include/Level/LevelModel.h new file mode 100644 index 000000000..549283982 --- /dev/null +++ b/Linked-List-Snake/include/Level/LevelModel.h @@ -0,0 +1,88 @@ +#pragma once +#include +#include "Element/ElementService.h" +#include "Element/ElementData.h" +#include "Level/LevelData.h" +#include + +namespace Level +{ + class LevelModel + { + private: + std::vector level_one_element_list = {}; + + std::vector level_two_element_list = + { + //TOP-LEFT + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(1, 1)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(2, 1)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(3, 1)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(1, 2)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(1, 3)), + + //TOP-RIGHT + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(48, 1)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(48, 2)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(48, 3)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(47, 1)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(46, 1)), + + //BOTTOM-LEFT + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(1, 26)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(1, 25)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(1, 24)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(2, 26)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(3, 26)), + + //BOTTOM-RIGHT + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(48, 26)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(48, 25)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(48, 24)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(47, 26)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(46, 26)), + + //CENTER-TOP-BAR + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(21, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(22, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(23, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(24, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(25, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(26, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(27, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(28, 11)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(29, 11)), + + //CENTER-BOTTOM-BAR + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(21, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(22, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(23, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(24, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(25, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(26, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(27, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(28, 15)), + Element::ElementData(Element::ElementType::OBSTACLE, sf::Vector2i(29, 15)), + }; + + std::vector level_configurations; + + float cell_width; + float cell_height; + + void initializeLevelData(); + + public: + static const int number_of_rows = 28; + static const int number_of_columns = 50; + + LevelModel(); + ~LevelModel(); + + void initialize(int width, int height); + + const std::vector& getElementDataList(int level_to_load); + float getCellWidth(); + float getCellHeight(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Level/LevelNumber.h b/Linked-List-Snake/include/Level/LevelNumber.h new file mode 100644 index 000000000..cdf73e444 --- /dev/null +++ b/Linked-List-Snake/include/Level/LevelNumber.h @@ -0,0 +1,9 @@ +#pragma once +namespace Level +{ + enum class LevelNumber + { + ONE, + TWO, + }; +} diff --git a/Linked-List-Snake/include/Level/LevelService.h b/Linked-List-Snake/include/Level/LevelService.h new file mode 100644 index 000000000..7b1397482 --- /dev/null +++ b/Linked-List-Snake/include/Level/LevelService.h @@ -0,0 +1,32 @@ +#pragma once +#include "LevelNumber.h" + +namespace Level +{ + class LevelController; + + class LevelService + { + private: + LevelController* level_controller; + LevelNumber current_level; + + void createLevelController(); + void spawnPlayer(); + void spawnLevelElements(LevelNumber level_to_load); + void spawnFood(); + void destroy(); + + public: + LevelService(); + ~LevelService(); + + void initialize(); + void update(); + void render(); + + void createLevel(LevelNumber level_to_load); + float getCellWidth(); + float getCellHeight(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Level/LevelView.h b/Linked-List-Snake/include/Level/LevelView.h new file mode 100644 index 000000000..905737ed7 --- /dev/null +++ b/Linked-List-Snake/include/Level/LevelView.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include "UI/UIElement/RectangleShapeView.h" + +namespace Level +{ + class LevelView + { + private: + const sf::Color background_color = sf::Color(180, 200, 160); + const sf::Color border_color = sf::Color::Black; + + UI::UIElement::RectangleShapeView* background_rectangle; + UI::UIElement::RectangleShapeView* border_rectangle; + + float grid_width; + float grid_height; + + void createViews(); + void initializeBackground(); + void initializeBorder(); + void calculateGridExtents(); + void destroy(); + + public: + static const int border_thickness = 10; + static const int border_offset_left = 40; + static const int border_offset_top = 40; + + LevelView(); + ~LevelView(); + + void initialize(); + void update(); + void render(); + + float getGridWidth(); + float getGridHeight(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/LinkedList/Node.h b/Linked-List-Snake/include/LinkedList/Node.h new file mode 100644 index 000000000..68bd644f6 --- /dev/null +++ b/Linked-List-Snake/include/LinkedList/Node.h @@ -0,0 +1,13 @@ +#pragma once +#include "Player/BodyPart.h" + +namespace LinkedList +{ + using namespace Player; + + struct Node + { + BodyPart body_part; + Node* next = nullptr; + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/LinkedList/SingleLinkedList.h b/Linked-List-Snake/include/LinkedList/SingleLinkedList.h new file mode 100644 index 000000000..e4bd62e46 --- /dev/null +++ b/Linked-List-Snake/include/LinkedList/SingleLinkedList.h @@ -0,0 +1,40 @@ +#pragma once +#include +#include "LinkedList/Node.h" + +namespace LinkedList +{ + class SingleLinkedList + { + private: + Node* head_node; + + float node_width; + float node_height; + + sf::Vector2i default_position; + Direction default_direction; + + Node* createNode(); + sf::Vector2i getNewNodePosition(Node* reference_node); + + + public: + SingleLinkedList(); + ~SingleLinkedList(); + + void initialize(float width, float height, sf::Vector2i position, Direction direction); + void render(); + + void insertNodeAtTail(); + void removeNodeAtHead(); + void removeAllNodes(); + void updateNodePosition(); + void updateNodeDirection(Direction direction_to_set); + + bool processNodeCollision(); + Node* getHeadNode(); + + std::vector getNodesPositionList(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Player/BodyPart.h b/Linked-List-Snake/include/Player/BodyPart.h new file mode 100644 index 000000000..49e38e0aa --- /dev/null +++ b/Linked-List-Snake/include/Player/BodyPart.h @@ -0,0 +1,44 @@ +#pragma once +#include +#include "UI/UIElement/ImageView.h" +#include "Direction.h" + +namespace Player +{ + class BodyPart + { + protected: + UI::UIElement::ImageView* bodypart_image; + + sf::Vector2i grid_position; + Direction direction; + + float bodypart_width; + float bodypart_height; + + void createBodyPartImage(); + void initializeBodyPartImage(); + sf::Vector2f getBodyPartScreenPosition(); + float getRotationAngle(); + + sf::Vector2i getNextPositionUp(); + sf::Vector2i getNextPositionDown(); + sf::Vector2i getNextPositionLeft(); + sf::Vector2i getNextPositionRight(); + + void destroy(); + + public: + BodyPart(); + ~BodyPart(); + + void initialize(float width, float height, sf::Vector2i pos, Direction dir); + void updatePosition(); + void render(); + + Direction getDirection(); + void setDirection(Direction new_direction); + sf::Vector2i getPosition(); + sf::Vector2i getNextPosition(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Player/Direction.h b/Linked-List-Snake/include/Player/Direction.h new file mode 100644 index 000000000..e8128b149 --- /dev/null +++ b/Linked-List-Snake/include/Player/Direction.h @@ -0,0 +1,12 @@ +#pragma once + +namespace Player +{ + enum class Direction + { + UP, + DOWN, + LEFT, + RIGHT, + }; +} diff --git a/Linked-List-Snake/include/Player/PlayerService.h b/Linked-List-Snake/include/Player/PlayerService.h new file mode 100644 index 000000000..3d6acb5de --- /dev/null +++ b/Linked-List-Snake/include/Player/PlayerService.h @@ -0,0 +1,28 @@ +#pragma once +#include +#include + +namespace Player +{ + class SnakeController; + + class PlayerService + { + private: + SnakeController* snake_controller; + + void createController(); + void destroy(); + + public: + PlayerService(); + ~PlayerService(); + + void initialize(); + void update(); + void render(); + + void spawnPlayer(); + std::vector getCurrentSnakePositionList(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/Player/SnakeController.h b/Linked-List-Snake/include/Player/SnakeController.h new file mode 100644 index 000000000..f9fcbdc76 --- /dev/null +++ b/Linked-List-Snake/include/Player/SnakeController.h @@ -0,0 +1,64 @@ +#pragma once +#include +#include "LinkedList/Node.h" +#include "LinkedList/SingleLinkedList.h" +#include "LinkedList/SingleLinkedList.h" + +namespace Player +{ + enum class SnakeState + { + ALIVE, + DEAD, + }; + + enum class InputState + { + WAITING, + PROCESSING + }; + + class SnakeController + { + private: + const int initial_snake_length = 10; + const float movement_frame_duration = 0.1f; + const float restart_duration = 3.f; + + const sf::Vector2i default_position = sf::Vector2i(25, 13); + const LinkedList::Direction default_direction = LinkedList::Direction::RIGHT; + + SnakeState current_snake_state; + float elapsed_duration; + float restart_counter; + LinkedList::Direction current_snake_direction; + InputState current_input_state; + + LinkedList::SingleLinkedList* single_linked_list; + + void createLinkedList(); + void processPlayerInput(); + void updateSnakeDirection(); + void delayedUpdate(); + void moveSnake(); + void processSnakeCollision(); + void handleRestart(); + void reset(); + void destroy(); + + public: + SnakeController(); + ~SnakeController(); + + void initialize(); + void update(); + void render(); + + void spawnSnake(); + void respawnSnake(); + void setSnakeState(SnakeState state); + SnakeState getSnakeState(); + + std::vector getCurrentSnakePositionList(); + }; +} \ No newline at end of file diff --git a/Linked-List-Snake/include/UI/GameplayUI/GameplayUIController.h b/Linked-List-Snake/include/UI/GameplayUI/GameplayUIController.h new file mode 100644 index 000000000..ec7952af4 --- /dev/null +++ b/Linked-List-Snake/include/UI/GameplayUI/GameplayUIController.h @@ -0,0 +1,43 @@ +#pragma once +#include "UI/Interface/IUIController.h" +#include "UI/UIElement/TextView.h" + +namespace UI +{ + namespace GameplayUI + { + class GameplayUIController : public Interface::IUIController + { + private: + // Constants: + const float font_size = 60.f; + + const float text_y_position = 7.f; + const float level_number_text_x_position = 65.f; + const float score_text_x_position = 800.f; + const float time_complexity_text_x_position = 1330.f; + + UI::UIElement::TextView* level_number_text; + UI::UIElement::TextView* score_text; + UI::UIElement::TextView* time_complexity_text; + + void createTexts(); + void initializeTexts(); + void initializeLevelNumberText(); + void initializeScoreText(); + void initializeTimeComplexityText(); + + void destroy(); + + public: + GameplayUIController(); + ~GameplayUIController(); + + void initialize() override; + void update() override; + void render() override; + void show() override; + }; + } +} + diff --git a/Linked-List-Snake/include/UI/LevelSelection/LevelSelectionUIController.h b/Linked-List-Snake/include/UI/LevelSelection/LevelSelectionUIController.h new file mode 100644 index 000000000..324dd4b4f --- /dev/null +++ b/Linked-List-Snake/include/UI/LevelSelection/LevelSelectionUIController.h @@ -0,0 +1,53 @@ +#pragma once +#include +#include "UI/Interface/IUIController.h" +#include "UI/UIElement/ButtonView.h" +#include "UI/UIElement/ImageView.h" + +namespace UI +{ + namespace LevelSelection + { + class LevelSelectionUIController : public Interface::IUIController + { + private: + // Constants: + const float button_width = 400.f; + const float button_height = 140.f; + + const float level_one_button_y_position = 500.f; + const float level_two_button_y_position = 700.f; + const float menu_button_y_position = 900.f; + + const float background_alpha = 85.f; + + UI::UIElement::ImageView* background_image; + + UI::UIElement::ButtonView* level_one_button; + UI::UIElement::ButtonView* level_two_button; + UI::UIElement::ButtonView* menu_button; + + void createImage(); + void createButtons(); + void initializeBackgroundImage(); + void initializeButtons(); + void registerButtonCallback(); + float calculateLeftOffsetForButton(); + + void levelOneButtonCallback(); + void levelTwoButtonCallback(); + void menuButtonCallback(); + + void destroy(); + + public: + LevelSelectionUIController(); + ~LevelSelectionUIController(); + + void initialize() override; + void update() override; + void render() override; + void show() override; + }; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/include/UI/UIElement/RectangleShapeView.h b/Linked-List-Snake/include/UI/UIElement/RectangleShapeView.h new file mode 100644 index 000000000..dc25fff18 --- /dev/null +++ b/Linked-List-Snake/include/UI/UIElement/RectangleShapeView.h @@ -0,0 +1,28 @@ +#pragma once +#include "UIView.h" + +namespace UI +{ + namespace UIElement + { + class RectangleShapeView : public UIView + { + protected: + sf::RectangleShape rectangle_shape; + + public: + RectangleShapeView(); + virtual ~RectangleShapeView(); + + virtual void initialize(sf::Vector2f rectangle_size, sf::Vector2f rectangle_position, int outline_thikness = 0, sf::Color fill_color = sf::Color::Transparent, sf::Color outline_color = sf::Color::Transparent); + virtual void update() override; + virtual void render() override; + + virtual void setSize(sf::Vector2f rectangle_size); + virtual void setPosition(sf::Vector2f rectangle_position); + virtual void setFillColor(sf::Color fill_color); + virtual void setOutlineColor(sf::Color outline_color); + virtual void setOutlineThickness(int outline_thikness); + }; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/include/UI/UIService.h b/Linked-List-Snake/include/UI/UIService.h index 756cb730e..792f1b1b6 100644 --- a/Linked-List-Snake/include/UI/UIService.h +++ b/Linked-List-Snake/include/UI/UIService.h @@ -1,9 +1,11 @@ #pragma once #include "UI/MainMenu/MainMenuUIController.h" #include "UI/SplashScreen/SplashScreenUIController.h" +#include "UI/LevelSelection/LevelSelectionUIController.h" #include "Instructions/InstructionsScreenUIController.h" #include "UI/Credits/CreditsScreenUIController.h" #include "UI/Interface/IUIController.h" +#include "UI/GameplayUI/GameplayUIController.h" namespace UI { @@ -12,6 +14,8 @@ namespace UI private: SplashScreen::SplashScreenUIController* splash_screen_controller; MainMenu::MainMenuUIController* main_menu_controller; + LevelSelection::LevelSelectionUIController* level_selection_ui_controller; + GameplayUI::GameplayUIController* gameplay_ui_controller; Instructions::InstructionsScreenUIController* instructions_screen_ui_controller; Credits::CreditsScreenUIController* credits_screen_ui_controller; diff --git a/Linked-List-Snake/sfml/include/SFML/Config.hpp b/Linked-List-Snake/sfml/include/SFML/Config.hpp index f4ea4ef3e..3093a7a51 100644 --- a/Linked-List-Snake/sfml/include/SFML/Config.hpp +++ b/Linked-List-Snake/sfml/include/SFML/Config.hpp @@ -31,7 +31,7 @@ //////////////////////////////////////////////////////////// #define SFML_VERSION_MAJOR 2 #define SFML_VERSION_MINOR 6 -#define SFML_VERSION_PATCH 0 +#define SFML_VERSION_PATCH 1 //////////////////////////////////////////////////////////// diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-audio-s-d.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-audio-s-d.pdb new file mode 100644 index 000000000..bbd97a4b6 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-audio-s-d.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-audio-s.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-audio-s.pdb new file mode 100644 index 000000000..bbd97a4b6 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-audio-s.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-audio.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-audio.pdb new file mode 100644 index 000000000..e0cd93576 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-audio.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-graphics-s-d.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-graphics-s-d.pdb new file mode 100644 index 000000000..d187d9728 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-graphics-s-d.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-graphics-s.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-graphics-s.pdb new file mode 100644 index 000000000..d187d9728 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-graphics-s.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-graphics.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-graphics.pdb new file mode 100644 index 000000000..310a084ae Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-graphics.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-main-d.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-main-d.pdb new file mode 100644 index 000000000..432660dd8 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-main-d.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-main-s.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-main-s.pdb new file mode 100644 index 000000000..432660dd8 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-main-s.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-network-s-d.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-network-s-d.pdb new file mode 100644 index 000000000..446f1fb80 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-network-s-d.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-network-s.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-network-s.pdb new file mode 100644 index 000000000..446f1fb80 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-network-s.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-network.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-network.pdb new file mode 100644 index 000000000..fa073311f Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-network.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-system-s-d.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-system-s-d.pdb new file mode 100644 index 000000000..aa448263a Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-system-s-d.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-system-s.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-system-s.pdb new file mode 100644 index 000000000..aa448263a Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-system-s.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-system.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-system.pdb new file mode 100644 index 000000000..ea487f4f0 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-system.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-window-s-d.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-window-s-d.pdb new file mode 100644 index 000000000..98a4c966e Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-window-s-d.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-window-s.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-window-s.pdb new file mode 100644 index 000000000..98a4c966e Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-window-s.pdb differ diff --git a/Linked-List-Snake/sfml/lib/Debug/sfml-window.pdb b/Linked-List-Snake/sfml/lib/Debug/sfml-window.pdb new file mode 100644 index 000000000..1e2442bd4 Binary files /dev/null and b/Linked-List-Snake/sfml/lib/Debug/sfml-window.pdb differ diff --git a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfig.cmake b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfig.cmake index f8b915b60..f28497b6c 100644 --- a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfig.cmake +++ b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfig.cmake @@ -144,5 +144,5 @@ if (NOT SFML_FOUND) endif() if (SFML_FOUND AND NOT SFML_FIND_QUIETLY) - message(STATUS "Found SFML 2.6.0 in ${CMAKE_CURRENT_LIST_DIR}") + message(STATUS "Found SFML 2.6.1 in ${CMAKE_CURRENT_LIST_DIR}") endif() diff --git a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfigVersion.cmake b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfigVersion.cmake index b2208ca9f..25db87605 100644 --- a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfigVersion.cmake +++ b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLConfigVersion.cmake @@ -9,19 +9,19 @@ # The variable CVF_VERSION must be set before calling configure_file(). -set(PACKAGE_VERSION "2.6.0") +set(PACKAGE_VERSION "2.6.1") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() - if("2.6.0" MATCHES "^([0-9]+)\\.") + if("2.6.1" MATCHES "^([0-9]+)\\.") set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") if(NOT CVF_VERSION_MAJOR VERSION_EQUAL 0) string(REGEX REPLACE "^0+" "" CVF_VERSION_MAJOR "${CVF_VERSION_MAJOR}") endif() else() - set(CVF_VERSION_MAJOR "2.6.0") + set(CVF_VERSION_MAJOR "2.6.1") endif() if(PACKAGE_FIND_VERSION_RANGE) diff --git a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLSharedTargets.cmake b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLSharedTargets.cmake index 1c1c3c062..852e1a8d4 100644 --- a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLSharedTargets.cmake +++ b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLSharedTargets.cmake @@ -7,7 +7,7 @@ if(CMAKE_VERSION VERSION_LESS "2.8.3") message(FATAL_ERROR "CMake >= 2.8.3 required") endif() cmake_policy(PUSH) -cmake_policy(VERSION 2.8.3...3.24) +cmake_policy(VERSION 2.8.3...3.25) #---------------------------------------------------------------- # Generated CMake target import file. #---------------------------------------------------------------- diff --git a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLStaticTargets.cmake b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLStaticTargets.cmake index 7257de655..419bb1b85 100644 --- a/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLStaticTargets.cmake +++ b/Linked-List-Snake/sfml/lib/cmake/SFML/SFMLStaticTargets.cmake @@ -7,7 +7,7 @@ if(CMAKE_VERSION VERSION_LESS "2.8.3") message(FATAL_ERROR "CMake >= 2.8.3 required") endif() cmake_policy(PUSH) -cmake_policy(VERSION 2.8.3...3.24) +cmake_policy(VERSION 2.8.3...3.25) #---------------------------------------------------------------- # Generated CMake target import file. #---------------------------------------------------------------- diff --git a/Linked-List-Snake/source/Element/ElementService.cpp b/Linked-List-Snake/source/Element/ElementService.cpp new file mode 100644 index 000000000..feb939196 --- /dev/null +++ b/Linked-List-Snake/source/Element/ElementService.cpp @@ -0,0 +1,64 @@ +#include "Element/ElementService.h" +#include "Level/LevelModel.h" +#include "Global/ServiceLocator.h" +#include "Level/LevelController.h" +#include "Element/Obstacle.h" +#include "Level/LevelModel.h" + +namespace Element +{ + ElementService::ElementService() = default; + + ElementService::~ElementService() = default; + + void ElementService::initialize() { } + + void ElementService::update() + { + for (int i = 0; i < obstacle_list.size(); i++) + { + obstacle_list[i]->update(); + } + } + + void ElementService::render() + { + for (int i = 0; i < obstacle_list.size(); i++) + { + obstacle_list[i]->render(); + } + } + + const void ElementService::spawnElements(std::vector& element_data_list, float cell_width, float cell_height) + { + for (int i = 0; i < element_data_list.size(); i++) + { + switch (element_data_list[i].element_type) + { + case::Element::ElementType::OBSTACLE: + spawnObstacle(element_data_list[i].position, cell_width, cell_height); + break; + } + } + } + + void ElementService::spawnObstacle(sf::Vector2i position, float cell_width, float cell_height) + { + Obstacle* obstacle = new Obstacle(); + + obstacle->initialize(position, cell_width, cell_height); + obstacle_list.push_back(obstacle); + } + + std::vector ElementService::getElementsPositionList() + { + std::vector elements_position_list; + + for (int i = 0; i < obstacle_list.size(); i++) + { + elements_position_list.push_back(obstacle_list[i]->getObstaclePosition()); + } + + return elements_position_list; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Element/Obstacle.cpp b/Linked-List-Snake/source/Element/Obstacle.cpp new file mode 100644 index 000000000..50d553df5 --- /dev/null +++ b/Linked-List-Snake/source/Element/Obstacle.cpp @@ -0,0 +1,61 @@ +#include "Element/Obstacle.h" +#include "Global/ServiceLocator.h" +#include "Level/LevelView.h" +#include "Global/Config.h" + +namespace Element +{ + using namespace Global; + using namespace Level; + using namespace UI::UIElement; + + Obstacle::Obstacle() + { + obstacle_image = new ImageView(); + } + + Obstacle::~Obstacle() + { + delete (obstacle_image); + } + + void Obstacle::initialize(sf::Vector2i grid_pos, float width, float height) + { + grid_position = grid_pos; + cell_width = width; + cell_height = height; + + initializeObstacleImage(); + } + + void Obstacle::initializeObstacleImage() + { + sf::Vector2f screen_position = getObstacleImagePosition(); + obstacle_image->initialize(Config::obstacle_texture_path, cell_width, cell_height, screen_position); + + obstacle_image->show(); + } + + void Obstacle::update() + { + obstacle_image->update(); + } + + void Obstacle::render() + { + obstacle_image->render(); + } + + sf::Vector2f Obstacle::getObstacleImagePosition() + { + float screen_position_x = LevelView::border_offset_left + (cell_width * grid_position.x); + float screen_position_y = LevelView::border_offset_top + (cell_height * grid_position.y); + + return sf::Vector2f(screen_position_x, screen_position_y); + } + + sf::Vector2i Obstacle::getObstaclePosition() + { + return grid_position; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Food/FoodItem.cpp b/Linked-List-Snake/source/Food/FoodItem.cpp new file mode 100644 index 000000000..209c04096 --- /dev/null +++ b/Linked-List-Snake/source/Food/FoodItem.cpp @@ -0,0 +1,94 @@ +#include "Food/FoodItem.h" +#include "Global/ServiceLocator.h" +#include "Level/LevelView.h" +#include "Global/Config.h" +#include "Food/FoodType.h" + +namespace Food +{ + using namespace Global; + using namespace Level; + using namespace UI::UIElement; + + FoodItem::FoodItem() + { + food_image = new ImageView(); + } + + FoodItem::~FoodItem() + { + delete (food_image); + } + + void FoodItem::initialize(sf::Vector2i grid_pos, float width, float height, FoodType type) + { + grid_position = grid_pos; + cell_width = width; + cell_height = height; + food_type = type; + + initializeFoodImage(); + } + + void FoodItem::initializeFoodImage() + { + sf::Vector2f screen_position = getFoodImagePosition(); + sf::String food_texture_path = getFoodTexturePath(); + + food_image->initialize(food_texture_path, cell_width, cell_height, screen_position); + food_image->show(); + } + + sf::String FoodItem::getFoodTexturePath() + { + switch (food_type) + { + case Food::FoodType::APPLE: + return Config::apple_texture_path; + + case Food::FoodType::MANGO: + return Config::mango_texture_path; + + case Food::FoodType::ORANGE: + return Config::orange_texture_path; + + case Food::FoodType::PIZZA: + return Config::pizza_texture_path; + + case Food::FoodType::BURGER: + return Config::burger_texture_path; + + case Food::FoodType::CHEESE: + return Config::cheese_texture_path; + + case Food::FoodType::POISION: + return Config::poision_texture_path; + + case Food::FoodType::ALCOHOL: + return Config::alcohol_texture_path; + } + } + + void FoodItem::update() + { + food_image->update(); + } + + void FoodItem::render() + { + food_image->render(); + } + + FoodType FoodItem::getFoodType() + { + return food_type; + } + + sf::Vector2f FoodItem::getFoodImagePosition() + { + float screen_position_x = LevelView::border_offset_left + (cell_width * grid_position.x); + float screen_position_y = LevelView::border_offset_top + (cell_height * grid_position.y); + + return sf::Vector2f(screen_position_x, screen_position_y); + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Food/FoodService.cpp b/Linked-List-Snake/source/Food/FoodService.cpp new file mode 100644 index 000000000..c5a7b12ea --- /dev/null +++ b/Linked-List-Snake/source/Food/FoodService.cpp @@ -0,0 +1,136 @@ +#include "Food/FoodService.h" +#include "Global/ServiceLocator.h" +#include "Food/FoodItem.h" +#include "Level/LevelModel.h" +#include "Player/PlayerService.h" + +namespace Food +{ + using namespace Time; + using namespace Global; + using namespace Level; + using namespace Player; + + FoodService::FoodService() : random_engine(random_device()) + { + current_food_item = nullptr; + } + + FoodService::~FoodService() + { + destroyFood(); + } + + void FoodService::initialize() + { + elapsed_duration = spawn_duration; + } + + void FoodService::update() + { + if (current_spawning_status == FoodSpawningStatus::ACTIVE) + { + updateElapsedDuration(); + handleFoodSpawning(); + } + + if (current_food_item) current_food_item->update(); + } + + void FoodService::render() + { + if (current_food_item) current_food_item->render(); + } + + void FoodService::startFoodSpawning() + { + current_spawning_status = FoodSpawningStatus::ACTIVE; + + cell_width = ServiceLocator::getInstance()->getLevelService()->getCellWidth(); + cell_height = ServiceLocator::getInstance()->getLevelService()->getCellHeight(); + } + + void FoodService::stopFoodSpawning() + { + current_spawning_status = FoodSpawningStatus::IN_ACTIVE; + destroyFood(); + reset(); + } + + FoodItem* FoodService::createFood(sf::Vector2i position, FoodType type) + { + FoodItem* food = new FoodItem(); + food->initialize(position, cell_width, cell_height, type); + return food; + } + + void FoodService::spawnFood() + { + current_food_item = createFood(getValidSpawnPosition(), getRandomFoodType()); + } + + sf::Vector2i FoodService::getValidSpawnPosition() + { + std::vector player_position_data = ServiceLocator::getInstance()->getPlayerService()->getCurrentSnakePositionList(); + std::vector elements_position_data = ServiceLocator::getInstance()->getElementService()->getElementsPositionList(); + sf::Vector2i spawn_position; + + do spawn_position = getRandomPosition(); + while (!isValidPosition(player_position_data, spawn_position) || !isValidPosition(elements_position_data, spawn_position)); + + return spawn_position; + } + + sf::Vector2i FoodService::getRandomPosition() + { + // Co-ordinate distribution i.e. selecting random position for food. + std::uniform_int_distribution x_distribution(0, LevelModel::number_of_columns - 1); + std::uniform_int_distribution y_distribution(0, LevelModel::number_of_rows - 1); + + int x_position = static_cast(x_distribution(random_engine)); + int y_position = static_cast(y_distribution(random_engine)); + + return sf::Vector2i(x_position, y_position); + } + + FoodType FoodService::getRandomFoodType() + { + std::uniform_int_distribution distribution(0, FoodItem::number_of_foods - 1); + + return static_cast(distribution(random_engine)); + } + + bool FoodService::isValidPosition(std::vector position_data, sf::Vector2i food_position) + { + for (int i = 0; i < position_data.size(); i++) + { + if (food_position == position_data[i]) return false; + } + return true; + } + + void FoodService::destroyFood() + { + if (current_food_item) delete(current_food_item); + } + + void FoodService::updateElapsedDuration() + { + elapsed_duration += ServiceLocator::getInstance()->getTimeService()->getDeltaTime(); + } + + void FoodService::handleFoodSpawning() + { + if (elapsed_duration >= spawn_duration) + { + destroyFood(); + reset(); + spawnFood(); + } + } + + void FoodService::reset() + { + elapsed_duration = 0.f; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Global/ServiceLocator.cpp b/Linked-List-Snake/source/Global/ServiceLocator.cpp index 84c99f938..2717749b6 100644 --- a/Linked-List-Snake/source/Global/ServiceLocator.cpp +++ b/Linked-List-Snake/source/Global/ServiceLocator.cpp @@ -1,18 +1,28 @@ #include "Global/ServiceLocator.h" +#include "Main/GameService.h" namespace Global { using namespace Graphics; using namespace Event; using namespace Sound; + using namespace Level; using namespace UI; + using namespace Main; using namespace Time; + using namespace Player; + using namespace Food; + using namespace Element; ServiceLocator::ServiceLocator() { graphic_service = nullptr; event_service = nullptr; sound_service = nullptr; + level_service = nullptr; + element_service = nullptr; + player_service = nullptr; + food_service = nullptr; ui_service = nullptr; time_service = nullptr; @@ -26,6 +36,10 @@ namespace Global event_service = new EventService(); graphic_service = new GraphicService(); sound_service = new SoundService(); + level_service = new LevelService(); + element_service = new ElementService(); + player_service = new PlayerService(); + food_service = new FoodService(); ui_service = new UIService(); time_service = new TimeService(); } @@ -35,6 +49,10 @@ namespace Global graphic_service->initialize(); sound_service->initialize(); event_service->initialize(); + level_service->initialize(); + element_service->initialize(); + player_service->initialize(); + food_service->initialize(); ui_service->initialize(); time_service->initialize(); } @@ -43,19 +61,41 @@ namespace Global { graphic_service->update(); event_service->update(); - ui_service->update(); time_service->update(); + + if (GameService::getGameState() == GameState::GAMEPLAY) + { + level_service->update(); + element_service->update(); + player_service->update(); + food_service->update(); + } + + ui_service->update(); } void ServiceLocator::render() { - ui_service->render(); graphic_service->render(); + + if (GameService::getGameState() == GameState::GAMEPLAY) + { + level_service->render(); + element_service->render(); + player_service->render(); + food_service->render(); + } + + ui_service->render(); } void ServiceLocator::clearAllServices() { delete(ui_service); + delete(food_service); + delete(player_service); + delete(element_service); + delete(level_service); delete(graphic_service); delete(sound_service); delete(event_service); @@ -74,9 +114,17 @@ namespace Global SoundService* ServiceLocator::getSoundService() { return sound_service; } - UIService* ServiceLocator::getUIService() { return ui_service; } + Level::LevelService* ServiceLocator::getLevelService() { return level_service; } + + Element::ElementService* ServiceLocator::getElementService() { return element_service; } Time::TimeService* ServiceLocator::getTimeService() { return time_service; } + Player::PlayerService* ServiceLocator::getPlayerService() { return player_service; } + + UIService* ServiceLocator::getUIService() { return ui_service; } + + Food::FoodService* ServiceLocator::getFoodService() { return food_service; } + void ServiceLocator::deleteServiceLocator() { delete(this); } } \ No newline at end of file diff --git a/Linked-List-Snake/source/Level/LevelController.cpp b/Linked-List-Snake/source/Level/LevelController.cpp new file mode 100644 index 000000000..9d77a86a1 --- /dev/null +++ b/Linked-List-Snake/source/Level/LevelController.cpp @@ -0,0 +1,51 @@ +#include "Level/LevelController.h" +#include "Level/LevelModel.h" +#include "Level/LevelView.h" + +namespace Level +{ + using namespace Element; + + LevelController::LevelController() + { + level_model = new LevelModel(); + level_view = new LevelView(); + } + + LevelController::~LevelController() + { + delete level_model; + delete level_view; + } + + void LevelController::initialize() + { + level_view->initialize(); + level_model->initialize(level_view->getGridWidth(), level_view->getGridHeight()); + } + + void LevelController::update() + { + level_view->update(); + } + + void LevelController::render() + { + level_view->render(); + } + + float LevelController::getCellWidth() + { + return level_model->getCellWidth(); + } + + float LevelController::getCellHeight() + { + return level_model->getCellHeight(); + } + + const std::vector& LevelController::getElementDataList(int level_to_load) + { + return level_model->getElementDataList(level_to_load); + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Level/LevelModel.cpp b/Linked-List-Snake/source/Level/LevelModel.cpp new file mode 100644 index 000000000..43d5c3e60 --- /dev/null +++ b/Linked-List-Snake/source/Level/LevelModel.cpp @@ -0,0 +1,41 @@ +#include "Level/LevelModel.h" +#include "Level/LevelService.h" +#include "Element/ElementService.h" + +namespace Level +{ + using namespace Element; + + LevelModel::LevelModel() = default; + + LevelModel::~LevelModel() = default; + + void LevelModel::initialize(int width, int height) + { + cell_width = static_cast(width) / static_cast(number_of_columns); + cell_height = static_cast(height) / static_cast(number_of_rows); + + initializeLevelData(); + } + + void LevelModel::initializeLevelData() + { + level_configurations.push_back(LevelData(Level::LevelNumber::ONE, &level_one_element_list)); + level_configurations.push_back(LevelData(Level::LevelNumber::TWO, &level_two_element_list)); + } + + const std::vector& LevelModel::getElementDataList(int level_to_load) + { + return *level_configurations[level_to_load].element_data_list; + } + + float LevelModel::getCellWidth() + { + return cell_width; + } + + float LevelModel::getCellHeight() + { + return cell_height; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Level/LevelService.cpp b/Linked-List-Snake/source/Level/LevelService.cpp new file mode 100644 index 000000000..8dcab1a69 --- /dev/null +++ b/Linked-List-Snake/source/Level/LevelService.cpp @@ -0,0 +1,90 @@ +#include "Level/LevelService.h" +#include "Level/LevelController.h" +#include "Global/ServiceLocator.h" +#include "Element/ElementService.h" +#include "Food/FoodService.h" +#include "Level/LevelModel.h" + +namespace Level +{ + using namespace Global; + using namespace Element; + using namespace Food; + + LevelService::LevelService() + { + level_controller = nullptr; + + createLevelController(); + } + + LevelService::~LevelService() + { + destroy(); + } + + void LevelService::createLevelController() + { + level_controller = new LevelController(); + } + + void LevelService::initialize() + { + level_controller->initialize(); + } + + void LevelService::update() + { + level_controller->update(); + } + + void LevelService::render() + { + level_controller->render(); + } + + void LevelService::createLevel(LevelNumber level_to_load) + { + current_level = level_to_load; + spawnLevelElements(level_to_load); + spawnPlayer(); + spawnFood(); + } + + float LevelService::getCellWidth() + { + return level_controller->getCellWidth(); + } + + float LevelService::getCellHeight() + { + return level_controller->getCellHeight(); + } + + void LevelService::spawnPlayer() + { + ServiceLocator::getInstance()->getPlayerService()->spawnPlayer(); + } + + void LevelService::spawnLevelElements(LevelNumber level_to_load) + { + float cell_width = level_controller->getCellWidth(); + float cell_height = level_controller->getCellHeight(); + + std::vector element_data_list = level_controller->getElementDataList((int)level_to_load); + ServiceLocator::getInstance()->getElementService()->spawnElements(element_data_list, cell_width, cell_height); + } + + void LevelService::spawnFood() + { + float cell_width = level_controller->getCellWidth(); + float cell_height = level_controller->getCellHeight(); + + ServiceLocator::getInstance()->getFoodService()->startFoodSpawning(); + } + + void LevelService::destroy() + { + delete level_controller; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Level/LevelView.cpp b/Linked-List-Snake/source/Level/LevelView.cpp new file mode 100644 index 000000000..93a7e35e7 --- /dev/null +++ b/Linked-List-Snake/source/Level/LevelView.cpp @@ -0,0 +1,90 @@ +#include "Level/LevelView.h" +#include "Global/ServiceLocator.h" +#include "Graphics/GraphicService.h" +#include "UI/UIElement/RectangleShapeView.h" + +namespace Level +{ + using namespace UI::UIElement; + using namespace Global; + + LevelView::LevelView() + { + createViews(); + } + + LevelView::~LevelView() + { + destroy(); + } + + void LevelView::createViews() + { + background_rectangle = new RectangleShapeView(); + border_rectangle = new RectangleShapeView(); + } + + void LevelView::initialize() + { + initializeBackground(); + calculateGridExtents(); + initializeBorder(); + } + + void LevelView::initializeBackground() + { + sf::RenderWindow* game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); + + sf::Vector2f background_size = sf::Vector2f(game_window->getSize().x, game_window->getSize().y); + + background_rectangle->initialize(background_size, sf::Vector2f(0, 0), 0, background_color); + background_rectangle->show(); + } + + void LevelView::initializeBorder() + { + sf::RenderWindow* game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); + + sf::Vector2f border_size = sf::Vector2f(grid_width, grid_height); + sf::Vector2f border_position = sf::Vector2f(border_offset_left, border_offset_top); + + border_rectangle->initialize(border_size, border_position, border_thickness, sf::Color::Transparent, border_color); + border_rectangle->show(); + } + + void LevelView::calculateGridExtents() + { + sf::RenderWindow* game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); + + grid_width = game_window->getSize().x - 2 * border_offset_left; + grid_height = game_window->getSize().y - 2 * border_offset_top; + } + + void LevelView::destroy() + { + delete (background_rectangle); + delete (border_rectangle); + } + + void LevelView::update() + { + background_rectangle->update(); + border_rectangle->update(); + } + + void LevelView::render() + { + background_rectangle->render(); + border_rectangle->render(); + } + + float LevelView::getGridWidth() + { + return grid_width; + } + + float LevelView::getGridHeight() + { + return grid_height; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/LinkedList/SingleLinkedList.cpp b/Linked-List-Snake/source/LinkedList/SingleLinkedList.cpp new file mode 100644 index 000000000..093fd4c76 --- /dev/null +++ b/Linked-List-Snake/source/LinkedList/SingleLinkedList.cpp @@ -0,0 +1,166 @@ +#include "LinkedList/SingleLinkedList.h" +#include "Player/BodyPart.h" +#include "Level/LevelView.h" +#include + +namespace LinkedList +{ + SingleLinkedList::SingleLinkedList() + { + head_node = nullptr; + } + + SingleLinkedList::~SingleLinkedList() = default; + + void SingleLinkedList::initialize(float width, float height, sf::Vector2i position, Direction direction) + { + node_width = width; + node_height = height; + default_position = position; + default_direction = direction; + } + + void SingleLinkedList::render() + { + Node* cur_node = head_node; + + while (cur_node != nullptr) + { + cur_node->body_part.render(); + cur_node = cur_node->next; + } + } + + void SingleLinkedList::updateNodePosition() + { + Node* cur_node = head_node; + + while (cur_node != nullptr) + { + cur_node->body_part.updatePosition(); + cur_node = cur_node->next; + } + } + + void SingleLinkedList::updateNodeDirection(Direction direction_to_set) + { + Node* cur_node = head_node; + + while (cur_node != nullptr) + { + Direction previous_direction = cur_node->body_part.getDirection(); + cur_node->body_part.setDirection(direction_to_set); + direction_to_set = previous_direction; + cur_node = cur_node->next; + } + } + + bool SingleLinkedList::processNodeCollision() + { + if (head_node == nullptr) return false; + + sf::Vector2i predicted_position = head_node->body_part.getNextPosition(); + + Node* cur_node = head_node->next; + while (cur_node != nullptr) + { + if (cur_node->body_part.getNextPosition() == predicted_position) + { + return true; + } + + cur_node = cur_node->next; + } + + return false; + } + + void SingleLinkedList::insertNodeAtTail() + { + Node* new_node = createNode(); + Node* cur_node = head_node; + + if (cur_node == nullptr) //If there is no head, then create a new head node + { + head_node = new_node; + new_node->body_part.initialize(node_width, node_height, default_position, default_direction); + return; + } + + while (cur_node->next != nullptr) + { + cur_node = cur_node->next; + } + + cur_node->next = new_node; + new_node->body_part.initialize(node_width, node_height, getNewNodePosition(cur_node), cur_node->body_part.getDirection()); + } + + void SingleLinkedList::removeNodeAtHead() + { + Node* cur_node = head_node; + head_node = head_node->next; + + cur_node->next = nullptr; + delete (cur_node); + } + + void SingleLinkedList::removeAllNodes() + { + if (head_node == nullptr) return; + + while (head_node != nullptr) + { + removeNodeAtHead(); + } + } + + Node* SingleLinkedList::createNode() + { + return new Node(); + } + + sf::Vector2i SingleLinkedList::getNewNodePosition(Node* reference_node) + { + Direction reference_direction = reference_node->body_part.getDirection(); + sf::Vector2i reference_position = reference_node->body_part.getPosition(); + + switch (reference_direction) + { + case Direction::UP: + return sf::Vector2i(reference_position.x, reference_position.y - 1); + break; + case Direction::DOWN: + return sf::Vector2i(reference_position.x, reference_position.y + 1); + break; + case Direction::LEFT: + return sf::Vector2i(reference_position.x + 1, reference_position.y); + break; + case Direction::RIGHT: + return sf::Vector2i(reference_position.x - 1, reference_position.y); + break; + } + + return default_position; + } + + Node* SingleLinkedList::getHeadNode() + { + return head_node; + } + + std::vector SingleLinkedList::getNodesPositionList() + { + std::vector nodes_position_list; + + Node* cur_node = head_node; + + while (cur_node != nullptr) + { + nodes_position_list.push_back(cur_node->body_part.getPosition()); + cur_node = cur_node->next; + } + + return nodes_position_list; + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Player/BodyPart.cpp b/Linked-List-Snake/source/Player/BodyPart.cpp new file mode 100644 index 000000000..c5f24b07a --- /dev/null +++ b/Linked-List-Snake/source/Player/BodyPart.cpp @@ -0,0 +1,138 @@ +#include "Player/BodyPart.h" +#include "Global/ServiceLocator.h" +#include "Level/LevelView.h" +#include "Level/LevelModel.h" +#include "Global/Config.h" + +namespace Player +{ + using namespace Global; + using namespace Level; + using namespace UI::UIElement; + + BodyPart::BodyPart() + { + grid_position = sf::Vector2i(0, 0); + createBodyPartImage(); + } + + BodyPart::~BodyPart() + { + destroy(); + } + + void BodyPart::initialize(float width, float height, sf::Vector2i pos, Direction dir) + { + bodypart_width = width; + bodypart_height = height; + direction = dir; + grid_position = pos; + + initializeBodyPartImage(); + } + + void BodyPart::createBodyPartImage() + { + bodypart_image = new ImageView(); + } + + void BodyPart::initializeBodyPartImage() + { + bodypart_image->initialize(Config::snake_body_texture_path, bodypart_width, bodypart_height, getBodyPartScreenPosition()); + bodypart_image->setOriginAtCentre(); + } + + void BodyPart::updatePosition() + { + grid_position = getNextPosition(); + + bodypart_image->setPosition(getBodyPartScreenPosition()); + bodypart_image->setRotation(getRotationAngle()); + bodypart_image->update(); + } + + sf::Vector2f BodyPart::getBodyPartScreenPosition() + { + float x_screen_position = LevelView::border_offset_left + (grid_position.x * bodypart_width) + (bodypart_width / 2); + float y_screen_position = LevelView::border_offset_top + (grid_position.y * bodypart_height) + (bodypart_height / 2); + + return sf::Vector2f(x_screen_position, y_screen_position); + } + + void BodyPart::render() + { + bodypart_image->render(); + } + + sf::Vector2i BodyPart::getNextPosition() + { + switch (direction) + { + case Direction::UP: + return getNextPositionUp(); + case Direction::DOWN: + return getNextPositionDown(); + case Direction::RIGHT: + return getNextPositionRight(); + case Direction::LEFT: + return getNextPositionLeft(); + default: + return grid_position; + } + } + + sf::Vector2i BodyPart::getNextPositionDown() + { + return sf::Vector2i(grid_position.x, (grid_position.y + 1) % (LevelModel::number_of_rows)); + } + + sf::Vector2i BodyPart::getNextPositionUp() + { + return sf::Vector2i(grid_position.x, (grid_position.y - 1 + (LevelModel::number_of_rows)) % (LevelModel::number_of_rows)); + } + + sf::Vector2i BodyPart::getNextPositionRight() + { + return sf::Vector2i((grid_position.x + 1) % (LevelModel::number_of_columns), grid_position.y); + } + + sf::Vector2i BodyPart::getNextPositionLeft() + { + return sf::Vector2i((grid_position.x - 1 + LevelModel::number_of_columns) % (LevelModel::number_of_columns), grid_position.y); + } + + float BodyPart::getRotationAngle() + { + switch (direction) + { + case Direction::UP: + return 270.f; + case Direction::DOWN: + return 90.f; + case Direction::RIGHT: + return 0; + case Direction::LEFT: + return 180.f; + } + } + + Direction BodyPart::getDirection() + { + return direction; + } + + void BodyPart::setDirection(Direction new_direction) + { + direction = new_direction; + } + + sf::Vector2i BodyPart::getPosition() + { + return grid_position; + } + + void BodyPart::destroy() + { + delete (bodypart_image); + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Player/PlayerService.cpp b/Linked-List-Snake/source/Player/PlayerService.cpp new file mode 100644 index 000000000..8a979f1a4 --- /dev/null +++ b/Linked-List-Snake/source/Player/PlayerService.cpp @@ -0,0 +1,52 @@ +#include "Player/PlayerService.h" +#include "Player/SnakeController.h" + +namespace Player +{ + PlayerService::PlayerService() + { + snake_controller = nullptr; + + createController(); + } + + PlayerService::~PlayerService() + { + destroy(); + } + + void PlayerService::createController() + { + snake_controller = new SnakeController(); + } + + void PlayerService::initialize() + { + snake_controller->initialize(); + } + + void PlayerService::update() + { + snake_controller->update(); + } + + void PlayerService::render() + { + snake_controller->render(); + } + + void PlayerService::spawnPlayer() + { + snake_controller->spawnSnake(); + } + + std::vector PlayerService::getCurrentSnakePositionList() + { + return snake_controller->getCurrentSnakePositionList(); + } + + void PlayerService::destroy() + { + delete (snake_controller); + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/Player/SnakeController.cpp b/Linked-List-Snake/source/Player/SnakeController.cpp new file mode 100644 index 000000000..9f2f49464 --- /dev/null +++ b/Linked-List-Snake/source/Player/SnakeController.cpp @@ -0,0 +1,177 @@ +#include "Player/SnakeController.h" +#include "Global/ServiceLocator.h" +#include "Level/LevelService.h" +#include "Event/EventService.h" +#include +#include + +namespace Player +{ + using namespace LinkedList; + using namespace Global; + using namespace Level; + using namespace Event; + using namespace Time; + + SnakeController::SnakeController() + { + single_linked_list = nullptr; + createLinkedList(); + } + + SnakeController::~SnakeController() + { + destroy(); + } + + void SnakeController::createLinkedList() + { + single_linked_list = new SingleLinkedList(); + } + + void SnakeController::initialize() + { + float width = ServiceLocator::getInstance()->getLevelService()->getCellWidth(); + float height = ServiceLocator::getInstance()->getLevelService()->getCellHeight(); + + reset(); + single_linked_list->initialize(width, height, default_position, default_direction); + } + + void SnakeController::update() + { + switch (current_snake_state) + { + case SnakeState::ALIVE: + processPlayerInput(); + delayedUpdate(); + break; + + case SnakeState::DEAD: + handleRestart(); + break; + } + } + + void SnakeController::render() + { + single_linked_list->render(); + } + + void SnakeController::processPlayerInput() + { + if (current_input_state == InputState::PROCESSING) + return; + + EventService* event_service = ServiceLocator::getInstance()->getEventService(); + + if (event_service->pressedUpArrowKey() && current_snake_direction != Direction::DOWN) + { + current_snake_direction = Direction::UP; + current_input_state = InputState::PROCESSING; + } + else if (event_service->pressedDownArrowKey() && current_snake_direction != Direction::UP) + { + current_snake_direction = Direction::DOWN; + current_input_state = InputState::PROCESSING; + } + else if (event_service->pressedLeftArrowKey() && current_snake_direction != Direction::RIGHT) + { + current_snake_direction = Direction::LEFT; + current_input_state = InputState::PROCESSING; + } + else if (event_service->pressedRightArrowKey() && current_snake_direction != Direction::LEFT) + { + current_snake_direction = Direction::RIGHT; + current_input_state = InputState::PROCESSING; + } + } + + void SnakeController::delayedUpdate() + { + elapsed_duration += ServiceLocator::getInstance()->getTimeService()->getDeltaTime(); + + if (elapsed_duration >= movement_frame_duration) + { + elapsed_duration = 0.f; + updateSnakeDirection(); + processSnakeCollision(); + + if(current_snake_state != SnakeState::DEAD) + moveSnake(); + current_input_state = InputState::WAITING; + } + } + + void SnakeController::updateSnakeDirection() + { + single_linked_list->updateNodeDirection(current_snake_direction); + } + + void SnakeController::moveSnake() + { + single_linked_list->updateNodePosition(); + } + + void SnakeController::processSnakeCollision() + { + if (single_linked_list->processNodeCollision()) + { + current_snake_state = SnakeState::DEAD; + } + } + + void SnakeController::handleRestart() + { + restart_counter += ServiceLocator::getInstance()->getTimeService()->getDeltaTime(); + + if (restart_counter >= restart_duration) + { + respawnSnake(); + } + } + + void SnakeController::spawnSnake() + { + for (int i = 0; i < initial_snake_length; i++) + { + single_linked_list->insertNodeAtTail(); + } + } + + void SnakeController::reset() + { + current_snake_state = SnakeState::ALIVE; + current_snake_direction = default_direction; + elapsed_duration = 0.f; + restart_counter = 0.f; + current_input_state = InputState::WAITING; + } + + void SnakeController::respawnSnake() + { + single_linked_list->removeAllNodes(); + reset(); + spawnSnake(); + } + + void SnakeController::setSnakeState(SnakeState state) + { + current_snake_state = state; + } + + SnakeState SnakeController::getSnakeState() + { + return current_snake_state; + } + + std::vector SnakeController::getCurrentSnakePositionList() + { + return single_linked_list->getNodesPositionList(); + } + + void SnakeController::destroy() + { + delete (single_linked_list); + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/UI/GameplayUI/GameplayUIController.cpp b/Linked-List-Snake/source/UI/GameplayUI/GameplayUIController.cpp new file mode 100644 index 000000000..56cb3f55a --- /dev/null +++ b/Linked-List-Snake/source/UI/GameplayUI/GameplayUIController.cpp @@ -0,0 +1,91 @@ +#include "UI/GameplayUI/GameplayUIController.h" +#include "Main/GameService.h" +#include "Graphics/GraphicService.h" +#include "Sound/SoundService.h" +#include "Event/EventService.h" +#include "Global/Config.h" + +namespace UI +{ + namespace GameplayUI + { + using namespace Global; + using namespace Event; + using namespace Sound; + using namespace Main; + using namespace Graphics; + using namespace UI::UIElement; + + GameplayUIController::GameplayUIController() + { + createTexts(); + } + + GameplayUIController::~GameplayUIController() + { + destroy(); + } + + void GameplayUIController::initialize() + { + initializeTexts(); + } + + void GameplayUIController::createTexts() + { + level_number_text = new TextView(); + score_text = new TextView(); + time_complexity_text = new TextView(); + } + + void GameplayUIController::initializeTexts() + { + initializeLevelNumberText(); + initializeScoreText(); + initializeTimeComplexityText(); + } + + void GameplayUIController::initializeLevelNumberText() + { + level_number_text->initialize("Level : 1", sf::Vector2f(level_number_text_x_position, text_y_position), FontType::BUBBLE_BOBBLE, font_size, sf::Color::Black); + } + + void GameplayUIController::initializeScoreText() + { + score_text->initialize("Score : 0", sf::Vector2f(score_text_x_position, text_y_position), FontType::BUBBLE_BOBBLE, font_size, sf::Color::Black); + } + + void GameplayUIController::initializeTimeComplexityText() + { + time_complexity_text->initialize("Time Complexity : O(1)", sf::Vector2f(time_complexity_text_x_position, text_y_position), FontType::BUBBLE_BOBBLE, font_size, sf::Color::Black); + } + + void GameplayUIController::update() + { + level_number_text->update(); + score_text->update(); + time_complexity_text->update(); + } + + void GameplayUIController::render() + { + level_number_text->render(); + score_text->render(); + time_complexity_text->render(); + } + + void GameplayUIController::show() + { + level_number_text->show(); + score_text->show(); + time_complexity_text->show(); + } + + void GameplayUIController::destroy() + { + delete (level_number_text); + delete (score_text); + delete (time_complexity_text); + } + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/UI/LevelSelection/LevelSelectionUIController.cpp b/Linked-List-Snake/source/UI/LevelSelection/LevelSelectionUIController.cpp new file mode 100644 index 000000000..b746ba26e --- /dev/null +++ b/Linked-List-Snake/source/UI/LevelSelection/LevelSelectionUIController.cpp @@ -0,0 +1,133 @@ +#include "UI/LevelSelection/LevelSelectionUIController.h" +#include "Main/GameService.h" +#include "Graphics/GraphicService.h" +#include "Sound/SoundService.h" +#include "Event/EventService.h" +#include "UI/UIElement/ButtonView.h" +#include "UI/UIElement/ImageView.h" +#include "Global/Config.h" +#include "Level/LevelService.h" + +namespace UI +{ + using namespace UIElement; + using namespace Global; + using namespace Event; + using namespace Sound; + using namespace Main; + + namespace LevelSelection + { + LevelSelectionUIController::LevelSelectionUIController() + { + createButtons(); + createImage(); + } + + LevelSelectionUIController::~LevelSelectionUIController() + { + destroy(); + } + + void LevelSelectionUIController::initialize() + { + initializeBackgroundImage(); + initializeButtons(); + registerButtonCallback(); + } + + void LevelSelectionUIController::createImage() + { + background_image = new ImageView(); + } + + void LevelSelectionUIController::createButtons() + { + level_one_button = new ButtonView(); + level_two_button = new ButtonView(); + menu_button = new ButtonView(); + } + + void LevelSelectionUIController::initializeBackgroundImage() + { + sf::RenderWindow* game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); + + background_image->initialize(Config::background_texture_path, game_window->getSize().x, game_window->getSize().y, sf::Vector2f(0, 0)); + background_image->setImageAlpha(background_alpha); + } + + void LevelSelectionUIController::initializeButtons() + { + float x_position = calculateLeftOffsetForButton(); + + level_one_button->initialize("Level One Button", Config::level_one_button_texture_path, button_width, button_height, sf::Vector2f(x_position, level_one_button_y_position)); + level_two_button->initialize("Level Two Button", Config::level_two_button_texture_path, button_width, button_height, sf::Vector2f(x_position, level_two_button_y_position)); + menu_button->initialize("Menu Button", Config::menu_button_texture_path, button_width, button_height, sf::Vector2f(x_position, menu_button_y_position)); + } + + void LevelSelectionUIController::registerButtonCallback() + { + level_one_button->registerCallbackFuntion(std::bind(&LevelSelectionUIController::levelOneButtonCallback, this)); + level_two_button->registerCallbackFuntion(std::bind(&LevelSelectionUIController::levelTwoButtonCallback, this)); + menu_button->registerCallbackFuntion(std::bind(&LevelSelectionUIController::menuButtonCallback, this)); + } + + float LevelSelectionUIController::calculateLeftOffsetForButton() + { + sf::RenderWindow* game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); + return (static_cast(game_window->getSize().x) / 2) - button_width / 2; + } + + void LevelSelectionUIController::levelOneButtonCallback() + { + ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK); + GameService::setGameState(GameState::GAMEPLAY); + ServiceLocator::getInstance()->getLevelService()->createLevel(Level::LevelNumber::ONE); + } + + void LevelSelectionUIController::levelTwoButtonCallback() + { + ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK); + GameService::setGameState(GameState::GAMEPLAY); + ServiceLocator::getInstance()->getLevelService()->createLevel(Level::LevelNumber::TWO); + } + + void LevelSelectionUIController::menuButtonCallback() + { + ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK); + GameService::setGameState(GameState::MAIN_MENU); + } + + void LevelSelectionUIController::update() + { + background_image->update(); + level_one_button->update(); + level_two_button->update(); + menu_button->update(); + } + + void LevelSelectionUIController::render() + { + background_image->render(); + level_one_button->render(); + level_two_button->render(); + menu_button->render(); + } + + void LevelSelectionUIController::show() + { + background_image->show(); + level_one_button->show(); + level_two_button->show(); + menu_button->show(); + } + + void LevelSelectionUIController::destroy() + { + delete (background_image); + delete (level_one_button); + delete (level_two_button); + delete (menu_button); + } + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/UI/MainMenu/MainMenuUIController.cpp b/Linked-List-Snake/source/UI/MainMenu/MainMenuUIController.cpp index 506483da7..e8326dca4 100644 --- a/Linked-List-Snake/source/UI/MainMenu/MainMenuUIController.cpp +++ b/Linked-List-Snake/source/UI/MainMenu/MainMenuUIController.cpp @@ -73,8 +73,8 @@ namespace UI void MainMenuUIController::playButtonCallback() { - // GameState will change to gameplay state. ServiceLocator::getInstance()->getSoundService()->playSound(SoundType::BUTTON_CLICK); + GameService::setGameState(GameState::LEVEL_SELECTION); } void MainMenuUIController::instructionsButtonCallback() diff --git a/Linked-List-Snake/source/UI/UIElement/RectangleShapeView.cpp b/Linked-List-Snake/source/UI/UIElement/RectangleShapeView.cpp new file mode 100644 index 000000000..d598e28b7 --- /dev/null +++ b/Linked-List-Snake/source/UI/UIElement/RectangleShapeView.cpp @@ -0,0 +1,63 @@ +#include "UI/UIElement/RectangleShapeView.h" + +namespace UI +{ + namespace UIElement + { + RectangleShapeView::RectangleShapeView() = default; + + RectangleShapeView::~RectangleShapeView() = default; + + void RectangleShapeView::initialize(sf::Vector2f rectangle_size, sf::Vector2f rectangle_position, int outline_thickness, sf::Color fill_color, sf::Color outline_color) + { + UIView::initialize(); + + setSize(rectangle_size); + setPosition(rectangle_position); + setOutlineThickness(outline_thickness); + setFillColor(fill_color); + setOutlineColor(outline_color); + } + + void RectangleShapeView::update() + { + UIView::update(); + } + + void RectangleShapeView::render() + { + UIView::render(); + + if (ui_state == UIState::VISIBLE) + { + game_window->draw(rectangle_shape); + } + } + + void RectangleShapeView::setSize(sf::Vector2f rectangle_size) + { + rectangle_shape.setSize(rectangle_size); + } + + void RectangleShapeView::setPosition(sf::Vector2f rectangle_position) + { + rectangle_shape.setPosition(rectangle_position); + } + + void RectangleShapeView::setFillColor(sf::Color fill_color) + { + rectangle_shape.setFillColor(fill_color); + } + + void RectangleShapeView::setOutlineColor(sf::Color outline_color) + { + rectangle_shape.setOutlineColor(outline_color); + } + + void RectangleShapeView::setOutlineThickness(int outline_thickness) + { + rectangle_shape.setOutlineThickness(outline_thickness); + } + + } +} \ No newline at end of file diff --git a/Linked-List-Snake/source/UI/UIService.cpp b/Linked-List-Snake/source/UI/UIService.cpp index 1abc8ab1a..a305e0cfe 100644 --- a/Linked-List-Snake/source/UI/UIService.cpp +++ b/Linked-List-Snake/source/UI/UIService.cpp @@ -7,6 +7,8 @@ namespace UI using namespace Main; using namespace MainMenu; using namespace SplashScreen; + using namespace LevelSelection; + using namespace GameplayUI; using namespace Instructions; using namespace Credits; using namespace UIElement; @@ -16,6 +18,8 @@ namespace UI { splash_screen_controller = nullptr; main_menu_controller = nullptr; + level_selection_ui_controller = nullptr; + gameplay_ui_controller = nullptr; instructions_screen_ui_controller = nullptr; credits_screen_ui_controller = nullptr; @@ -26,6 +30,8 @@ namespace UI { splash_screen_controller = new SplashScreenUIController(); main_menu_controller = new MainMenuUIController(); + level_selection_ui_controller = new LevelSelectionUIController(); + gameplay_ui_controller = new GameplayUIController(); instructions_screen_ui_controller = new InstructionsScreenUIController(); credits_screen_ui_controller = new CreditsScreenUIController(); @@ -64,6 +70,7 @@ namespace UI { splash_screen_controller->initialize(); main_menu_controller->initialize(); + level_selection_ui_controller->initialize(); instructions_screen_ui_controller->initialize(); credits_screen_ui_controller->initialize(); } @@ -78,12 +85,18 @@ namespace UI case GameState::MAIN_MENU: return main_menu_controller; + case GameState::LEVEL_SELECTION: + return level_selection_ui_controller; + case GameState::INSTRUCTIONS: return instructions_screen_ui_controller; case GameState::CREDITS: return credits_screen_ui_controller; + case GameState::GAMEPLAY: + return gameplay_ui_controller; + default: return nullptr; } @@ -93,6 +106,7 @@ namespace UI { delete(splash_screen_controller); delete(main_menu_controller); + delete(level_selection_ui_controller); delete(instructions_screen_ui_controller); delete(credits_screen_ui_controller); }