diff --git a/Space-Invaders/PlayerService.cpp b/Space-Invaders/PlayerService.cpp new file mode 100644 index 000000000..92f70dd0a --- /dev/null +++ b/Space-Invaders/PlayerService.cpp @@ -0,0 +1,57 @@ +#include "../Header/PlayerService.h" +#include "../Header/ServiceLocator.h" + +PlayerService::PlayerService() +{ + game_window = nullptr; +} + +PlayerService::~PlayerService() = default; + +//init +void PlayerService::initialize() +{ + game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); + initializePlayerSprite(); +} + +//take our players input in update, then set the position. +//order is important here +void PlayerService::update() +{ + processPlayerInput(); + player_sprite.setPosition(getPlayerPosition()); +} + +void PlayerService::render() +{ + game_window->draw(player_sprite); +} + +void PlayerService::processPlayerInput() +{ + // Handle keyboard input + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)) { + move(-1.0f * getMoveSpeed()); + } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)) { + move(1.0f * getMoveSpeed()); + } +} + +void PlayerService::initializePlayerSprite() +{ + if (player_texture.loadFromFile(player_texture_path)) + { + player_sprite.setTexture(player_texture); + } +} + +void PlayerService::move(float offsetX) { + position.x += offsetX; +} + +//helper functions +sf::Vector2f PlayerService::getPlayerPosition() { return position; } +int PlayerService::getMoveSpeed() { return movement_speed; } + diff --git a/Space-Invaders/Space-Invaders.vcxproj b/Space-Invaders/Space-Invaders.vcxproj index d4d53576b..30f60fefb 100644 --- a/Space-Invaders/Space-Invaders.vcxproj +++ b/Space-Invaders/Space-Invaders.vcxproj @@ -132,12 +132,30 @@ + + + + + + + + + + - + + + + + + + + + diff --git a/Space-Invaders/Space-Invaders.vcxproj.filters b/Space-Invaders/Space-Invaders.vcxproj.filters index a095c5df4..55742eea8 100644 --- a/Space-Invaders/Space-Invaders.vcxproj.filters +++ b/Space-Invaders/Space-Invaders.vcxproj.filters @@ -21,12 +21,66 @@ Source Files + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + - + Header Files - + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + Header Files diff --git a/Space-Invaders/header/EventService.h b/Space-Invaders/header/EventService.h new file mode 100644 index 000000000..3f2fe897e --- /dev/null +++ b/Space-Invaders/header/EventService.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include + +class EventService +{ +private: + sf::Event game_event; //event var + sf::RenderWindow* game_window; //ptr to our game window + + bool isGameWindowOpen(); + bool gameWindowWasClosed(); //for the condition we already had - the title bar cross. + bool hasQuitGame(); //for our new 'ESC' condition + + + + + + +public: + EventService(); + ~EventService(); + + void initialize(); + void update(); + void processEvents(); // while window is open we will check for events + bool pressedEscapeKey(); + bool isKeyboardEvent(); + bool pressedLeftKey(); + + bool pressedRightKey(); +}; diff --git a/Space-Invaders/header/GraphicService.h b/Space-Invaders/header/GraphicService.h new file mode 100644 index 000000000..0d138531f --- /dev/null +++ b/Space-Invaders/header/GraphicService.h @@ -0,0 +1,7 @@ +class GraphicService { +public: + void initialize(); + +private: + static const int frame_rate = 60; +}; \ No newline at end of file diff --git a/Space-Invaders/header/PlayerController.h b/Space-Invaders/header/PlayerController.h new file mode 100644 index 000000000..45a7567d4 --- /dev/null +++ b/Space-Invaders/header/PlayerController.h @@ -0,0 +1,26 @@ + +#pragma once +#include +#include "../Player/PlayerModel.h" +#include "../Player/PlayerView.h" + +class PlayerController +{ +private: + PlayerView* player_view; + PlayerModel* player_model; + + void processPlayerInput(); + void moveLeft(); + void moveRight(); + +public: + PlayerController(); + ~PlayerController(); + + void initialize(); + void update(); + void render(); + + sf::Vector2f getPlayerPosition(); +}; diff --git a/Space-Invaders/header/PlayerModel.h b/Space-Invaders/header/PlayerModel.h new file mode 100644 index 000000000..ddc252a0f --- /dev/null +++ b/Space-Invaders/header/PlayerModel.h @@ -0,0 +1,43 @@ +#pragma once +#include + +enum class PlayerState //Our Enum +{ + ALIVE, + DEAD, + // we will add more states later +}; + +class PlayerModel +{ +private: + const sf::Vector2f initial_player_position = sf::Vector2f(500.f, 500.f); + + sf::Vector2f player_position; + PlayerState player_state; //Declaration + int player_score; + +public: + const sf::Vector2f left_most_position = sf::Vector2f(50.f, 0.f); + const sf::Vector2f right_most_position = sf::Vector2f(700.f, 0.f); + + const float player_movement_speed = 200.0f; + + PlayerModel(); + ~PlayerModel(); + + void initialize(); + void reset(); + + sf::Vector2f getPlayerPosition(); + void setPlayerPosition(sf::Vector2f position); + + int getPlayerScore(); + void setPlayerScore(int score); + + //new getter and setter + PlayerState getPlayerState(); + void setPlayerState(PlayerState state); + + +}; \ No newline at end of file diff --git a/Space-Invaders/header/PlayerService.h b/Space-Invaders/header/PlayerService.h new file mode 100644 index 000000000..5e57ab793 --- /dev/null +++ b/Space-Invaders/header/PlayerService.h @@ -0,0 +1,26 @@ + +#pragma once + + +#pragma once +#include +#include "../../Header/Player/PlayerController.h" +class PlayerService +{ + +private: + +PlayerController* player_controller + +public: + + PlayerService(); + ~PlayerService(); + + void initialize(); + void update(); + void render(); + + + +}; diff --git a/Space-Invaders/header/PlayerView.h b/Space-Invaders/header/PlayerView.h new file mode 100644 index 000000000..3c9999102 --- /dev/null +++ b/Space-Invaders/header/PlayerView.h @@ -0,0 +1,29 @@ +#pragma once +#include "../../Header/Player/PlayerController.h" +#include + +class PlayerView +{ +private: + + const sf::String player_texture_path = "assets/textures/player_ship.png"; + const float player_sprite_width = 60.f; + const float player_sprite_height = 60.f; + + sf::RenderWindow* game_window; + + sf::Texture player_texture; + sf::Sprite player_sprite; + + void initializePlayerSprite(); + void scalePlayerSprite(); + PlayerController* player_controller; +public: + PlayerView(); + ~PlayerView(); + + void initialize(); + void update(); + void render(); + void initialize(PlayerController* controller); +}; diff --git a/Space-Invaders/header/TimeService.h b/Space-Invaders/header/TimeService.h new file mode 100644 index 000000000..7f6c57a02 --- /dev/null +++ b/Space-Invaders/header/TimeService.h @@ -0,0 +1,32 @@ + +#pragma once +#include + +/* + // The TimeService class helps keep track of time in game and calculate delta time. + // Utilizes the library to calculate delta time. + */ +class TimeService +{ +private: + + // A point in time which indicates the starting time of previous frame. + std::chrono::time_point previous_time; + // No need to worry about the syntax of this variable too much right now + // It'll be explained in detail at a later time. + + float delta_time; //to store the detla time + + void updateDeltaTime(); // method to update time + float calculateDeltaTime(); //calculate time by subtracting the previous time from the current time + void updatePreviousTime(); // finally update the current time to be previous time + +public: + + //lifecycle methods + void initialize(); + void update(); + + //getter + float getDeltaTime(); +}; \ No newline at end of file diff --git a/Space-Invaders/header/servicelocator.h b/Space-Invaders/header/servicelocator.h index 6f70f09be..6c8d15b7d 100644 --- a/Space-Invaders/header/servicelocator.h +++ b/Space-Invaders/header/servicelocator.h @@ -1 +1,31 @@ + #pragma once +#include "../header/GraphicService.h" +#include "../header/EventService.h" + +class ServiceLocator +{ +private: + // Private Attributes: + GraphicService* graphic_service; + + // Private Constructor and Destructor: + ServiceLocator(); + // Constructor for initializing the ServiceLocator. + ~ServiceLocator(); // Destructor for cleaning up resources upon object deletion. + + // Private Methods: + void createServices(); // Creates instances of all services. + void clearAllServices(); // Deletes and deallocates memory for all services. + +public: + // Public Methods: + static ServiceLocator* getInstance(); // Provides a method to access the unique ServiceLocator instance (object). + void initialize(); // Initializes the ServiceLocator. + void update(); // Updates all services. + void render(); // Renders using the services. + + // Methods to Get Specific Services: + GraphicService* getGraphicService(); + +}; diff --git a/Space-Invaders/source/EventService.cpp b/Space-Invaders/source/EventService.cpp new file mode 100644 index 000000000..891ed1457 --- /dev/null +++ b/Space-Invaders/source/EventService.cpp @@ -0,0 +1,45 @@ +#include "../header/EventService.h" +#include "../header/GameService.h" +#include "../header/GraphicService.h" + +EventService::EventService() { game_window = nullptr; } + +EventService::~EventService() = default; //calls the default destructor + +void EventService::initialize() +{ + game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); +} + +void EventService::update() +{ + //for later +} + +void EventService::processEvents() +{ + if (isGameWindowOpen()) { + while (game_window->pollEvent(game_event)) { + // Check for window closure + if (gameWindowWasClosed() || hasQuitGame()) + { + game_window->close(); + } + } + } +} + +bool EventService::hasQuitGame() { return (isKeyboardEvent() && pressedEscapeKey()); } // only true if the ESC key is pressed and a keyboard event has been registered + +//checks for if a keyboard key has been pressed +bool EventService::isKeyboardEvent() { return game_event.type == sf::Event::KeyPressed; } + +//control click on the SFML functions to see what they do internally +bool EventService::pressedEscapeKey() { return game_event.key.code == sf::Keyboard::Escape; } + +bool EventService::isGameWindowOpen() { return game_window != nullptr; } + +bool EventService::pressedLeftKey() { return game_event.key.code == sf::Keyboard::Left; } +bool EventService::pressedRightKey() { return game_event.key.code == sf::Keyboard::Right; } + +bool EventService::gameWindowWasClosed() { return game_event.type == sf::Event::Closed; } \ No newline at end of file diff --git a/Space-Invaders/source/GraphicService.cpp b/Space-Invaders/source/GraphicService.cpp new file mode 100644 index 000000000..27b2dde7c --- /dev/null +++ b/Space-Invaders/source/GraphicService.cpp @@ -0,0 +1,6 @@ +#include "../header/GraphicService.h" +void GraphicService::initialize() +{ + game_window = createGameWindow(); + game_window->setFramerateLimit(frame_rate); +} \ No newline at end of file diff --git a/Space-Invaders/source/PLayerController.cpp b/Space-Invaders/source/PLayerController.cpp new file mode 100644 index 000000000..998e15c6c --- /dev/null +++ b/Space-Invaders/source/PLayerController.cpp @@ -0,0 +1,72 @@ +#include "../../Header/Player/PlayerController.h" +#include "../../Header/EventService.h" +#include "../../Header/ServiceLocator.h" +#include + +PlayerController::PlayerController() +{ + player_view = new PlayerView(); + player_model = new PlayerModel(); +} + +PlayerController::~PlayerController() +{ + delete (player_view); + delete (player_model); +} +//the controller is responsible for calling the lifecycle methods for the other two +void PlayerController::initialize() +{ + player_model->initialize(); + + //This will give an error right now since we haven't included the controller in the view. + player_view->initialize(this); // 'this' refers to the class we are currently inside +} + +void PlayerController::update() +{ + processPlayerInput(); + player_view->update(); // we update() the view +} + +void PlayerController::render() +{ + player_view->render(); // render the view +} + +sf::Vector2f PlayerController::getPlayerPosition() +{ + return player_model->getPlayerPosition(); +} + +void PlayerController::processPlayerInput() +{ + // we will move this to event service at a later time + if ((sf::Keyboard::isKeyPressed(sf::Keyboard::Left))) + { + moveLeft(); + } + // we will move this to event service at a later time + if ((sf::Keyboard::isKeyPressed(sf::Keyboard::Right))) + { + moveRight(); + } +} + +void PlayerController::moveLeft() +{ + sf::Vector2f currentPosition = player_model->getPlayerPosition(); + currentPosition.x -= player_model->player_movement_speed * ServiceLocator::getInstance()->getTimeService()->getDeltaTime(); + + currentPosition.x = std::max(currentPosition.x, player_model->left_most_position.x); + player_model->setPlayerPosition(currentPosition); +} + +void PlayerController::moveRight() +{ + sf::Vector2f currentPosition = player_model->getPlayerPosition(); + currentPosition.x += player_model->player_movement_speed * ServiceLocator::getInstance()->getTimeService()->getDeltaTime(); + + currentPosition.x = std::min(currentPosition.x, player_model->right_most_position.x); + player_model->setPlayerPosition(currentPosition); +} \ No newline at end of file diff --git a/Space-Invaders/source/PLayerView.cpp b/Space-Invaders/source/PLayerView.cpp new file mode 100644 index 000000000..22b067944 --- /dev/null +++ b/Space-Invaders/source/PLayerView.cpp @@ -0,0 +1,43 @@ +#include "../../Header/Player/PlayerView.h" +#include "../../Header/ServiceLocator.h" + +PlayerView::PlayerView() { } + +PlayerView::~PlayerView() { } + +void PlayerView::initialize(PlayerController* controller) +{ + + player_controller = controller; + game_window = ServiceLocator::getInstance()->getGraphicService()->getGameWindow(); + initializePlayerSprite(); +} + +void PlayerView::initializePlayerSprite() +{ + if (player_texture.loadFromFile(player_texture_path)) + { + player_sprite.setTexture(player_texture); + scalePlayerSprite(); + } +} + +void PlayerView::scalePlayerSprite() +{ + // setScale is an inbuilt method of the sprite class that takes two floats to scale the sprite. it scales the sprite to our desired height + player_sprite.setScale( + //Here we find the factor to scale our sprites with. Ignore the static_cast for now, we will discuss it later. + static_cast(player_sprite_width) / player_sprite.getTexture()->getSize().x, + static_cast(player_sprite_height) / player_sprite.getTexture()->getSize().y + ); +} + +void PlayerView::update() +{ + player_sprite.setPosition(player_controller->getPlayerPosition()); +} + +void PlayerView::render() +{ + game_window->draw(player_sprite); +} \ No newline at end of file diff --git a/Space-Invaders/source/PlayerModel.cpp b/Space-Invaders/source/PlayerModel.cpp new file mode 100644 index 000000000..f56c7dc0d --- /dev/null +++ b/Space-Invaders/source/PlayerModel.cpp @@ -0,0 +1,45 @@ +#include "../../Header/Player/PlayerModel.h" + +PlayerModel::PlayerModel() { } + +PlayerModel::~PlayerModel() { } + +void PlayerModel::initialize() { reset(); } // remember to call reset() + +void PlayerModel::reset() +{ + player_state = PlayerState::ALIVE; // set state to alive + player_position = initial_player_position; + player_score = 0; +} + +sf::Vector2f PlayerModel::getPlayerPosition() +{ + return player_position; +} + +void PlayerModel::setPlayerPosition(sf::Vector2f position) +{ + player_position = position; +} + +int PlayerModel::getPlayerScore() +{ + return player_score; +} + +void PlayerModel::setPlayerScore(int score) +{ + player_score = score; +} + +//.. +PlayerState PlayerModel::getPlayerState() +{ + return player_state; +} + +void PlayerModel::setPlayerState(PlayerState state) +{ + player_state = state; +} \ No newline at end of file diff --git a/Space-Invaders/source/PlayerService.cpp b/Space-Invaders/source/PlayerService.cpp new file mode 100644 index 000000000..345bd0474 --- /dev/null +++ b/Space-Invaders/source/PlayerService.cpp @@ -0,0 +1,27 @@ +#include "../Header/PlayerService.h" +#include "../Header/Player/PlayerController.h" + +PlayerService::PlayerService() +{ + player_controller = new PlayerController(); +} + +PlayerService::~PlayerService() +{ + delete (player_controller); +} + +void PlayerService::initialize() +{ + player_controller->initialize(); +} + +void PlayerService::update() +{ + player_controller->update(); +} + +void PlayerService::render() +{ + player_controller->render(); +} \ No newline at end of file diff --git a/Space-Invaders/source/ServiceLocator.cpp b/Space-Invaders/source/ServiceLocator.cpp new file mode 100644 index 000000000..2d5b31b90 --- /dev/null +++ b/Space-Invaders/source/ServiceLocator.cpp @@ -0,0 +1,57 @@ +#include "../Header/ServiceLocator.h" +#include "../Header/TimeService.h" +#include "../Header/EventService.h" +ServiceLocator::ServiceLocator() +{ + graphic_service = nullptr; + time_service = nullptr; + event_service = nullptr; + player_service = nullptr; + + createServices(); +} + +//.. some other code + +void ServiceLocator::createServices() +{ + graphic_service = new GraphicService(); + time_service = new TimeService(); + event_service = new EventService(); + player_service = new PlayerService(); +} + +void ServiceLocator::clearAllServices() +{ + delete(graphic_service); + delete(time_service); + delete(event_service); + delete(player_service); +} + +//... other code + +void ServiceLocator::initialize() +{ + graphic_service->initialize(); + time_service->initialize(); + event_service->initialize(); + player_service->initialize(); +} + +void ServiceLocator::update() +{ + graphic_service->update(); + time_service->update(); + event_service->update(); + player_service->update(); +} + +//... other code + +GraphicService* ServiceLocator::getGraphicService() { return graphic_service; } +EventService* ServiceLocator::getEventService() { return event_service; } +PlayerService* ServiceLocator::getPlayerService() { return player_service; } +TimeService* ServiceLocator::getTimeService() { return time_service; } + +//... other code \ No newline at end of file diff --git a/Space-Invaders/source/TimeService.cpp b/Space-Invaders/source/TimeService.cpp new file mode 100644 index 000000000..33cbee4c8 --- /dev/null +++ b/Space-Invaders/source/TimeService.cpp @@ -0,0 +1,40 @@ +#include "../Header/TimeService.h" + +void TimeService::initialize() +{ + previous_time = std::chrono::steady_clock::now(); + delta_time = 0; +} + +void TimeService::update() +{ + updateDeltaTime(); +} + +float TimeService::getDeltaTime() +{ + return delta_time; +} + +void TimeService::updateDeltaTime() +{ + delta_time = calculateDeltaTime(); + updatePreviousTime(); +} + +float TimeService::calculateDeltaTime() +{ + // Calculate time difference in microseconds between the current and previous frame. + int delta = std::chrono::duration_cast( + std::chrono::steady_clock::now() - previous_time).count(); + + // The cast is used to convert delta time from microseconds into seconds. + // We will learn aboit how this works in detail later. + return static_cast(delta) / static_cast(1000000); +} + +// Update previous_time to the current time +void TimeService::updatePreviousTime() +{ + previous_time = std::chrono::steady_clock::now(); +}