diff --git a/include/entities/Game.h b/include/entities/Game.h index 71491ce..326969d 100644 --- a/include/entities/Game.h +++ b/include/entities/Game.h @@ -7,19 +7,24 @@ #include "services/AudioService.h" #include "services/MapService.h" #include "services/InputService.h" +#include "services/GameService.h" #include "entities/Player.h" +#include "entities/Text.h" class Game { public: Game() { - TextureWrapper wrapper1 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME1), {GetScreenWidth()*2.0f,(float)GetScreenHeight()}, {0,0}); - wrapper1.setSourceRect({0,0,wrapper1.getSize().x, wrapper1.getSize().y}); - TextureWrapper wrapper2 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME2), {864.0f,(float)GetScreenHeight()}, {wrapper1.getSize().x,0.0}); - wrapper2.setSourceRect({0,200,wrapper2.getSize().x, 200+wrapper2.getSize().y}); - TextureWrapper wrapper3 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME3), {1792.0f,(float)GetScreenHeight()}, {wrapper1.getSize().x+wrapper2.getSize().x,0.0}); - wrapper3.setSourceRect({64,200,64+wrapper3.getSize().x, 200+wrapper3.getSize().y}); + GameService::getInstance().setGameOver(false); + GameService::getInstance().setPaused(false); + + TextureWrapper wrapper1 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME1), {GetScreenWidth() * 2.0f, (float)GetScreenHeight()}, {0, 0}); + wrapper1.setSourceRect({0, 0, wrapper1.getSize().x, wrapper1.getSize().y}); + TextureWrapper wrapper2 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME2), {864.0f, (float)GetScreenHeight()}, {wrapper1.getSize().x, 0.0}); + wrapper2.setSourceRect({0, 200, wrapper2.getSize().x, 200 + wrapper2.getSize().y}); + TextureWrapper wrapper3 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME3), {1792.0f, (float)GetScreenHeight()}, {wrapper1.getSize().x + wrapper2.getSize().x, 0.0}); + wrapper3.setSourceRect({64, 200, 64 + wrapper3.getSize().x, 200 + wrapper3.getSize().y}); std::vector wrappers; wrappers.push_back(wrapper1); @@ -38,10 +43,12 @@ public: this->camera = camera; this->player = Player(); - this->player.getTexture().setPosition({200,350}); + this->player.getTexture().setPosition({200, 350}); - InputService::getInstance().setKeysToWatch({KEY_SPACE, KEY_A, KEY_D}, {MOUSE_BUTTON_LEFT}); + initPauseScreen(); + initGameOverScreen(); + InputService::getInstance().setKeysToWatch({KEY_A, KEY_W, KEY_S, KEY_D, KEY_ENTER}, {MOUSE_BUTTON_LEFT}); AudioService::getInstance().setMusic(EMusic::GAME); AudioService::getInstance().playMusic(); } @@ -49,13 +56,133 @@ public: { } + void initPauseScreen() + { + const int TOP_GAP = 100; + const int BOTTOM_GAP = 50; + const int AMNT_OF_BUTTONS = 4; + const int TOTAL_SPACE = GetScreenHeight() - (TOP_GAP + BOTTOM_GAP); + const int SPACE_PER_ITEM = TOTAL_SPACE / AMNT_OF_BUTTONS; + + for (int i = 0; i < AMNT_OF_BUTTONS; i++) + { + Text txt = Text("Continue", EFont::SANSATION, 30, 0, WHITE); + pauseScreenButtons.push_back(txt); + } + pauseScreenButtons[0].setColor(RED); + pauseScreenButtons[1].setText("Save Game"); + pauseScreenButtons[2].setText("Quit to Main Menu"); + pauseScreenButtons[3].setText("Quit to Desktop"); + + for (int i = 0; i < AMNT_OF_BUTTONS; i++) + { + pauseScreenButtons[i].setPosition({(float)(GetScreenWidth() - pauseScreenButtons[i].getDimensions().x) / 2.0f, (float)TOP_GAP + SPACE_PER_ITEM * i}); + } + } + + void initGameOverScreen() + { + this->gameOverText = Text("game over", EFont::OXIN, 60, 0, WHITE); + this->gameOverText.setPosition({(float)(GetScreenWidth() - gameOverText.getDimensions().x) / 2.0f, (float)(GetScreenHeight() - gameOverText.getDimensions().y) / 3.0f}); + + const int TOP_POS = GetScreenHeight() / 1.8; + const int X_GAP = 90; + const int AMNT_OF_BUTTONS = 2; + const int TOTAL_SPACE = GetScreenWidth() - (X_GAP + X_GAP); + const int SPACE_PER_ITEM = TOTAL_SPACE / AMNT_OF_BUTTONS; + for (int i = 0; i < AMNT_OF_BUTTONS; i++) + { + Text txt = Text("play again", EFont::OXIN, 30, 0, WHITE); + gameOverScreenButtons.push_back(txt); + } + gameOverScreenButtons[0].setColor(BLACK); + gameOverScreenButtons[1].setText("quit to main menu"); + for (int i = 0; i < AMNT_OF_BUTTONS; i++) + { + gameOverScreenButtons[i].setPosition({(float)X_GAP + SPACE_PER_ITEM * i, (float)TOP_POS}); + } + } + void logic() { + if (GameService::getInstance().isPaused()) + { + pausedLogic(); + return; + } + else if (GameService::getInstance().isGameOver()) + { + gameOverLogic(); + return; + } + + if (InputService::getInstance().isKeyPressed(KEY_ENTER)) + { + GameService::getInstance().setPaused(true); + AudioService::getInstance().pauseMusic(); + return; + } // this->camera.offset.x -= 1.5; this->player.logic(); - if(this->player.getTexture().getPosition().x > (StateService::getInstance().getScreenSize().x / 2.0f)) { - this->camera.offset = {(StateService::getInstance().getScreenSize().x / 2.0f) +((StateService::getInstance().getScreenSize().x / 2.0f) - this->player.getTexture().getPosition().x), StateService::getInstance().getScreenSize().y / 2.0f}; + if (this->player.getTexture().getPosition().x > (StateService::getInstance().getScreenSize().x / 2.0f)) + { + this->camera.offset = {(StateService::getInstance().getScreenSize().x / 2.0f) + ((StateService::getInstance().getScreenSize().x / 2.0f) - this->player.getTexture().getPosition().x), StateService::getInstance().getScreenSize().y / 2.0f}; + } + } + void pausedLogic() + { + if (InputService::getInstance().isKeyPressed(KEY_S) || InputService::getInstance().isKeyPressed(KEY_W)) + { + pauseScreenButtons[hoveredPauseScreenButton].setColor(WHITE); + /** Move up or down depending on the pressed button. +4 is used so that -1 becomes 3 (the last button) */ + hoveredPauseScreenButton = ((hoveredPauseScreenButton - (InputService::getInstance().isKeyPressed(KEY_S) ? -1 : 1)) + pauseScreenButtons.size()) % pauseScreenButtons.size(); + pauseScreenButtons[hoveredPauseScreenButton].setColor(RED); + } + + if (InputService::getInstance().isKeyPressed(KEY_ENTER)) + { + + std::string selectedButton = pauseScreenButtons[hoveredPauseScreenButton].getText(); + + if (selectedButton == "Continue") + { + GameService::getInstance().setPaused(false); + AudioService::getInstance().playMusic(); + } + else if (selectedButton == "Save Game") + { + } + else if (selectedButton == "Quit to Main Menu") + StateService::getInstance().setScreen(EScreen::MAIN); + else if (selectedButton == "Quit to Desktop") + StateService::getInstance().setScreen(EScreen::CLOSE); + } + } + + void gameOverLogic() + { + if (InputService::getInstance().isKeyPressed(KEY_D) || InputService::getInstance().isKeyPressed(KEY_A)) + { + gameOverScreenButtons[hoveredGameOverScreenButton].setColor(WHITE); + /** Move up or down depending on the pressed button. +4 is used so that -1 becomes 3 (the last button) */ + hoveredGameOverScreenButton = ((hoveredGameOverScreenButton - (InputService::getInstance().isKeyPressed(KEY_D) ? -1 : 1)) + gameOverScreenButtons.size()) % gameOverScreenButtons.size(); + gameOverScreenButtons[hoveredGameOverScreenButton].setColor(BLACK); + } + + if (InputService::getInstance().isKeyPressed(KEY_ENTER)) + { + GameService::getInstance().setGameOver(false); + std::string selectedButton = gameOverScreenButtons[hoveredGameOverScreenButton].getText(); + + if (selectedButton == "play again") + { + StateService::getInstance().setScreen(EScreen::GAME); + } + else if (selectedButton == "quit to main menu") + { + StateService::getInstance().setScreen(EScreen::MAIN); + } } } @@ -69,14 +196,59 @@ public: this->player.draw(); EndMode2D(); + + if (GameService::getInstance().isPaused()) + { + drawPaused(); + } + else if (GameService::getInstance().isGameOver()) + { + drawGameOver(); + } EndDrawing(); } + void drawPaused() + { + // 100, 100, 255, 60 + DrawRectangle(0, 0, StateService::getInstance().getScreenSize().x, StateService::getInstance().getScreenSize().y, {0, 0, 255, 100}); + if (pauseScreenButtons.size() > 0) + { + for (int i = 0; i < pauseScreenButtons.size(); i++) + { + pauseScreenButtons[i].draw(); + } + } + } + + void drawGameOver() + { + DrawRectangle(0, 0, StateService::getInstance().getScreenSize().x, StateService::getInstance().getScreenSize().y, {255, 0, 0, 100}); + + gameOverText.draw(); + + for (int i = 0; i < gameOverScreenButtons.size(); i++) + { + gameOverScreenButtons[i].draw(); + } + } + private: Camera2D camera; Background background; Map map; Player player; + + std::vector pauseScreenButtons; + int hoveredPauseScreenButton = 0; + + Text gameOverText; + std::vector gameOverScreenButtons; + int hoveredGameOverScreenButton = 0; + + // bool isPaused = false; + // bool isGameOver = false; + // std::vector enemies // std::vector crates // std::vector playerBullets diff --git a/include/entities/Player.h b/include/entities/Player.h index eea1a0b..bafc08c 100644 --- a/include/entities/Player.h +++ b/include/entities/Player.h @@ -6,6 +6,7 @@ #include "services/AssetService.h" #include "services/MapService.h" #include "services/InputService.h" +#include "services/GameService.h" #include "entities/TextureWrapper.h" #include "enums/ECorner.h" @@ -24,9 +25,10 @@ public: void logic() { - gravity(); + applyGravity(); movement(); handleCollision(); + outofboundsCheck(); } void draw() @@ -43,6 +45,9 @@ protected: private: TextureWrapper texture; Vector2 velocity = {0, 0}; + float jumpPower = 7.2f; + float moveSpeed = 5.0f; + float gravity = 0.6f; std::vector timesCollision; // Holds the amount of times the player has collided with a tile, and which corner of the player is touching a tile bool groundCollision; // Keeps track of whether or not the player has collided with the ground @@ -52,11 +57,11 @@ private: * Is used for precise collision detection */ - void gravity() + void applyGravity() { if (!groundCollision) { - velocity.y += 0.6f; + velocity.y += gravity; } else { @@ -69,16 +74,16 @@ private: velocity.x = 0.0f; if (InputService::getInstance().isKeyDown(KEY_A)) { - velocity.x -= 5.0f; + velocity.x -= moveSpeed; } else if (InputService::getInstance().isKeyDown(KEY_D)) { - velocity.x += 5.0f; + velocity.x += moveSpeed; } - if (InputService::getInstance().isKeyPressed(KEY_SPACE) && groundCollision) + if (InputService::getInstance().isKeyPressed(KEY_W) && groundCollision) { - velocity.y -= 7.2f; + velocity.y -= jumpPower; } } @@ -118,6 +123,14 @@ private: this->texture.setPosition({floorf(this->texture.getPosition().x / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize(), this->texture.getPosition().y}); } } + + void outofboundsCheck() { + if(this->texture.getPosition().y > StateService::getInstance().getScreenSize().y) { + GameService::getInstance().setGameOver(true); + AudioService::getInstance().setMusic(EMusic::GAME_OVER); + AudioService::getInstance().playMusic(); + } + } }; #endif diff --git a/include/entities/Text.h b/include/entities/Text.h index 21dd3b0..680a206 100644 --- a/include/entities/Text.h +++ b/include/entities/Text.h @@ -9,6 +9,7 @@ class Text { public: + Text(){} Text(std::string text, EFont font, int fontSize = 30, int spacing = 0, Color color = WHITE, Vector2 position = {100,100}); ~Text(){} diff --git a/include/screens/GameOverScreen.h b/include/screens/GameOverScreen.h new file mode 100644 index 0000000..4e2a222 --- /dev/null +++ b/include/screens/GameOverScreen.h @@ -0,0 +1,33 @@ +#ifndef GAME_OVER_SCREEN_H +#define GAME_OVER_SCREEN_H + +#include "screens/Screen.h" +#include "raylib.h" +#include "services/AudioService.h" + +class GameOverScreen : public Screen +{ + +public: + GameOverScreen() + { + AudioService::getInstance().setMusic(EMusic::GAME_OVER); + AudioService::getInstance().playMusic(); + } + + void logic() override + { + } + + void draw() override + { + BeginDrawing(); + // ClearBackground((Color){255,0,0,100}); + DrawRectangle(0, 0, 640, 544, (Color){255,0,0,65}); + EndDrawing(); + } + +private: +}; + +#endif \ No newline at end of file diff --git a/include/services/GameService.h b/include/services/GameService.h new file mode 100644 index 0000000..5e8e364 --- /dev/null +++ b/include/services/GameService.h @@ -0,0 +1,30 @@ +#ifndef GAME_SERVICE_H +#define GAME_SERVICE_H + +#include "Service.h" + +class GameService : public Service { +public: + bool isPaused() { + return this->paused; + } + + bool isGameOver() { + return this->gameOver; + } + + void setPaused(bool paused) { + this->paused = paused; + } + + void setGameOver(bool gameOver) { + this->gameOver = gameOver; + } + +private: + bool paused = false; + bool gameOver = false; +}; + + +#endif \ No newline at end of file diff --git a/include/services/StateService.h b/include/services/StateService.h index 01960b6..4e1ce49 100644 --- a/include/services/StateService.h +++ b/include/services/StateService.h @@ -32,7 +32,6 @@ public: * Start the game loop */ void startGame(); - static void staticStep() { if (IsKeyPressed(KEY_ENTER) || IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) @@ -45,16 +44,13 @@ public: private: std::unique_ptr currentScreen; - bool gameRunning = true; - Vector2 screenSize; /** * One step of the gameloop */ void step(); - void handleMusic(); }; diff --git a/src/screens/MainScreen.cpp b/src/screens/MainScreen.cpp index 77f6293..40738e3 100644 --- a/src/screens/MainScreen.cpp +++ b/src/screens/MainScreen.cpp @@ -35,7 +35,7 @@ MainScreen::MainScreen() AudioService::getInstance().playMusic(); } - InputService::getInstance().setKeysToWatch({KEY_ENTER, KEY_UP, KEY_DOWN}, {MOUSE_BUTTON_LEFT}); + InputService::getInstance().setKeysToWatch({KEY_ENTER, KEY_W, KEY_S}, {MOUSE_BUTTON_LEFT}); } void MainScreen::logic() @@ -81,11 +81,11 @@ void MainScreen::mouseLogic() void MainScreen::keyboardLogic() { - if (InputService::getInstance().isKeyPressed(KEY_DOWN) || InputService::getInstance().isKeyPressed(KEY_UP)) + if (InputService::getInstance().isKeyPressed(KEY_S) || InputService::getInstance().isKeyPressed(KEY_W)) { buttons[hoveredButton].setColor(WHITE); /** Move up or down depending on the pressed button. +4 is used so that -1 becomes 3 (the last button) */ - hoveredButton = ((hoveredButton - (InputService::getInstance().isKeyPressed(KEY_DOWN) ? -1 : 1)) + 4) % 4; + hoveredButton = ((hoveredButton - (InputService::getInstance().isKeyPressed(KEY_S) ? -1 : 1)) + 4) % 4; buttons[hoveredButton].setColor(RED); } } diff --git a/src/services/AssetService.cpp b/src/services/AssetService.cpp index 06039a9..b99907b 100644 --- a/src/services/AssetService.cpp +++ b/src/services/AssetService.cpp @@ -17,7 +17,7 @@ void AssetService::setAssets() music[EMusic::MAIN] = loadMusic("Audio/Music/Crash_WarpRoomTheme.ogg", true); music[EMusic::GAME] = loadMusic("Audio/Music/GameTheme_2.ogg", true); - music[EMusic::GAME_OVER] = loadMusic("Audio/Music/gameOverTheme.ogg", false); + music[EMusic::GAME_OVER] = loadMusic("Audio/Music/gameOverTheme_2.ogg", false); /** Todo: set volume */ backgrounds[EBackground::TUTORIAL] = loadTexture("Textures/TutorialBackground2.png"); diff --git a/src/services/AudioService.cpp b/src/services/AudioService.cpp index 64737c8..c93e800 100644 --- a/src/services/AudioService.cpp +++ b/src/services/AudioService.cpp @@ -13,6 +13,7 @@ void AudioService::setMusic(EMusic music) if (currentTrack == music) return; + stopMusic(); // Makes sure it doesn't continue where it left off this->currentTrack = music; this->music = AssetService::getInstance().getMusic(music); } diff --git a/src/services/StateService.cpp b/src/services/StateService.cpp index 9c56ebf..ce1a975 100644 --- a/src/services/StateService.cpp +++ b/src/services/StateService.cpp @@ -4,6 +4,7 @@ #include "screens/MainScreen.h" #include "screens/TutorialScreen.h" #include "screens/GameScreen.h" +#include "screens/GameOverScreen.h" #include #include "services/AudioService.h" #include "services/InputService.h" @@ -24,6 +25,9 @@ void StateService::setScreen(EScreen state) case EScreen::GAME: currentScreen = std::make_unique(); break; + // case EScreen::GAMEOVER: + // currentScreen = std::make_unique(); + // break; case EScreen::CLOSE: gameRunning = false; break;