diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index a4fc976..0e4d1b2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -28,8 +28,7 @@ "settings": {}, "extensions": [ "esbenp.prettier-vscode", - "ms-vscode.cpptools-extension-pack", - "jeff-hykin.better-cpp-syntax" + "ms-vscode.cpptools-extension-pack" ] } }, diff --git a/include/entities/Game.h b/include/entities/Game.h index 326969d..d75d022 100644 --- a/include/entities/Game.h +++ b/include/entities/Game.h @@ -45,6 +45,9 @@ public: this->player = Player(); this->player.getTexture().setPosition({200, 350}); + + this->crosshair = TextureWrapper(AssetService::getInstance().getSprite(ESprite::CROSSHAIR), {15,15}, {0,0}, {0,0,15,15}); + initPauseScreen(); initGameOverScreen(); @@ -82,7 +85,7 @@ public: void initGameOverScreen() { - this->gameOverText = Text("game over", EFont::OXIN, 60, 0, WHITE); + this->gameOverText = Text("Game Over", EFont::SANSATION, 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; @@ -92,11 +95,11 @@ public: 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); + Text txt = Text("Play Again", EFont::SANSATION, 30, 0, GRAY); gameOverScreenButtons.push_back(txt); } - gameOverScreenButtons[0].setColor(BLACK); - gameOverScreenButtons[1].setText("quit to main menu"); + gameOverScreenButtons[0].setColor(WHITE); + 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}); @@ -105,6 +108,8 @@ public: void logic() { + this->crosshair.setPosition(GetMousePosition()); + if (GameService::getInstance().isPaused()) { pausedLogic(); @@ -164,25 +169,25 @@ public: { if (InputService::getInstance().isKeyPressed(KEY_D) || InputService::getInstance().isKeyPressed(KEY_A)) { - gameOverScreenButtons[hoveredGameOverScreenButton].setColor(WHITE); + gameOverScreenButtons[hoveredGameOverScreenButton].setColor(GRAY); /** 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); + gameOverScreenButtons[hoveredGameOverScreenButton].setColor(WHITE); } if (InputService::getInstance().isKeyPressed(KEY_ENTER)) { - GameService::getInstance().setGameOver(false); std::string selectedButton = gameOverScreenButtons[hoveredGameOverScreenButton].getText(); - if (selectedButton == "play again") + if (selectedButton == "Play Again") { StateService::getInstance().setScreen(EScreen::GAME); } - else if (selectedButton == "quit to main menu") + else if (selectedButton == "Quit to Main Menu") { StateService::getInstance().setScreen(EScreen::MAIN); } + GameService::getInstance().setGameOver(false); } } @@ -205,6 +210,7 @@ public: { drawGameOver(); } + drawCrosshair(); EndDrawing(); } @@ -233,11 +239,22 @@ public: } } + void drawCrosshair() { + DrawTextureEx(this->crosshair.getTexture(),GetMousePosition(),0,1.2f,RED); + // DrawTexturePro( + // this->crosshair.getTexture(), + // this->crosshair.getSourceRect(), + // {GetMousePosition().x, GetMousePosition().y, GetMousePosition().x+this->crosshair.getSize().x, GetMousePosition().y+this->crosshair.getSize().y}, + // {this->crosshair.getSize().x/2.0f, this->crosshair.getSize().y/2.0f}, + // 0, + // WHITE); + } private: Camera2D camera; Background background; Map map; Player player; + TextureWrapper crosshair; std::vector pauseScreenButtons; int hoveredPauseScreenButton = 0; diff --git a/include/entities/Map.h b/include/entities/Map.h index 7aeece0..c16fcd3 100644 --- a/include/entities/Map.h +++ b/include/entities/Map.h @@ -24,6 +24,10 @@ public: return this->tileSize; } + std::vector> getColMap() { + return this->colMap; + } + private: /** Holds the number for every single tile, which refers to a certain sprite in the tileset */ std::vector> map; diff --git a/include/entities/Player.h b/include/entities/Player.h index bafc08c..2cb07e5 100644 --- a/include/entities/Player.h +++ b/include/entities/Player.h @@ -9,6 +9,7 @@ #include "services/GameService.h" #include "entities/TextureWrapper.h" #include "enums/ECorner.h" +#include "entities/Vector2i.h" class Player { @@ -18,6 +19,8 @@ public: TextureWrapper wrapper = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER), {32, 32}, {200, 200}); wrapper.setSourceRect({0, 0, 32, 32}); this->texture = wrapper; + prevFrame = GetTime(); + spriteAnimation = {0,0}; } ~Player() { @@ -25,9 +28,9 @@ public: void logic() { - applyGravity(); + // applyGravity(); movement(); - handleCollision(); + // handleCollision(); outofboundsCheck(); } @@ -48,6 +51,11 @@ private: float jumpPower = 7.2f; float moveSpeed = 5.0f; float gravity = 0.6f; + float animationDelay = 0.2f; // seconds + double prevFrame; + Vector2 spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Player direction + enum Direction { Down, Left, Right, Up }; // Used in conjuction with spriteAnimation, makes sure sprite direction matches with player direction + std::vector tiles; // Holds eight points of the player for accurate collision 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 @@ -71,20 +79,86 @@ private: void movement() { - velocity.x = 0.0f; if (InputService::getInstance().isKeyDown(KEY_A)) { - velocity.x -= moveSpeed; + spriteAnimation.y = Left; + velocity.x = -moveSpeed; + animate(); } else if (InputService::getInstance().isKeyDown(KEY_D)) { - velocity.x += moveSpeed; + spriteAnimation.y = Right; + velocity.x = moveSpeed; + animate(); + } else { + velocity.x = 0.0f; + } + positionUpdates(); + handleCollision(); + + if (!groundCollision) { + velocity.y += gravity; + } else { + velocity.y = 0.0f; } if (InputService::getInstance().isKeyPressed(KEY_W) && groundCollision) { velocity.y -= jumpPower; } + + this->texture.move(velocity); + } + + void animate() + { + if (GetTime() - prevFrame > animationDelay) + { + spriteAnimation.x = std::fmod(spriteAnimation.x + 1,3); + + Rectangle sourceRect = this->texture.getSourceRect(); + sourceRect.x = spriteAnimation.x * this->texture.getSize().x; + sourceRect.y = spriteAnimation.y * this->texture.getSize().y; + // sourceRect.x = std::fmod(sourceRect.x, 3 * this->texture.getSize().x); + this->texture.setSourceRect(sourceRect); + prevFrame = GetTime(); + } + } + + void positionUpdates() { + const Vector2 pos = this->texture.getPosition(); + const Vector2 size = this->texture.getSize(); + const int tileSize = MapService::getInstance().getMap().getTileSize(); + + const float bottom = pos.y + size.y + velocity.y; + const float left = pos.x + velocity.x; + const float right = pos.x + size.x + velocity.x; + const float top = pos.y + velocity.y; + + Vector2i topLeft(Vector2i((int)(left + 5) / tileSize, (int)top / tileSize)); // +5 to separate top from side + Vector2i topRight(Vector2i((int)(right - 5) / tileSize, (int)top / tileSize)); // -5 to separate top from side + + Vector2i leftTop(Vector2i((int)left / tileSize, (int)(top + 5) / tileSize)); + Vector2i leftBottom(Vector2i((int)left / tileSize, (int)(bottom - 5) / tileSize)); + Vector2i rightTop(Vector2i((int)right / tileSize, (int)(top + 5) / tileSize)); + Vector2i rightBottom(Vector2i((int)right / tileSize, (int)(bottom - 5) / tileSize)); + + Vector2i bottomLeft(Vector2i((int)(left + 5) / tileSize, (int)bottom / tileSize)); // +5 to separate bottom from side + Vector2i bottomRight(Vector2i((int)(right - 5) / tileSize, (int)bottom / tileSize)); // -5 to separate bottom from side + + + tiles.clear(); + + tiles.push_back(topLeft); + tiles.push_back(topRight); + + tiles.push_back(leftTop); + tiles.push_back(leftBottom); + tiles.push_back(rightTop); + tiles.push_back(rightBottom); + + tiles.push_back(bottomLeft); + tiles.push_back(bottomRight); } /** @@ -95,37 +169,93 @@ private: */ void handleCollision() { - Vector2 tempPos = this->texture.getPosition(); - this->texture.move(velocity); - groundCollision = false; - std::unordered_map collisions = MapService::getInstance().getMap().checkForCollision(this->texture); + timesCollision.clear(); - if (collisions[ECorner::BOTTOM_LEFT] || collisions[ECorner::BOTTOM_RIGHT]) + for (int i = 0; i < tiles.size(); i++) + { + if (MapService::getInstance().getMap().getColMap()[tiles[i].y][tiles[i].x] == 1) { - velocity.y = 0.0f; - groundCollision = true; - this->texture.setPosition({this->texture.getPosition().x, floorf(this->texture.getPosition().y / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize()}); - } - if (collisions[ECorner::LEFT_TOP] && collisions[ECorner::LEFT_BOTTOM]) - { - velocity.x = 0.0f; - this->texture.setPosition({ceilf(this->texture.getPosition().x / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize(), this->texture.getPosition().y}); - } - if (collisions[ECorner::TOP_LEFT] || collisions[ECorner::TOP_RIGHT]) - { - velocity.y = 0.0f; - this->texture.setPosition({this->texture.getPosition().x, (ceilf(this->texture.getPosition().y / MapService::getInstance().getMap().getTileSize())) * MapService::getInstance().getMap().getTileSize()}); - } - if (collisions[ECorner::RIGHT_TOP] && collisions[ECorner::RIGHT_BOTTOM]) - { - velocity.x = 0.0f; - this->texture.setPosition({floorf(this->texture.getPosition().x / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize(), this->texture.getPosition().y}); + timesCollision.push_back(i); } } - void outofboundsCheck() { - if(this->texture.getPosition().y > StateService::getInstance().getScreenSize().y) { + 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; + } + } + } + + // Set velocity.x based on going right or left + + // Take current position of all 4 corners + // Apply velocity + // Calculate the 8 points + // Add them to a list + + // Empty vector of amount of collisions + // Loop through the points + // Check the collisionmap for intersection + // If so, add item to the vector of collisions + + // Set groundcollision to false + // Loop through collisions + // Based on their location (TopLeft, RightTop, etc) change the velocity + + // Apply gravity if not on the floor + // If jumping and on the floor, go up + + // Move using velocity + + // Vector2 tempPos = this->texture.getPosition(); + // this->texture.move(velocity); + + // groundCollision = false; + // std::unordered_map collisions = MapService::getInstance().getMap().checkForCollision(this->texture); + + // if (collisions[ECorner::BOTTOM_LEFT] || collisions[ECorner::BOTTOM_RIGHT]) + // { + // velocity.y = 0.0f; + // groundCollision = true; + // this->texture.setPosition({this->texture.getPosition().x, floorf(this->texture.getPosition().y / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize()}); + // } + // if (collisions[ECorner::LEFT_TOP] && collisions[ECorner::LEFT_BOTTOM]) + // { + // velocity.x = 0.0f; + // this->texture.setPosition({ceilf(this->texture.getPosition().x / MapService::getInstance().getMap().getTileSize()) * MapService::getInstance().getMap().getTileSize(), this->texture.getPosition().y}); + // } + // if (collisions[ECorner::TOP_LEFT] || collisions[ECorner::TOP_RIGHT]) + // { + // velocity.y = 0.0f; + // this->texture.setPosition({this->texture.getPosition().x, (ceilf(this->texture.getPosition().y / MapService::getInstance().getMap().getTileSize())) * MapService::getInstance().getMap().getTileSize()}); + // } + // if (collisions[ECorner::RIGHT_TOP] && collisions[ECorner::RIGHT_BOTTOM]) + // { + // velocity.x = 0.0f; + // 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(); diff --git a/include/entities/Vector2i.h b/include/entities/Vector2i.h new file mode 100644 index 0000000..950533a --- /dev/null +++ b/include/entities/Vector2i.h @@ -0,0 +1,15 @@ +#ifndef VECTOR2I_H +#define VECTOR2I_H + +class Vector2i { + public: + Vector2i(){} + Vector2i (int x, int y) { + this->x = x; + this->y = y; + } + int x; + int y; +}; + +#endif \ No newline at end of file diff --git a/include/enums/ESprite.h b/include/enums/ESprite.h index 5e70281..932595c 100644 --- a/include/enums/ESprite.h +++ b/include/enums/ESprite.h @@ -15,7 +15,8 @@ enum class ESprite { POWERUP, HUD_HEART, HUD_HEART_EMPTY, - HUD_AMMO + HUD_AMMO, + CROSSHAIR }; #endif \ No newline at end of file diff --git a/src/screens/MainScreen.cpp b/src/screens/MainScreen.cpp index 40738e3..54c9d18 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_W, KEY_S}, {MOUSE_BUTTON_LEFT}); + InputService::getInstance().setKeysToWatch({KEY_ENTER, KEY_W, KEY_S}, {}); } void MainScreen::logic() @@ -44,7 +44,7 @@ void MainScreen::logic() // std::cout << mouseD.y <background = Background(EBackground::TUTORIAL); - InputService::getInstance().setKeysToWatch({KEY_ENTER}, {MOUSE_BUTTON_LEFT}); + InputService::getInstance().setKeysToWatch({KEY_ENTER},{}); } void TutorialScreen::logic() { - if ( InputService::getInstance().isKeyPressed(KEY_ENTER) || InputService::getInstance().isMouseButtonPressed(MOUSE_BUTTON_LEFT)) + if ( InputService::getInstance().isKeyPressed(KEY_ENTER)) { StateService::getInstance().setScreen(EScreen::MAIN); } diff --git a/src/services/AssetService.cpp b/src/services/AssetService.cpp index b99907b..7a75245 100644 --- a/src/services/AssetService.cpp +++ b/src/services/AssetService.cpp @@ -43,6 +43,7 @@ void AssetService::setAssets() 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"); + sprites[ESprite::CROSSHAIR] = loadTexture("Textures/crosshair_3.png"); } Font AssetService::getFont(EFont font, int fontSize) diff --git a/src/services/StateService.cpp b/src/services/StateService.cpp index ce1a975..8115e18 100644 --- a/src/services/StateService.cpp +++ b/src/services/StateService.cpp @@ -45,10 +45,11 @@ void StateService::startGame() { // if(!instance) // return; - InitAudioDevice(); + // InitAudioDevice(); // InitWindow(640,544, "Jelly Rescue"); InitWindow(screenSize.x, screenSize.y, "Jelly Rescue"); - SetTargetFPS(60); + SetTargetFPS(45); + HideCursor(); // #if defined(PLATFORM_WEB) // emscripten_set_keypress_callback(EMSCRIPTEN_EVENT_TARGET_CANVAS, nullptr, 1, staticStep); @@ -74,7 +75,7 @@ void StateService::startGame() #endif CloseWindow(); - CloseAudioDevice(); + // CloseAudioDevice(); } void StateService::handleMusic()