From 774dc3806b70fd283b14fbd56c101356b5d0eb37 Mon Sep 17 00:00:00 2001 From: Ninjaws Date: Tue, 10 Dec 2024 19:26:48 +0100 Subject: [PATCH] [Added] Start of player class, start of collision detection --- include/entities/Game.h | 19 +++- include/entities/Map.h | 16 ++- include/entities/Player.h | 166 ++++++++++++++++++++++++++++++ include/entities/Text.h | 16 +-- include/entities/TextureWrapper.h | 31 ++++++ include/enums/ECorner.h | 19 ++++ include/enums/ESprite.h | 21 ++++ include/screens/GameScreen.h | 6 +- include/screens/MainScreen.h | 12 +-- include/screens/Screen.h | 11 +- include/screens/TitleScreen.h | 8 +- include/screens/TutorialScreen.h | 9 +- include/services/AssetService.h | 5 + include/services/InputService.h | 12 +++ include/services/MapService.h | 27 +++++ src/entities/Map.cpp | 81 ++++++++++++++- src/services/AssetService.cpp | 15 +++ src/services/StateService.cpp | 9 -- 18 files changed, 433 insertions(+), 50 deletions(-) create mode 100644 include/entities/Player.h create mode 100644 include/enums/ECorner.h create mode 100644 include/enums/ESprite.h create mode 100644 include/services/MapService.h diff --git a/include/entities/Game.h b/include/entities/Game.h index 19eb456..71491ce 100644 --- a/include/entities/Game.h +++ b/include/entities/Game.h @@ -5,6 +5,9 @@ #include "entities/Background.h" #include "services/StateService.h" #include "services/AudioService.h" +#include "services/MapService.h" +#include "services/InputService.h" +#include "entities/Player.h" class Game { @@ -24,6 +27,7 @@ public: wrappers.push_back(wrapper3); this->background = Background(wrappers); this->map = Map(); + MapService::getInstance().setMap(this->map); Vector2 screenSize = StateService::getInstance().getScreenSize(); Camera2D camera = {0}; @@ -33,6 +37,11 @@ public: camera.zoom = 1.0f; this->camera = camera; + this->player = Player(); + this->player.getTexture().setPosition({200,350}); + + InputService::getInstance().setKeysToWatch({KEY_SPACE, KEY_A, KEY_D}, {MOUSE_BUTTON_LEFT}); + AudioService::getInstance().setMusic(EMusic::GAME); AudioService::getInstance().playMusic(); } @@ -42,7 +51,12 @@ public: void logic() { - this->camera.offset.x -= 1.5; + // 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}; + + } } void draw() @@ -52,6 +66,7 @@ public: this->background.draw(); this->map.draw(); + this->player.draw(); EndMode2D(); EndDrawing(); @@ -61,7 +76,7 @@ private: Camera2D camera; Background background; Map map; - // Player player + Player player; // std::vector enemies // std::vector crates // std::vector playerBullets diff --git a/include/entities/Map.h b/include/entities/Map.h index 332caf5..1e68ca8 100644 --- a/include/entities/Map.h +++ b/include/entities/Map.h @@ -3,6 +3,8 @@ #include #include "raylib.h" +#include "entities/TextureWrapper.h" +#include /** * Holds the collision and texture maps for the game world @@ -15,19 +17,27 @@ public: void draw(); + /** Checks and returns which corners of the object have been collided with */ + std::unordered_map checkForCollision(TextureWrapper texture); + 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 */ + /** Holds 1s (collision) and 0s (no collision) for every tile */ std::vector> colMap; - float tileSize = 32; + unsigned int tileSize = 32; Texture2D tileset; void loadMap(); - void loadColMap(){} + void loadColMap(); void loadTileset(); + + /** + * Converts the corners of the object to the matching tiles, so that they can be checked for collision + */ + std::unordered_map cornersToTilePos(std::unordered_map corners); }; #endif \ No newline at end of file diff --git a/include/entities/Player.h b/include/entities/Player.h new file mode 100644 index 0000000..177543d --- /dev/null +++ b/include/entities/Player.h @@ -0,0 +1,166 @@ +#ifndef PLAYER_H +#define PLAYER_H + +#include "raylib.h" +#include +#include "services/AssetService.h" +#include "services/MapService.h" +#include "services/InputService.h" +#include "entities/TextureWrapper.h" +#include "enums/ECorner.h" + +class Player +{ +public: + Player() + { + TextureWrapper wrapper = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER), {32, 32}, {200, 200}); + wrapper.setSourceRect({0, 0, 32, 32}); + this->texture = wrapper; + } + ~Player() + { + } + + void logic() + { + gravity(); + movement(); + handleCollision(); + applyVelocity(); + } + + void draw() + { + DrawTextureRec(this->texture.getTexture(), this->texture.getSourceRect(), this->texture.getPosition(), WHITE); + } + + TextureWrapper &getTexture() + { + return this->texture; + } + +protected: +private: + // Vector2 position; + TextureWrapper texture; + Vector2 velocity = {0, 0}; + + 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 + bool crateTopCollision; + /** + * Holds the corners of the player + * Is used for precise collision detection + */ + // Keeps tracko f whether or not the player has collided with the top of the crate + // std::unordered_map + + void gravity() + { + + // PositionUpdate(); + // Collision(); + + // if (!groundCollision && !crateTopCollision) + // { + if (!groundCollision) + { + velocity.y += 0.6f; + } + else + { + velocity.y = 0.0f; + } + + // if (sf::Keyboard::isKeyPressed(sf::Keyboard::W) && (groundCollision == true || crateTopCollision == true)) + // { + // velocity.y = -GetJumpSpeed(); + // } + + // this->texture.move(velocity); + } + + void movement() + { + velocity.x = 0.0f; + if (InputService::getInstance().isKeyDown(KEY_A)) { + // std::cout << "Left" << std::endl; + velocity.x -= 3.0f; + } else if (InputService::getInstance().isKeyDown(KEY_D)) { + velocity.x += 3.0f; + // std::cout << "Right" << std::endl; + } + + if(InputService::getInstance().isKeyPressed(KEY_SPACE) && groundCollision) { + velocity.y -= 7.2f; + } + + this->texture.move(velocity); + } + + void handleCollision() + { + groundCollision = false; + std::unordered_map collisions = MapService::getInstance().getMap().checkForCollision(this->texture); + + if (collisions[ECorner::BOTTOM_LEFT] || collisions[ECorner::BOTTOM_RIGHT]) + { + this->texture.move({0, -velocity.y}); + velocity.y = 0.0f; + groundCollision = true; + } + if (collisions[ECorner::LEFT_TOP] && collisions[ECorner::LEFT_BOTTOM]) { + this->texture.move({+velocity.x, 0}); + velocity.x = 0.0f; + } + if (collisions[ECorner::TOP_LEFT] || collisions[ECorner::TOP_RIGHT]) { + this->texture.move({0, +velocity.y}); + velocity.y = 0.0f; + } + if (collisions[ECorner::RIGHT_TOP] && collisions[ECorner::RIGHT_BOTTOM]) { + this->texture.move({-velocity.x, 0}); + velocity.x = 0.0f; + } + } + + void applyVelocity() { + // std::cout << velocity.x << std::endl; + this->texture.move(velocity); + } + + // timesCollision.clear(); + + // for (int i = 0; i < tiles.size(); i++) + // { + // if (GetColMap()[tiles[i].y][tiles[i].x] == 1) + // { + // timesCollision.push_back(i); + // } + // } + + // groundCollision = false; + + // if (timesCollision.size() > 0) + // { + // for (int i = 0; i < timesCollision.size(); i++) + // { + // if (timesCollision[i] == 0 || timesCollision[i] == 1) //Topleft and Topright + // { + // velocity.y = 0; + // } + // else if (timesCollision[i] == 2 || timesCollision[i] == 3 || //Lefttop and Leftbottom + // timesCollision[i] == 4 || timesCollision[i] == 5) //Righttop and Lefttop + // { + // velocity.x = 0; + // } + // else if (timesCollision[i] == 6 || timesCollision[i] == 7) //Bottomleft and Bottomright + // { + // groundCollision = true; + // } + // } + // } + // } +}; + +#endif diff --git a/include/entities/Text.h b/include/entities/Text.h index 887108e..21dd3b0 100644 --- a/include/entities/Text.h +++ b/include/entities/Text.h @@ -8,14 +8,6 @@ #include "services/AssetService.h" class Text { - private: - std::string text; - Font font; - int fontSize; - int spacing; - Color color; - Vector2 position; - public: Text(std::string text, EFont font, int fontSize = 30, int spacing = 0, Color color = WHITE, Vector2 position = {100,100}); ~Text(){} @@ -43,6 +35,14 @@ class Text { } void draw(); + + private: + std::string text; + Font font; + int fontSize; + int spacing; + Color color; + Vector2 position; }; #endif \ No newline at end of file diff --git a/include/entities/TextureWrapper.h b/include/entities/TextureWrapper.h index a8d3c8f..0bd2af9 100644 --- a/include/entities/TextureWrapper.h +++ b/include/entities/TextureWrapper.h @@ -2,9 +2,12 @@ #define TEXTURE_WRAPPER_H #include "raylib.h" +#include "enums/ECorner.h" +#include class TextureWrapper { public: + TextureWrapper(){} TextureWrapper(Texture2D texture, Vector2 size = {32,32}, Vector2 position = {0,0}, Rectangle sourceRect = {0,0,32,32}) { this->texture = texture; this->size = size; @@ -34,6 +37,34 @@ class TextureWrapper { this->sourceRect = rect; } + void setPosition(Vector2 position) { + this->position = position; + } + + void move(Vector2 deltaPos) { + this->position = {this->position.x + deltaPos.x, this->position.y + deltaPos.y}; + } + + /** Returns the 4 corners of the texture */ + std::unordered_map getCorners() { + std::unordered_map corners; + float top = this->position.y; + float right = this->position.x+this->size.x; + float bottom = this->position.y + this->size.y; + float left = this->position.x; + float margin = 5; // Space to the corner + corners[ECorner::TOP_LEFT] = {left+margin, top}; + corners[ECorner::TOP_RIGHT] = {right-margin, top}; + corners[ECorner::RIGHT_TOP] = {right, top+margin}; + corners[ECorner::RIGHT_BOTTOM] = {right, bottom-margin}; + corners[ECorner::BOTTOM_RIGHT] = {right-margin, bottom}; + corners[ECorner::BOTTOM_LEFT] = {left+margin, bottom}; + corners[ECorner::LEFT_BOTTOM] = {left, bottom-margin}; + corners[ECorner::LEFT_TOP] = {left, top+margin}; + + return corners; + } + private: Texture2D texture; Rectangle sourceRect; diff --git a/include/enums/ECorner.h b/include/enums/ECorner.h new file mode 100644 index 0000000..e4d46db --- /dev/null +++ b/include/enums/ECorner.h @@ -0,0 +1,19 @@ +#ifndef CORNERS_H +#define CORNERS_H + +/** + * All corners of a GameObject + */ +enum class ECorner { + TOP_LEFT, + TOP_RIGHT, + RIGHT_TOP, + RIGHT_BOTTOM, + BOTTOM_RIGHT, + BOTTOM_LEFT, + LEFT_BOTTOM, + LEFT_TOP +}; + + +#endif \ No newline at end of file diff --git a/include/enums/ESprite.h b/include/enums/ESprite.h new file mode 100644 index 0000000..5e70281 --- /dev/null +++ b/include/enums/ESprite.h @@ -0,0 +1,21 @@ +#ifndef ESPRITE_H +#define ESPRITE_H + +enum class ESprite { + PLAYER, + PLAYER_GUN_LEFT, + PLAYER_GUN_RIGHT, + ENEMY, + ENEMY_GUN_LEFT, + ENEMY_GUN_RIGHT, + CRATE, + JELLY, + HEALTHPACK, + AMMOPACK, + POWERUP, + HUD_HEART, + HUD_HEART_EMPTY, + HUD_AMMO +}; + +#endif \ No newline at end of file diff --git a/include/screens/GameScreen.h b/include/screens/GameScreen.h index eb0847d..a5e7582 100644 --- a/include/screens/GameScreen.h +++ b/include/screens/GameScreen.h @@ -6,13 +6,13 @@ class GameScreen: public Screen { -private: - Game game; -protected: public: GameScreen(); void logic() override; void draw() override; + +private: + Game game; }; #endif \ No newline at end of file diff --git a/include/screens/MainScreen.h b/include/screens/MainScreen.h index 11e061b..34ecc0b 100644 --- a/include/screens/MainScreen.h +++ b/include/screens/MainScreen.h @@ -6,6 +6,12 @@ #include "entities/Text.h" class MainScreen : public Screen { +public: + MainScreen(); + + void logic() override; + void draw() override; + private: int hoveredButton = 0; std::vector buttons; @@ -13,12 +19,6 @@ private: void mouseLogic(); void keyboardLogic(); void clickLogic(); - -public: - MainScreen(); - - void logic() override; - void draw() override; }; #endif \ No newline at end of file diff --git a/include/screens/Screen.h b/include/screens/Screen.h index 955bfe9..90270ec 100644 --- a/include/screens/Screen.h +++ b/include/screens/Screen.h @@ -3,14 +3,6 @@ class Screen { -private: -protected: - // std::optional map; - // std::optional camera; - // std::optional map; - // std::optional background; - // std::vector text; - public: Screen(){} ~Screen() {} @@ -23,6 +15,9 @@ public: * Draw frame to the screen */ virtual void draw() = 0; + +private: + }; #endif diff --git a/include/screens/TitleScreen.h b/include/screens/TitleScreen.h index e04ba18..7975eaa 100644 --- a/include/screens/TitleScreen.h +++ b/include/screens/TitleScreen.h @@ -6,15 +6,15 @@ #include "entities/Text.h" class TitleScreen : public Screen { -private: - Music bg; - std::vector text; - public: TitleScreen(); void logic() override; void draw() override; + +private: + Music bg; + std::vector text; }; #endif \ No newline at end of file diff --git a/include/screens/TutorialScreen.h b/include/screens/TutorialScreen.h index 3a96fe5..2b48387 100644 --- a/include/screens/TutorialScreen.h +++ b/include/screens/TutorialScreen.h @@ -7,17 +7,16 @@ class TutorialScreen : public Screen { -private: - std::vector text; - Background background; - -protected: public: TutorialScreen(); ~TutorialScreen() {} void logic() override; void draw() override; + +private: + std::vector text; + Background background; }; #endif \ No newline at end of file diff --git a/include/services/AssetService.h b/include/services/AssetService.h index c6f405e..5eec69e 100644 --- a/include/services/AssetService.h +++ b/include/services/AssetService.h @@ -9,6 +9,7 @@ #include "enums/EMusic.h" #include "enums/EBackground.h" #include "enums/EMap.h" +#include "enums/ESprite.h" #include "services/Service.h" class AssetService: public Service @@ -27,6 +28,9 @@ public: std::string getMapUrl(EMap map) { return this->assetDir + this->maps[map]; } + Texture2D getSprite(ESprite sprite) { + return this->sprites[sprite]; + } protected: AssetService(); @@ -41,6 +45,7 @@ private: std::unordered_map music; std::unordered_map backgrounds; std::unordered_map maps; + std::unordered_map sprites; void setAssets(); diff --git a/include/services/InputService.h b/include/services/InputService.h index dd7e289..e7f537b 100644 --- a/include/services/InputService.h +++ b/include/services/InputService.h @@ -20,11 +20,13 @@ public: { this->watchedKeys.clear(); this->keysPressed.clear(); + this->keysDown.clear(); for (int i = 0; i < keysToWatch.size(); i++) { this->watchedKeys.insert(keysToWatch[i]); this->keysPressed[keysToWatch[i]] = false; + this->keysDown[keysToWatch[i]] = false; } setMouseButtonsToWatch(mouseButtonsToWatch); @@ -42,10 +44,15 @@ public: for (auto key : watchedKeys) { keysPressed[key] = false; + keysDown[key] = false; if (IsKeyPressed(key)) { keysPressed[key] = true; } + if (IsKeyDown(key)) + { + keysDown[key] = true; + } } for (auto button : watchedMouseButtons) { @@ -62,6 +69,10 @@ public: return keysPressed[key]; } + bool isKeyDown(KeyboardKey key) { + return keysDown[key]; + } + bool isMouseButtonPressed(MouseButton button) { return mouseButtonsPressed[button]; @@ -70,6 +81,7 @@ public: private: std::unordered_set watchedKeys; std::unordered_map keysPressed; + std::unordered_map keysDown; std::unordered_set watchedMouseButtons; std::unordered_map mouseButtonsPressed; diff --git a/include/services/MapService.h b/include/services/MapService.h new file mode 100644 index 0000000..139a60d --- /dev/null +++ b/include/services/MapService.h @@ -0,0 +1,27 @@ +#ifndef MAP_SERVICE_H +#define MAP_SERVICE_H + +#include "services/Service.h" +#include "entities/Map.h" +#include "entities/TextureWrapper.h" + +/** + * Allows all rigidbodies to check against the current Map + */ +class MapService : public Service +{ +public: + void setMap(Map map) + { + this->map = Map(); + } + + Map& getMap() { + return this->map; + } + +private: + Map map; +}; + +#endif \ No newline at end of file diff --git a/src/entities/Map.cpp b/src/entities/Map.cpp index 07224b9..c1ddcc5 100644 --- a/src/entities/Map.cpp +++ b/src/entities/Map.cpp @@ -4,11 +4,13 @@ #include #include #include "services/AssetService.h" +#include "entities/Map.h" Map::Map() { loadTileset(); loadMap(); + loadColMap(); } void Map::loadMap() @@ -78,11 +80,53 @@ void Map::loadMap() } } +void Map::loadColMap() +{ + std::vector tempColMap; + std::ifstream openfile(AssetService::getInstance().getMapUrl(EMap::COLLISION)); + + colMap.clear(); + + if (openfile.is_open()) + { + while (!openfile.eof()) + { + std::string str; + std::getline(openfile, str); + std::stringstream stream(str); + std::string value; + while (std::getline(stream, value, ' ')) + { + if (value.length() > 0) + { + int tempValue = atoi(value.c_str()); + tempColMap.push_back(tempValue); + } + } + colMap.push_back(tempColMap); + tempColMap.clear(); + } + } +} + void Map::loadTileset() { this->tileset = AssetService::getInstance().loadTexture("Textures/tileset.png"); } +std::unordered_map Map::cornersToTilePos(std::unordered_map corners) +{ + // std::cout << "Starting converting" << std::endl; + std::unordered_map cornersTilePos; + for (const auto &pair : corners) + { + // std::cout << "Foreach pair" << std::endl; + Vector2 original = corners[pair.first]; + cornersTilePos[pair.first] = {floorf(original.x / this->tileSize), floorf(original.y / this->tileSize)}; + } + return cornersTilePos; +} + void Map::draw() { for (int i = 0; i < map.size(); i++) @@ -92,8 +136,8 @@ void Map::draw() 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); + Rectangle sourceRect = {map[i][j].x * tileSize, map[i][j].y * tileSize, (float)tileSize, (float)tileSize}; + DrawTextureRec(tileset, sourceRect, {(float)j * tileSize, (float)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); @@ -101,3 +145,36 @@ void Map::draw() } } } + +std::unordered_map Map::checkForCollision(TextureWrapper texture) +{ + // std::cout << "Converting.." << std::endl; + std::unordered_map cornersTilePos = cornersToTilePos(texture.getCorners()); + // std::cout << "Done with converting" << std::endl; + + std::unordered_map cornerCollisions; + + for (const auto &pair : cornersTilePos) + { + // std::cout << "foreach collision check" << std::endl; + Vector2 pos = cornersTilePos[pair.first]; + // std::cout << pos.x << " " << pos.y << std::endl; + if(colMap[pos.y][pos.x] == 1) { + cornerCollisions[pair.first] = true; + } else { + cornerCollisions[pair.first] = false; + } + } + // std::cout << "Finished collision checks" << std::endl; + + return cornerCollisions; + + // for (int i = 0; i < tiles.size(); i++) + // { + // if (colMap[tiles[i].y][tiles[i].x] == 1) + // { + // timesCollision.push_back(i); + // } + // } + +} diff --git a/src/services/AssetService.cpp b/src/services/AssetService.cpp index d6f6ce9..06039a9 100644 --- a/src/services/AssetService.cpp +++ b/src/services/AssetService.cpp @@ -28,6 +28,21 @@ void AssetService::setAssets() maps[EMap::TEXTURE] = "Maps/map1.txt"; maps[EMap::COLLISION] = "Maps/colmap1.txt"; + + sprites[ESprite::PLAYER] = loadTexture("Textures/player.png"); + sprites[ESprite::PLAYER_GUN_LEFT] = loadTexture("Textures/gunleft.png"); + sprites[ESprite::PLAYER_GUN_RIGHT] = loadTexture("Textures/gunright.png"); + sprites[ESprite::ENEMY] = loadTexture("Textures/enemy.png"); + sprites[ESprite::ENEMY_GUN_LEFT] = loadTexture("Textures/gunleft_2.png"); + sprites[ESprite::ENEMY_GUN_RIGHT] = loadTexture("Textures/gunright_2.png"); + sprites[ESprite::CRATE] = loadTexture("Textures/woodencrate.png"); + sprites[ESprite::JELLY] = loadTexture("Textures/happyjelly.png"); + sprites[ESprite::HEALTHPACK] = loadTexture("Textures/FirstAidKit.png"); + sprites[ESprite::AMMOPACK] = loadTexture("Textures/Bullets_small.png"); + sprites[ESprite::POWERUP] = loadTexture("Textures/powerUpAnimation.png"); + sprites[ESprite::HUD_HEART] = loadTexture("Textures/heart.png"); + sprites[ESprite::HUD_HEART_EMPTY] = loadTexture("Textures/heart_empty.png"); + sprites[ESprite::HUD_AMMO] = loadTexture("Textures/bullet_hud.png"); } Font AssetService::getFont(EFont font, int fontSize) diff --git a/src/services/StateService.cpp b/src/services/StateService.cpp index a37b200..9c56ebf 100644 --- a/src/services/StateService.cpp +++ b/src/services/StateService.cpp @@ -89,13 +89,4 @@ void StateService::step() handleMusic(); currentScreen->draw(); currentScreen->logic(); - // if (IsKeyPressed(KEY_ENTER) || IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) - // { - // setScreen(EScreen::MAIN); - // } - // if(instance) { - // instance->handleMusic(); - // instance->currentScreen->draw(); - // instance->currentScreen->logic(); - // } }