From 76dd80d3a3574c44f9a145c97568fce6dc082396 Mon Sep 17 00:00:00 2001 From: Ninjaws Date: Sun, 8 Dec 2024 22:03:56 +0100 Subject: [PATCH] [Added] Tutorial Screen, Start of the Game Screen --- include/AssetService.h | 6 ++ include/AudioService.h | 5 +- include/Background.h | 24 ++++++++ include/EBackground.h | 13 +++++ include/GameScreen.h | 16 +++++ include/MainScreen.h | 4 +- include/Map.h | 33 +++++++++++ include/Screen.h | 10 +++- include/StateService.h | 12 +++- include/Text.h | 3 +- include/TitleScreen.h | 7 --- include/TutorialScreen.h | 17 ++++++ src/entities/Background.cpp | 39 +++++++++++++ src/entities/Map.cpp | 103 +++++++++++++++++++++++++++++++++ src/entities/Text.cpp | 6 -- src/main.cpp | 1 + src/screens/GameScreen.cpp | 27 +++++++++ src/screens/MainScreen.cpp | 44 +++++++------- src/screens/Screen.cpp | 19 +++++- src/screens/TitleScreen.cpp | 19 ++---- src/screens/TutorialScreen.cpp | 23 ++++++++ src/services/AssetService.cpp | 14 ++++- src/services/StateService.cpp | 16 +++-- 23 files changed, 396 insertions(+), 65 deletions(-) create mode 100644 include/Background.h create mode 100644 include/EBackground.h create mode 100644 include/GameScreen.h create mode 100644 include/Map.h create mode 100644 include/TutorialScreen.h create mode 100644 src/entities/Background.cpp create mode 100644 src/entities/Map.cpp create mode 100644 src/screens/GameScreen.cpp create mode 100644 src/screens/TutorialScreen.cpp diff --git a/include/AssetService.h b/include/AssetService.h index a1bbd73..3177fa6 100644 --- a/include/AssetService.h +++ b/include/AssetService.h @@ -7,6 +7,7 @@ #include #include "EFont.h" #include "EMusic.h" +#include "EBackground.h" #include "Service.h" class AssetService: public Service @@ -19,6 +20,7 @@ private: std::unordered_map fonts; std::vector sounds; std::unordered_map music; + std::unordered_map backgrounds; void setAssets(); @@ -35,6 +37,10 @@ public: Music getMusic(EMusic music) { return this->music[music]; } + Texture2D getBackground(EBackground background){ + return this->backgrounds[background]; + } + Texture2D loadTexture(std::string filename); }; #endif \ No newline at end of file diff --git a/include/AudioService.h b/include/AudioService.h index 04fa67f..68a697a 100644 --- a/include/AudioService.h +++ b/include/AudioService.h @@ -9,13 +9,10 @@ class AudioService : public Service { private: - /** Friend to allow access to the destructor */ - // friend class Service; std::optional music; - EMusic currentTrack; + EMusic currentTrack = EMusic::NONE; protected: - // ~AudioService(); public: void setMusic(EMusic music); diff --git a/include/Background.h b/include/Background.h new file mode 100644 index 0000000..26a5326 --- /dev/null +++ b/include/Background.h @@ -0,0 +1,24 @@ +#ifndef BACKGROUND_H +#define BACKGROUND_H + +#include "raylib.h" +#include "EBackground.h" +#include + +class Background { + private: + Vector2 position; + std::vector textures; + protected: + public: + Background(EBackground background); + Background(std::vector backgrounds); + ~Background(){} + Vector2 getPosition(); + void updatePosition(Vector2 deltaPos); + void setPosition(Vector2 position); + void draw(); +}; + + +#endif \ No newline at end of file diff --git a/include/EBackground.h b/include/EBackground.h new file mode 100644 index 0000000..166bb44 --- /dev/null +++ b/include/EBackground.h @@ -0,0 +1,13 @@ +#ifndef EBACKGROUND_H +#define EBACKGROUND_H + +enum class EBackground { + TUTORIAL, + GAME1, + GAME2, + GAME3, + VICTORY +}; + + +#endif \ No newline at end of file diff --git a/include/GameScreen.h b/include/GameScreen.h new file mode 100644 index 0000000..fcd75f8 --- /dev/null +++ b/include/GameScreen.h @@ -0,0 +1,16 @@ +#ifndef GAME_SCREEN_H +#define GAME_SCREEN_H + +#include "Screen.h" + +class GameScreen: public Screen { + +private: +protected: +public: + GameScreen(); + void logic() override; + +}; + +#endif \ No newline at end of file diff --git a/include/MainScreen.h b/include/MainScreen.h index d6d0fd9..97ccd28 100644 --- a/include/MainScreen.h +++ b/include/MainScreen.h @@ -2,8 +2,6 @@ #define MAIN_SCREEN_H #include "Screen.h" -#include "raylib.h" -#include class MainScreen : public Screen { private: @@ -11,10 +9,10 @@ private: void mouseLogic(); void keyboardLogic(); + void clickLogic(); public: MainScreen(); - ~MainScreen(); void logic() override; }; diff --git a/include/Map.h b/include/Map.h new file mode 100644 index 0000000..332caf5 --- /dev/null +++ b/include/Map.h @@ -0,0 +1,33 @@ +#ifndef MAP_H +#define MAP_H + +#include +#include "raylib.h" + +/** + * Holds the collision and texture maps for the game world + */ +class Map +{ +public: + Map(); + ~Map() {} + + void draw(); + +private: + /** Holds the number for every single tile, which refers to a certain sprite in the tileset */ + std::vector> map; + /** Holds 1s (collision) and 0s (no collision) for every tile */ + std::vector> colMap; + + float tileSize = 32; + + Texture2D tileset; + + void loadMap(); + void loadColMap(){} + void loadTileset(); +}; + +#endif \ No newline at end of file diff --git a/include/Screen.h b/include/Screen.h index dc576f4..532b724 100644 --- a/include/Screen.h +++ b/include/Screen.h @@ -3,15 +3,23 @@ #include #include "Text.h" +#include "raylib.h" +#include +#include "Background.h" +#include "Map.h" class Screen { private: protected: + // std::optional map; + std::optional camera; + std::optional map; + std::optional background; std::vector text; public: - Screen(){} + Screen(); ~Screen(){} /** diff --git a/include/StateService.h b/include/StateService.h index 3449bf8..3d66009 100644 --- a/include/StateService.h +++ b/include/StateService.h @@ -11,6 +11,9 @@ #include #endif +/** + * Handles switching between screens + */ class StateService : public Service { private: @@ -18,6 +21,8 @@ private: bool gameRunning = true; + Vector2 screenSize; + /** * One step of the gameloop */ @@ -26,7 +31,12 @@ private: void handleMusic(); public: - + Vector2 getScreenSize(){ + return screenSize; + } + void setScreenSize(Vector2 screenSize) { + this->screenSize = screenSize; + } void setScreen(EScreen screen); Screen *getScreen(); /** diff --git a/include/Text.h b/include/Text.h index 4e51dc3..6d65e64 100644 --- a/include/Text.h +++ b/include/Text.h @@ -18,7 +18,7 @@ class Text { public: Text(std::string text, EFont font, int fontSize = 30, int spacing = 0, Color color = WHITE, Vector2 position = {100,100}); - ~Text(); + ~Text(){} Vector2 getDimensions(); @@ -42,7 +42,6 @@ class Text { return this->text; } - void draw(); }; diff --git a/include/TitleScreen.h b/include/TitleScreen.h index 35c884b..45b33c4 100644 --- a/include/TitleScreen.h +++ b/include/TitleScreen.h @@ -3,22 +3,15 @@ #include "Screen.h" #include "raylib.h" -#include "Text.h" -#include -#include class TitleScreen : public Screen { private: Music bg; - // std::vector text; public: TitleScreen(); - ~TitleScreen(); - // void step() override; void logic() override; - // void draw() override; }; #endif \ No newline at end of file diff --git a/include/TutorialScreen.h b/include/TutorialScreen.h new file mode 100644 index 0000000..853ab30 --- /dev/null +++ b/include/TutorialScreen.h @@ -0,0 +1,17 @@ +#ifndef TUTORIAL_SCREEN_H +#define TUTORIAL_SCREEN_H + +#include "Screen.h" + +class TutorialScreen : public Screen { +private: +protected: +public: + TutorialScreen(); + + void logic() override; + +}; + + +#endif \ No newline at end of file diff --git a/src/entities/Background.cpp b/src/entities/Background.cpp new file mode 100644 index 0000000..11c9cc5 --- /dev/null +++ b/src/entities/Background.cpp @@ -0,0 +1,39 @@ +#include "Background.h" + +#include "AssetService.h" + +Background::Background(EBackground background) +{ + this->textures.push_back(AssetService::getInstance().getBackground(background)); + this->position = {0,0}; +} + +Background::Background(std::vector backgrounds) +{ + for(int i = 0; i < backgrounds.size(); i++) { + this->textures.push_back(AssetService::getInstance().getBackground(backgrounds[i])); + this->position = {0,0}; + } +} + +Vector2 Background::getPosition() +{ + return this->position; +} + +void Background::updatePosition(Vector2 deltaPos) +{ + this->position = {this->position.x+deltaPos.x, this->position.y+deltaPos.y}; +} + +void Background::setPosition(Vector2 position) +{ + this->position = position; +} + +void Background::draw() +{ + for(int i = 0; i < textures.size(); i++) { + DrawTexture(textures[i], position.x+ (i != 0 ? i*textures[i-1].width : 0), position.y, WHITE); + } +} diff --git a/src/entities/Map.cpp b/src/entities/Map.cpp new file mode 100644 index 0000000..d13d29d --- /dev/null +++ b/src/entities/Map.cpp @@ -0,0 +1,103 @@ +#include "Map.h" +#include +#include +#include +#include +#include "AssetService.h" + +Map::Map() +{ + loadTileset(); + loadMap(); +} + +void Map::loadMap() +{ + std::vector tempMap; + std::ifstream openfile("assets/Maps/map1.txt"); + + map.clear(); + + if (openfile.is_open()) + { + std::string tileLocation; + openfile >> tileLocation; + // tileTexture.loadFromFile(tileLocation); + // tileSprites.setTexture(tileTexture); + while (!openfile.eof()) + { + std::string str, value; + std::getline(openfile, str); + std::stringstream stream(str); + + while (std::getline(stream, value, ' ')) + { + if (value.length() > 0) + { + std::string xx = value.substr(0, value.find(',')); + std::string yy = value.substr(value.find(',') + 1); + + int x = 0, y = 0, i, j; + // Look at all characters before the ',' + for (i = 0; i < xx.length(); i++) + { + // if one of them is not a number, break + if (!isdigit(xx[i])) + break; + } + for (j = 0; j < yy.length(); j++) + { + if (!isdigit(yy[j])) + break; + } + + // If all characters are numbers, convert string to int (the number that the sprite has in the sheet ( in this case, on the x axis) + if (i == xx.length()) + x = atoi(xx.c_str()); + else + x = -1; + // Otherwise, return -1 (aka no sprite) + + if (j == yy.length()) + y = atoi(yy.c_str()); + else + y = -1; + + // Hold both the x and y positions of the sprite + Vector2 vec2 = {(float)x, (float)y}; + tempMap.push_back(vec2); + } + } + + if (tempMap.size() > 0) + { + map.push_back(tempMap); + tempMap.clear(); + } + } + } +} + +void Map::loadTileset() +{ + this->tileset = AssetService::getInstance().loadTexture("Textures/tileset.png"); +} + +void Map::draw() +{ + for (int i = 0; i < map.size(); i++) + { + for (int j = 0; j < map[i].size(); j++) + { + if (map[i][j].x != -1 && map[i][j].y != -1) + { + // Rectangle source = {0,0,32,32}; + Rectangle sourceRect = {map[i][j].x * tileSize, map[i][j].y * tileSize, tileSize, tileSize}; + DrawTextureRec(tileset, sourceRect, {j * tileSize, i * tileSize}, WHITE); + // tileSprites.setPosition(j * tileSize, i * tileSize); + // tileSprites.setTextureRect(sf::IntRect(map[i][j].x * tileSize, map[i][j].y * tileSize, tileSize, tileSize)); + // GetWindow().draw(tileSprites); + } + } + } +} diff --git a/src/entities/Text.cpp b/src/entities/Text.cpp index 90ecb6f..e1bf782 100644 --- a/src/entities/Text.cpp +++ b/src/entities/Text.cpp @@ -12,12 +12,6 @@ Text::Text(std::string text, EFont font, int fontSize, int spacing, Color color, this->position = position; } -Text::~Text() -{ - // Causes double free for some reason - // UnloadFont(this->font); -} - Vector2 Text::getDimensions() { return MeasureTextEx(font, text.c_str(), (float)fontSize, (float)spacing); diff --git a/src/main.cpp b/src/main.cpp index 25245fd..4ed8675 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,7 @@ int main(void) { StateService& stateService = StateService::getInstance(); + stateService.setScreenSize({640,544}); stateService.startGame(); // std::cout << "StateService instance: " << service << std::endl; diff --git a/src/screens/GameScreen.cpp b/src/screens/GameScreen.cpp new file mode 100644 index 0000000..b06934a --- /dev/null +++ b/src/screens/GameScreen.cpp @@ -0,0 +1,27 @@ +#include "GameScreen.h" +#include "Map.h" +#include "StateService.h" + +GameScreen::GameScreen() +{ + std::vector bgs; + bgs.push_back(EBackground::GAME1); + bgs.push_back(EBackground::GAME2); + bgs.push_back(EBackground::GAME3); + this->background = Background(bgs); + this->map = Map(); + + Vector2 screenSize = StateService::getInstance().getScreenSize(); + Camera2D camera = { 0 }; + camera.offset = (Vector2){ screenSize.x / 2.0f, screenSize.y / 2.0f }; // Set offset to center + camera.target = (Vector2){ screenSize.x /2.0f, screenSize.y / 2.0f }; // Initially at the center of the world + camera.rotation = 0.0f; + camera.zoom = 1.0f; + this->camera = camera; +} + +void GameScreen::logic() +{ + // this->background.value().updatePosition({-2.5f,0}); + this->camera.value().target.x += 1.0f; +} diff --git a/src/screens/MainScreen.cpp b/src/screens/MainScreen.cpp index 7bb1d36..0be1ee5 100644 --- a/src/screens/MainScreen.cpp +++ b/src/screens/MainScreen.cpp @@ -1,8 +1,7 @@ #include "MainScreen.h" -#include "AssetService.h" #include "AudioService.h" -#include #include "StateService.h" +#include "raylib.h" MainScreen::MainScreen() { @@ -17,7 +16,6 @@ MainScreen::MainScreen() Text txt = Text("new game", EFont::GTEK, 30, 0, WHITE); text.push_back(txt); } - text[0].setColor(RED); text[1].setText("load game"); text[2].setText("tutorial"); @@ -29,12 +27,12 @@ MainScreen::MainScreen() } /** Will be ignored if already active (like when coming from the TitleScreen) */ - AudioService::getInstance().setMusic(EMusic::MAIN); - AudioService::getInstance().playMusic(); -} - -MainScreen::~MainScreen() -{ + EMusic track = AudioService::getInstance().getCurrentTrack(); + if (track != EMusic::MAIN) + { + AudioService::getInstance().setMusic(EMusic::MAIN); + AudioService::getInstance().playMusic(); + } } void MainScreen::logic() @@ -43,10 +41,12 @@ void MainScreen::logic() // std::cout << mouseD.y <= rect.x && mousePos.x <= (rect.x+rect.width) && - if (mousePos.x >= rect.x && mousePos.x <= (rect.x+rect.width) && mousePos.y >= rect.y && mousePos.y <= (rect.y + rect.height)) + if ((mousePos.x + textPadding) >= rect.x && mousePos.x <= (rect.x + rect.width + textPadding) && (mousePos.y + textPadding) >= rect.y && mousePos.y <= (rect.y + rect.height + textPadding)) { text[hoveredButton].setColor(WHITE); hoveredButton = i; @@ -82,22 +84,22 @@ void MainScreen::keyboardLogic() hoveredButton = ((hoveredButton - (IsKeyPressed(KEY_DOWN) ? -1 : 1)) + 4) % 4; text[hoveredButton].setColor(RED); } +} +void MainScreen::clickLogic() +{ if (IsKeyPressed(KEY_ENTER) || IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) { - std::cout << text[hoveredButton].getText() << std::endl; std::string selectedButton = text[hoveredButton].getText(); - - if(selectedButton == "new game") { + if (selectedButton == "new game") + StateService::getInstance().setScreen(EScreen::GAME); + else if (selectedButton == "load game") + { } - else if(selectedButton == "load game") { - } - else if(selectedButton == "tutorial") { + else if (selectedButton == "tutorial") StateService::getInstance().setScreen(EScreen::TUTORIAL); - } - else if(selectedButton == "quit") { + else if (selectedButton == "quit") StateService::getInstance().setScreen(EScreen::CLOSE); - } } -} \ No newline at end of file +} diff --git a/src/screens/Screen.cpp b/src/screens/Screen.cpp index 6209d13..473d121 100644 --- a/src/screens/Screen.cpp +++ b/src/screens/Screen.cpp @@ -2,10 +2,24 @@ #include "AudioService.h" #include +Screen::Screen() +{ +} + void Screen::draw() { BeginDrawing(); - ClearBackground(BLACK); + + if (camera.has_value()) + BeginMode2D(this->camera.value()); + + if (!background.has_value()) + ClearBackground(BLACK); + else + this->background.value().draw(); + + if (map.has_value()) + this->map.value().draw(); if (text.size() > 0) { @@ -14,5 +28,8 @@ void Screen::draw() text[t].draw(); } } + if (camera.has_value()) + EndMode2D(); + EndDrawing(); } \ No newline at end of file diff --git a/src/screens/TitleScreen.cpp b/src/screens/TitleScreen.cpp index 5153721..579948c 100644 --- a/src/screens/TitleScreen.cpp +++ b/src/screens/TitleScreen.cpp @@ -27,20 +27,11 @@ TitleScreen::TitleScreen() text.push_back(textCenter); text.push_back(testSub); - - AudioService::getInstance().setMusic(EMusic::MAIN); - AudioService::getInstance().playMusic(); - - // bg = LoadMusicStream("assets/Audio/Music/Crash_WarpRoomTheme.ogg"); - // bg.looping = true; - // SetMasterVolume(1.0f); - // SetMusicVolume(bg, 1.0f); - // PlayMusicStream(bg); -} - -TitleScreen::~TitleScreen() -{ - // UnloadMusicStream(bg); + EMusic track = AudioService::getInstance().getCurrentTrack(); + if (track != EMusic::MAIN) { + AudioService::getInstance().setMusic(EMusic::MAIN); + AudioService::getInstance().playMusic(); + } } void TitleScreen::logic() diff --git a/src/screens/TutorialScreen.cpp b/src/screens/TutorialScreen.cpp new file mode 100644 index 0000000..2135016 --- /dev/null +++ b/src/screens/TutorialScreen.cpp @@ -0,0 +1,23 @@ +#include "TutorialScreen.h" + +#include "StateService.h" +#include "EFont.h" +#include "EScreen.h" + +TutorialScreen::TutorialScreen() +{ + Text textBack = Text("Press Enter to go back", EFont::SANSATION, 30, 0, RED); + textBack.setPosition({(float)(GetScreenWidth() - textBack.getDimensions().x) / 1.3f, + (float)(GetScreenHeight() - textBack.getDimensions().y) / 1.15f}); + this->text.push_back(textBack); + + this->background = Background(EBackground::TUTORIAL); +} + +void TutorialScreen::logic() +{ + if (IsKeyPressed(KEY_ENTER) || IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) + { + StateService::getInstance().setScreen(EScreen::MAIN); + } +} diff --git a/src/services/AssetService.cpp b/src/services/AssetService.cpp index 7b55cf7..cc2ae54 100644 --- a/src/services/AssetService.cpp +++ b/src/services/AssetService.cpp @@ -1,5 +1,4 @@ #include "AssetService.h" -#include AssetService::AssetService() { @@ -19,6 +18,13 @@ 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); + /** Todo: set volume */ + + backgrounds[EBackground::TUTORIAL] = loadTexture("Textures/TutorialBackground2.png"); + backgrounds[EBackground::GAME1] = loadTexture("Textures/GameBackground_1.png"); + backgrounds[EBackground::GAME2] = loadTexture("Textures/GameBackground_2.jpg"); + backgrounds[EBackground::GAME3] = loadTexture("Textures/GameBackground_3.png"); + backgrounds[EBackground::VICTORY] = loadTexture("Textures/VictoryScreenBackground.png"); } Font AssetService::getFont(EFont font, int fontSize) @@ -29,6 +35,12 @@ Font AssetService::getFont(EFont font, int fontSize) return fnt; } +Texture2D AssetService::loadTexture(std::string filename) +{ + Texture2D texture = LoadTexture((assetDir + filename).c_str()); + return texture; +} + std::string AssetService::getFontUrl(EFont font) { return assetDir + fonts[font]; diff --git a/src/services/StateService.cpp b/src/services/StateService.cpp index 7c9c0d2..99cf07b 100644 --- a/src/services/StateService.cpp +++ b/src/services/StateService.cpp @@ -2,6 +2,8 @@ #include "raylib.h" #include "TitleScreen.h" #include "MainScreen.h" +#include "TutorialScreen.h" +#include "GameScreen.h" #include #include "AudioService.h" @@ -15,6 +17,12 @@ void StateService::setScreen(EScreen state) case EScreen::MAIN: currentScreen = std::make_unique(); break; + case EScreen::TUTORIAL: + currentScreen = std::make_unique(); + break; + case EScreen::GAME: + currentScreen = std::make_unique(); + break; case EScreen::CLOSE: gameRunning = false; break; @@ -31,7 +39,7 @@ Screen *StateService::getScreen() void StateService::startGame() { InitAudioDevice(); - InitWindow(640, 544, "Jelly Rescue"); + InitWindow(screenSize.x, screenSize.y, "Jelly Rescue"); SetTargetFPS(60); setScreen(EScreen::TITLE); @@ -53,8 +61,9 @@ void StateService::startGame() void StateService::handleMusic() { std::optional music = AudioService::getInstance().getMusic(); - if(music.has_value()) { - UpdateMusicStream(music.value()); + if (music.has_value()) + { + UpdateMusicStream(music.value()); } } @@ -64,4 +73,3 @@ void StateService::step() currentScreen->draw(); currentScreen->logic(); } -