From 55792bb9548c0e39c38f1440ae10d783dfd3167b Mon Sep 17 00:00:00 2001 From: Ninjaws Date: Fri, 13 Dec 2024 22:04:33 +0100 Subject: [PATCH] [Added] The ability to fire bullets to the player --- include/entities/Bullet.h | 83 +++++++++++++++++++++++++++++++++ include/entities/EBullet.h | 20 ++++++++ include/entities/Game.h | 25 +++++++--- include/entities/PBullet.h | 23 +++++++++ include/entities/Player.h | 55 ++++++++++++++++++++-- include/services/GameService.h | 57 ++++++++++++++++++++++ include/services/InputService.h | 12 +++++ 7 files changed, 266 insertions(+), 9 deletions(-) create mode 100644 include/entities/Bullet.h create mode 100644 include/entities/EBullet.h create mode 100644 include/entities/PBullet.h diff --git a/include/entities/Bullet.h b/include/entities/Bullet.h new file mode 100644 index 0000000..b623fb7 --- /dev/null +++ b/include/entities/Bullet.h @@ -0,0 +1,83 @@ +#ifndef BULLET_H +#define BULLET_H + +#include "raylib.h" +#include +#include "entities/TextureWrapper.h" +#include "entities/Vector2i.h" +#include "services/MapService.h" +#include + +class Bullet +{ +public: + Bullet() {} + Bullet(Vector2 pos, float direction) + { + this->position = pos; + this->direction = direction; + std::cout << direction << std::endl; + } + + // ~Bullet() {} + + void logic() + { + move(); + hasCollided = false; + envCollision(); + objCollision(); + // // detectCollision(); + } + + void draw() + { + DrawCircle(position.x, position.y, size, color); + } + + bool getHasCollided() + { + return this->hasCollided; + } + +protected: + Color color = RED; + +private: + // TextureWrapper object; + Vector2 position; + float direction; + float velocity = 15.0f; + int size = 7; + bool hasCollided = false; + + void move() + { + // float directionInRadians = this->direction * M_PI / 180.0f; + position.x += velocity * cos(direction); + position.y += velocity * sin(direction); + } + void envCollision() + { + if (position.y < 0 || position.y > GetScreenHeight()) + { + hasCollided = true; + return; + } + + const int tileSize = MapService::getInstance().getMap().getTileSize(); + Vector2i tilePos = Vector2i((int)this->position.x / tileSize, (int)this->position.y / tileSize); + if (MapService::getInstance().getMap().getColMap()[tilePos.y][tilePos.x] == 1) + { + hasCollided = true; + return; + } + } + virtual void objCollision() = 0; + + // void handleCollision() { + + // } +}; + +#endif \ No newline at end of file diff --git a/include/entities/EBullet.h b/include/entities/EBullet.h new file mode 100644 index 0000000..3118b9b --- /dev/null +++ b/include/entities/EBullet.h @@ -0,0 +1,20 @@ +// #ifndef EBULLET_H +// #define EBULLET_H + +// #include "Bullet.h" +// #include + +// class EBullet : public Bullet { +// public: + +// EBullet() {} +// ~EBullet() {} + +// void detectCollision() override { +// std::cout << "Enemy bullets" << std::endl; +// } +// private: + +// }; + +// #endif \ No newline at end of file diff --git a/include/entities/Game.h b/include/entities/Game.h index 7d61180..2639fe0 100644 --- a/include/entities/Game.h +++ b/include/entities/Game.h @@ -10,14 +10,15 @@ #include "services/GameService.h" #include "entities/Player.h" #include "entities/Text.h" +#include "entities/Bullet.h" +#include "entities/PBullet.h" class Game { public: Game() { - GameService::getInstance().setGameOver(false); - GameService::getInstance().setPaused(false); + GameService::getInstance().resetGame(); 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}); @@ -42,10 +43,8 @@ public: camera.zoom = 1.0f; // this->camera = camera; GameService::getInstance().setCamera(camera); - this->player = Player(); this->player.setPosition({200, 350}); - this->crosshair = TextureWrapper(AssetService::getInstance().getSprite(ESprite::CROSSHAIR), {15, 15}, {0, 0}, {0, 0, 15, 15}); initPauseScreen(); @@ -81,7 +80,9 @@ public: AudioService::getInstance().pauseMusic(); return; } - // this->camera.offset.x -= 1.5; + + GameService::getInstance().bulletLogic(); + this->player.logic(); if (this->player.getTexture().getPosition().x > (StateService::getInstance().getScreenSize().x / 2.0f)) { @@ -95,6 +96,13 @@ public: BeginMode2D(GameService::getInstance().getCamera()); this->background.draw(); + + // std::vector pbs = GameService::getInstance().getPlayerBullets(); + // for (int i = 0; i < GameService::getInstance().getPlayerBullets().size(); i++) + // { + // GameService::getInstance().getPlayerBullets()[i].draw(); + // } + GameService::getInstance().drawBullets(); this->map.draw(); this->player.draw(); @@ -126,12 +134,13 @@ private: std::vector gameOverScreenButtons; int hoveredGameOverScreenButton = 0; + // std::vector playerBullets; + // bool isPaused = false; // bool isGameOver = false; // std::vector enemies // std::vector crates - // std::vector playerBullets // std::vector enemyBullets // std::vector jellies // std::vector ammo @@ -241,6 +250,10 @@ private: } } + void shootLogic() + { + } + void drawPaused() { // 100, 100, 255, 60 diff --git a/include/entities/PBullet.h b/include/entities/PBullet.h new file mode 100644 index 0000000..f440ba7 --- /dev/null +++ b/include/entities/PBullet.h @@ -0,0 +1,23 @@ +#ifndef PBULLET_H +#define PBULLET_H + +#include "entities/Bullet.h" +#include + +class PBullet : public Bullet { +public: + + PBullet() {} + PBullet(Vector2 pos, float angle) : Bullet(pos, angle) { + this->color = YELLOW; + } + + +private: + void objCollision() override { + + } + +}; + +#endif \ No newline at end of file diff --git a/include/entities/Player.h b/include/entities/Player.h index e530e19..c260ce1 100644 --- a/include/entities/Player.h +++ b/include/entities/Player.h @@ -10,6 +10,7 @@ #include "entities/TextureWrapper.h" #include "enums/ECorner.h" #include "entities/Vector2i.h" +#include "entities/PBullet.h" class Player { @@ -22,6 +23,8 @@ public: spriteAnimation = {0, 0}; this->gunRight = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER_GUN_RIGHT), {58, 29}, {0, 0}); this->gunLeft = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER_GUN_LEFT), {58, 29}, {0, 0}); + this->ammo = max_ammo; + this->prevShot = GetTime(); } ~Player() { @@ -30,6 +33,7 @@ public: void logic() { rotateGun(); + shoot(); movement(); outofboundsCheck(); } @@ -59,9 +63,9 @@ private: float jumpPower = 7.2f; float moveSpeed = 5.0f; float gravity = 0.6f; - float animationDelay = 0.2f; // In seconds + float animationDelay = 0.2f; // In seconds double prevFrame; - Vector2 spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Player direction + Vector2 spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Player direction enum Direction { Down, @@ -70,11 +74,16 @@ private: 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 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 bool crateTopCollision; // Whether the player is standing on top of a crate + int ammo; + int max_ammo = 100; + float firingRate= 0.2f; // Delay in seconds + double prevShot; // The last time the player fired a bullet + void applyGravity() { if (!groundCollision) @@ -320,6 +329,46 @@ private: WHITE); } } + + void shoot() + { + if (InputService::getInstance().isMouseButtonDown(MOUSE_BUTTON_LEFT) && GetTime() - prevShot > firingRate && groundCollision) + { + prevShot = GetTime(); + if (ammo == 0) { + // Play empty gun sound + return; + } + // Play shooting sound + ammo--; + Vector2 bulletStartLocation = {this->texture.getPosition().x + 10, this->texture.getPosition().y + 10}; + + Vector2 mouseWorldPos = GameService::getInstance().getMouseWorldPos(); + + if (spriteAnimation.y == Left) + { + bulletStartLocation.y = this->texture.getPosition().y + 10; + bulletStartLocation.x = this->texture.getPosition().x - 5; + } + if (spriteAnimation.y == Right) + { + bulletStartLocation.y = this->texture.getPosition().y + 10; + bulletStartLocation.x = this->texture.getPosition().x + 37; + } + + if (mouseWorldPos.x > this->texture.getPosition().x + (this->gunLeft.getSize().x) && spriteAnimation.y == Right || + mouseWorldPos.x + (this->gunLeft.getSize().x / 2) < this->texture.getPosition().x && spriteAnimation.y == Left) + { + // PlayGunSound(); + // currentAmmo--; + // .push_back(bulletStartLocation); + float angleShot = atan2(mouseWorldPos.y - bulletStartLocation.y, + mouseWorldPos.x - bulletStartLocation.x); + GameService::getInstance().addPlayerBullet(PBullet(bulletStartLocation, angleShot)); + // bulletDirections.push_back(angleShot); + } + } + } }; #endif diff --git a/include/services/GameService.h b/include/services/GameService.h index d98fd3f..dcf1ebd 100644 --- a/include/services/GameService.h +++ b/include/services/GameService.h @@ -3,6 +3,9 @@ #include "services/Service.h" #include "entities/Game.h" +#include "entities/PBullet.h" +#include +#include class GameService : public Service { @@ -52,10 +55,64 @@ public: // return this->game; // } + void addPlayerBullet(PBullet bullet) + { + this->playerBullets.push_back(bullet); + } + + // std::list& getPlayerBullets() { + // return this->playerBullets; + // } + + // void removeCollidedBullets() + // { + // for (auto it = playerBullets.begin(); it != playerBullets.end(); /* no increment here */) + // { + // if (it->getHasCollided()) + // { + // it = playerBullets.erase(it); // Remove element and get the next valid iterator + // } + // else + // { + // ++it; // Only increment if no removal happens + // } + // } + // } + + void bulletLogic() + { + for (auto it = this->playerBullets.begin(); it != this->playerBullets.end();) + { + it->logic(); + if (it->getHasCollided()) + it = this->playerBullets.erase(it); + else + ++it; + } + } + + void drawBullets() + { + for (auto it = this->playerBullets.begin(); it != this->playerBullets.end();) + { + it->draw(); + ++it; + } + } + + void resetGame() + { + paused = false; + gameOver = false; + // playerBullets.clear(); + } + private: bool paused = false; bool gameOver = false; Camera2D camera; + + std::list playerBullets; }; #endif \ No newline at end of file diff --git a/include/services/InputService.h b/include/services/InputService.h index e7f537b..84b06bc 100644 --- a/include/services/InputService.h +++ b/include/services/InputService.h @@ -57,10 +57,15 @@ public: for (auto button : watchedMouseButtons) { mouseButtonsPressed[button] = false; + mouseButtonsDown[button] = false; if (IsMouseButtonPressed(button)) { mouseButtonsPressed[button] = true; } + if (IsMouseButtonDown(button)) + { + mouseButtonsDown[button] = true; + } } } @@ -78,22 +83,29 @@ public: return mouseButtonsPressed[button]; } + bool isMouseButtonDown(MouseButton button) { + return mouseButtonsDown[button]; + } + private: std::unordered_set watchedKeys; std::unordered_map keysPressed; std::unordered_map keysDown; std::unordered_set watchedMouseButtons; std::unordered_map mouseButtonsPressed; + std::unordered_map mouseButtonsDown; void setMouseButtonsToWatch(std::vector mouseButtonsToWatch) { this->watchedMouseButtons.clear(); this->mouseButtonsPressed.clear(); + this->mouseButtonsDown.clear(); for (int i = 0; i < mouseButtonsToWatch.size(); i++) { this->watchedMouseButtons.insert(mouseButtonsToWatch[i]); this->mouseButtonsPressed[mouseButtonsToWatch[i]] = false; + this->mouseButtonsDown[mouseButtonsToWatch[i]] = false; } } };