From 5af531a08b4230a3732b4fcbfafc0fc9e3fb281d Mon Sep 17 00:00:00 2001 From: Ninjaws Date: Sun, 15 Dec 2024 20:14:57 +0100 Subject: [PATCH] [Added] Jellies, healthpacks, ammopacks, powerups, [Updated] Gun rotation --- .devcontainer/devcontainer.json | 3 +- .vscode/settings.json | 58 ++++++ include/entities/AmmoPack.h | 43 +++++ include/entities/Background.h | 6 + include/entities/Bullet.h | 2 +- include/entities/Crate.h | 7 +- include/entities/Game.h | 46 +++-- include/entities/HealthPack.h | 43 +++++ include/entities/Jelly.h | 50 +++++ include/entities/PBullet.h | 4 +- include/entities/Player.h | 137 +++++++++----- include/entities/Powerup.h | 58 ++++++ include/services/CollectableService.h | 251 ++++++++++++++++++-------- include/services/GameService.h | 7 - src/services/AssetService.cpp | 4 +- 15 files changed, 564 insertions(+), 155 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 include/entities/AmmoPack.h create mode 100644 include/entities/HealthPack.h create mode 100644 include/entities/Jelly.h create mode 100644 include/entities/Powerup.h diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 462a8c6..367e543 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -20,7 +20,8 @@ "source=./scripts,target=/app/scripts,type=bind", "source=./dist,target=/app/dist,type=bind", "source=./assets,target=/app/assets,type=bind", - "source=./include,target=/app/include,type=bind" + "source=./include,target=/app/include,type=bind", + "source=./.vscode,target=/app/.vscode,type=bind" ], "customizations": { diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5a12027 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,58 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "span": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "format": "cpp", + "text_encoding": "cpp" + } +} \ No newline at end of file diff --git a/include/entities/AmmoPack.h b/include/entities/AmmoPack.h new file mode 100644 index 0000000..3c631ea --- /dev/null +++ b/include/entities/AmmoPack.h @@ -0,0 +1,43 @@ +#ifndef AMMO_PACK_H +#define AMMO_PACK_H + +#include "raylib.h" +#include "services/AssetService.h" +#include "entities/TextureWrapper.h" + +class AmmoPack { + public: + AmmoPack() { + this->object = TextureWrapper(AssetService::getInstance().getSprite(ESprite::AMMOPACK),{32,32}); + } + void logic(){ + } + + void draw() { + DrawTexture(object.getTexture(), object.getPosition().x, object.getPosition().y, WHITE); + } + + int getAmmoAmount() { + return this->ammoAmount; + } + + void setPickedUp(bool pickedUp) { + this->pickedUp = pickedUp; + } + + bool hasBeenPickedUp() { + return this->pickedUp; + } + + TextureWrapper& getObject() { + return this->object; + } + + private: + TextureWrapper object; + unsigned int ammoAmount = 10; // Amount of ammo replenished by the pack + bool pickedUp; // When the player has picked up the pack +}; + + +#endif \ No newline at end of file diff --git a/include/entities/Background.h b/include/entities/Background.h index dc9ad8b..a5cd0ed 100644 --- a/include/entities/Background.h +++ b/include/entities/Background.h @@ -35,6 +35,12 @@ class Background { DrawTextureRec(texture.getTexture(), texture.getSourceRect(), texture.getPosition(),WHITE); } } + + Vector2 getBackgroundSize() { + TextureWrapper lastbg = this->textures[this->textures.size()-1]; + return {lastbg.getPosition().x + lastbg.getSize().x, lastbg.getPosition().y + lastbg.getSize().y}; + } + private: std::vector textures; // Vector2 position; diff --git a/include/entities/Bullet.h b/include/entities/Bullet.h index d65ff65..2986310 100644 --- a/include/entities/Bullet.h +++ b/include/entities/Bullet.h @@ -31,7 +31,7 @@ public: void draw() { - DrawCircle(position.x, position.y, size, color); + DrawCircleGradient(position.x, position.y, size, color, BLUE); } bool getHasCollided() diff --git a/include/entities/Crate.h b/include/entities/Crate.h index 3f31bce..9e81e63 100644 --- a/include/entities/Crate.h +++ b/include/entities/Crate.h @@ -37,12 +37,7 @@ public: private: TextureWrapper texture; - bool hit; // Whether a PBullet has hit the create + bool hit; // Whether a PBullet has hit the crate }; - - - - - #endif \ No newline at end of file diff --git a/include/entities/Game.h b/include/entities/Game.h index 3c797ab..630b2ea 100644 --- a/include/entities/Game.h +++ b/include/entities/Game.h @@ -13,6 +13,7 @@ #include "entities/Text.h" #include "entities/Bullet.h" #include "entities/PBullet.h" +#include class Game { @@ -25,7 +26,7 @@ public: 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}); + TextureWrapper wrapper3 = TextureWrapper(AssetService::getInstance().getBackground(EBackground::GAME3), {1728.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; @@ -50,6 +51,7 @@ public: CollectableService::getInstance().initCollectables(); + initHud(); initPauseScreen(); initGameOverScreen(); @@ -88,7 +90,8 @@ public: CollectableService::getInstance().collectableLogic(); this->player.logic(); - if (this->player.getTexture().getPosition().x > (StateService::getInstance().getScreenSize().x / 2.0f)) + if (this->player.getTexture().getPosition().x > (StateService::getInstance().getScreenSize().x / 2.0f) && + this->player.getTexture().getPosition().x + (StateService::getInstance().getScreenSize().x / 2.0f) < background.getBackgroundSize().x) { GameService::getInstance().getCamera().offset = {(StateService::getInstance().getScreenSize().x / 2.0f) + ((StateService::getInstance().getScreenSize().x / 2.0f) - this->player.getTexture().getPosition().x), StateService::getInstance().getScreenSize().y / 2.0f}; } @@ -140,18 +143,14 @@ private: std::vector gameOverScreenButtons; int hoveredGameOverScreenButton = 0; - // std::vector playerBullets; + // Font hudJellyFont; + Text hudJellyText; + TextureWrapper hudJellyTexture; - // bool isPaused = false; - // bool isGameOver = false; - - // std::vector enemies - // std::vector crates - // std::vector enemyBullets - // std::vector jellies - // std::vector ammo - // std::vector healthpacks - // Powerup powerup + void initHud() { + hudJellyTexture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY),{32,32},{500,5}); + hudJellyText = Text("0/3",EFont::SANSATION,30,0,RED,{hudJellyTexture.getPosition().x + hudJellyTexture.getSize().x*1.5f, hudJellyTexture.getPosition().y+5}); + } void initPauseScreen() { @@ -283,7 +282,12 @@ private: void drawCrosshair() { - DrawTextureEx(this->crosshair.getTexture(), GetMousePosition(), 0, 1.2f, RED); + DrawTextureEx( + this->crosshair.getTexture(), + {GetMousePosition().x - this->crosshair.getSize().x / 2.0f, GetMousePosition().y - this->crosshair.getSize().y / 2.0f}, + 0, + 1.2f, + RED); // DrawTexturePro( // this->crosshair.getTexture(), // this->crosshair.getSourceRect(), @@ -297,6 +301,7 @@ private: { drawHudHealth(); drawHudBullets(); + drawHudJellies(); } void drawHudBullets() @@ -351,6 +356,19 @@ private: DrawTexture(healthSprite, pos.x, pos.y, WHITE); } } + + void drawHudJellies() + { + std::stringstream stream; + stream.clear(); + stream << CollectableService::getInstance().getAmountOfJelliesFreed(); + stream << "/"; + stream << CollectableService::getInstance().getMaxAmountOfJellies(); + hudJellyText.setText(stream.str()); + + DrawTexture(hudJellyTexture.getTexture(), hudJellyTexture.getPosition().x, hudJellyTexture.getPosition().y, WHITE); + hudJellyText.draw(); + } }; #endif \ No newline at end of file diff --git a/include/entities/HealthPack.h b/include/entities/HealthPack.h new file mode 100644 index 0000000..dad0083 --- /dev/null +++ b/include/entities/HealthPack.h @@ -0,0 +1,43 @@ +#ifndef HEALTH_PACK_H +#define HEALTH_PACK_H + +#include "raylib.h" +#include "services/AssetService.h" +#include "entities/TextureWrapper.h" + +class HealthPack { + public: + HealthPack() { + this->object = TextureWrapper(AssetService::getInstance().getSprite(ESprite::HEALTHPACK),{32,32}); + } + void logic(){ + } + + void draw() { + DrawTexture(object.getTexture(), object.getPosition().x, object.getPosition().y, WHITE); + } + + int getHealAmount() { + return this->healAmount; + } + + void setPickedUp(bool pickedUp) { + this->pickedUp = pickedUp; + } + + bool hasBeenPickedUp() { + return this->pickedUp; + } + + TextureWrapper& getObject() { + return this->object; + } + + private: + TextureWrapper object; + unsigned int healAmount = 2; // Amount of health replenished by the pack + bool pickedUp; // When the player has picked up the pack +}; + + +#endif \ No newline at end of file diff --git a/include/entities/Jelly.h b/include/entities/Jelly.h new file mode 100644 index 0000000..a04ee5b --- /dev/null +++ b/include/entities/Jelly.h @@ -0,0 +1,50 @@ +#ifndef JELLY_H +#define JELLY_H + +#include "raylib.h" +#include "services/MapService.h" +#include "services/AssetService.h" +#include "entities/TextureWrapper.h" + +class Jelly +{ +public: + Jelly(){ + this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY),{32,32}); + AssetService::getInstance().playSound(ESound::JELLY_FREED); + } + Jelly(Vector2 startPos) + { + this->startPosition = startPos; + this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::JELLY),{32,32},startPos); + AssetService::getInstance().playSound(ESound::JELLY_FREED); + } + + void logic() + { + if (texture.getPosition().y >= startPosition.y) + { + velocity.y = -jumpSpeed; + } + else + { + velocity.y += gravity; + } + + texture.move(velocity); + } + + void draw() + { + DrawTexture(texture.getTexture(), texture.getPosition().x, texture.getPosition().y, WHITE); + } + +private: + TextureWrapper texture; + float jumpSpeed = 7.0f; + float gravity = 0.6f; + Vector2 velocity = {0, 0}; + Vector2 startPosition = {0,0}; +}; + +#endif \ No newline at end of file diff --git a/include/entities/PBullet.h b/include/entities/PBullet.h index 4febe31..5dd3377 100644 --- a/include/entities/PBullet.h +++ b/include/entities/PBullet.h @@ -21,8 +21,8 @@ private: /** Check for collisions with creates */ for (auto &crate : CollectableService::getInstance().getCrates()) { - if(this->position.x + this->size > crate.getObject().getPosition().x && this->position.x - this->size < crate.getObject().getPosition().x && - this->position.y + this->size > crate.getObject().getPosition().y && this->position.y - this->size < crate.getObject().getPosition().y ) { + if(this->position.x + this->size > crate.getObject().getPosition().x && this->position.x-this->size < crate.getObject().getPosition().x + crate.getObject().getSize().x && + this->position.y + this->size > crate.getObject().getPosition().y && this->position.y-this->size < crate.getObject().getPosition().y + crate.getObject().getSize().y) { crate.setHit(true); AssetService::getInstance().playSound(ESound::CRATE_BREAK); // AssetService::getInstance().playSound(ESound::JELLY_FREED); diff --git a/include/entities/Player.h b/include/entities/Player.h index 9840767..1a97d9a 100644 --- a/include/entities/Player.h +++ b/include/entities/Player.h @@ -2,7 +2,6 @@ #define PLAYER_H #include "raylib.h" -#include #include "services/AssetService.h" #include "services/MapService.h" #include "services/InputService.h" @@ -12,6 +11,8 @@ #include "enums/ESound.h" #include "entities/Vector2i.h" #include "entities/PBullet.h" +#include +#include class Player { @@ -19,7 +20,6 @@ public: Player() { this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER), {32, 32}, {200, 200}); - prevFrame = GetTime(); spriteAnimation = {0, Right}; this->gunRight = TextureWrapper(AssetService::getInstance().getSprite(ESprite::PLAYER_GUN_RIGHT), {58, 29}, {0, 0}); @@ -28,6 +28,7 @@ public: this->prevShot = GetTime(); this->health = max_health; } + ~Player() { } @@ -38,12 +39,13 @@ public: shoot(); movement(); outofboundsCheck(); + consumableCollision(); } void draw() { drawGun(); - DrawTextureRec(this->texture.getTexture(), this->texture.getSourceRect(), this->texture.getPosition(), WHITE); + DrawTextureRec(this->texture.getTexture(), this->texture.getSourceRect(), this->texture.getPosition(), gainedPowerup ? RED : WHITE); } TextureWrapper &getTexture() @@ -56,15 +58,18 @@ public: this->texture.setPosition(pos); } - int getAmmo() { + int getAmmo() + { return this->ammo; } - uint8_t getHealth() { + uint8_t getHealth() + { return this->health; } - uint8_t getMaxHealth() { + uint8_t getMaxHealth() + { return this->max_health; } @@ -78,7 +83,7 @@ private: float moveSpeed = 5.0f; float gravity = 0.6f; float animationDelay = 0.2f; // In seconds - double prevFrame; + double prevFrame; // Time since the last frame Vector2i spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Player direction enum Direction { @@ -86,19 +91,20 @@ private: Left, Right, Up - }; // Used in conjuction with spriteAnimation, makes sure sprite direction matches with player direction + }; // 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 bool crateTopCollision; // Whether the player is standing on top of a crate - uint8_t ammo; // Current ammo of the player - uint8_t max_ammo = 100; // Max ammo of the player - float firingRate= 0.2f; // Delay in seconds - double prevShot; // The last time the player fired a bullet - uint8_t health; // Current health of the player - uint8_t max_health = 10; // Max health of the player + uint8_t ammo; // Current ammo of the player + uint8_t max_ammo = 100; // Max ammo of the player + float firingRate = 0.2f; // Delay in seconds + double prevShot; // The last time the player fired a bullet + uint8_t health; // Current health of the player + uint8_t max_health = 10; // Max health of the player + bool gainedPowerup = false; void applyGravity() { @@ -290,6 +296,56 @@ private: // } } + void consumableCollision() + { + /** Check for collisions with ammo packs */ + for (auto &ammoPack : CollectableService::getInstance().getAmmoPacks()) + { + if (this->texture.getPosition().x + this->texture.getSize().x > ammoPack.getObject().getPosition().x && + this->texture.getPosition().x < ammoPack.getObject().getPosition().x + ammoPack.getObject().getSize().x && + this->texture.getPosition().y + this->texture.getSize().y> ammoPack.getObject().getPosition().y && + this->texture.getPosition().y < ammoPack.getObject().getPosition().y + ammoPack.getObject().getSize().y) + { + ammoPack.setPickedUp(true); + AssetService::getInstance().playSound(ESound::AMMO_PICKUP); + ammo += ammoPack.getAmmoAmount(); + } + } + + /** Check for collisions with health packs */ + for (auto &healthPack : CollectableService::getInstance().getHealthPacks()) + { + if (this->texture.getPosition().x + this->texture.getSize().x > healthPack.getObject().getPosition().x && + this->texture.getPosition().x < healthPack.getObject().getPosition().x + healthPack.getObject().getSize().x && + this->texture.getPosition().y + this->texture.getSize().y> healthPack.getObject().getPosition().y && + this->texture.getPosition().y < healthPack.getObject().getPosition().y + healthPack.getObject().getSize().y) + { + if(health < max_health) { + healthPack.setPickedUp(true); + AssetService::getInstance().playSound(ESound::HEAL_PICKUP); + health = std::max(health+healthPack.getHealAmount(),(int)max_health); + } + } + } + + for (auto &powerup : CollectableService::getInstance().getPowerups()) + { + if (this->texture.getPosition().x + this->texture.getSize().x > powerup.getObject().getPosition().x && + this->texture.getPosition().x < powerup.getObject().getPosition().x + powerup.getObject().getSize().x && + this->texture.getPosition().y + this->texture.getSize().y> powerup.getObject().getPosition().y && + this->texture.getPosition().y < powerup.getObject().getPosition().y + powerup.getObject().getSize().y) + { + // if(health < max_health) { + powerup.setPickedUp(true); + AssetService::getInstance().playSound(ESound::POWERUP); + jumpPower += powerup.getExtraJumpPower(); + gainedPowerup = true; + // health = std::max(health+powerup.getHealAmount(),(int)max_health); + // } + } + } + } + void outofboundsCheck() { if (this->texture.getPosition().y > StateService::getInstance().getScreenSize().y) @@ -305,15 +361,15 @@ private: { if (GameService::getInstance().getMouseWorldPos().x > this->texture.getPosition().x + (this->gunLeft.getSize().x) && spriteAnimation.y == Right) { - float gunRotationRight = atan2(GameService::getInstance().getMouseWorldPos().y - this->texture.getPosition().y, - GameService::getInstance().getMouseWorldPos().x - this->texture.getPosition().x); - this->gunRight.setRotation(gunRotationRight * 90); + float gunRotationRight = atan2(GameService::getInstance().getMouseWorldPos().y - (this->texture.getPosition().y + this->texture.getSize().y / 2.0), + GameService::getInstance().getMouseWorldPos().x - (this->texture.getPosition().x + this->texture.getSize().x / 2.0)); + this->gunRight.setRotation(gunRotationRight * 180 / M_PI); } else if (GameService::getInstance().getMouseWorldPos().x + (this->gunLeft.getSize().x / 2) < this->texture.getPosition().x && spriteAnimation.y == Left) { - float gunRotationLeft = atan2(GameService::getInstance().getMouseWorldPos().y - this->texture.getPosition().y, - this->texture.getPosition().x - GameService::getInstance().getMouseWorldPos().x); - this->gunLeft.setRotation(-gunRotationLeft * 90); + float gunRotationLeft = atan2(GameService::getInstance().getMouseWorldPos().y - (this->texture.getPosition().y + this->texture.getSize().y / 2.0), + (this->texture.getPosition().x + this->texture.getSize().x / 2.0) - GameService::getInstance().getMouseWorldPos().x); + this->gunLeft.setRotation(-gunRotationLeft * 180 / M_PI); } } @@ -321,11 +377,13 @@ private: { if (GameService::getInstance().getMouseWorldPos().x > this->texture.getPosition().x + this->gunLeft.getSize().x && spriteAnimation.y == Right) { + // + this->texture.getSize().x / 2.0f + // + this->texture.getSize().y / 2.0f DrawTexturePro( this->gunRight.getTexture(), {0, 0, this->gunRight.getSize().x, this->gunRight.getSize().y}, {this->texture.getPosition().x + this->texture.getSize().x / 2.0f, - this->texture.getPosition().y + this->texture.getSize().x / 2.0f, + this->texture.getPosition().y + this->texture.getSize().y / 2.0f, this->gunRight.getSize().x, this->gunRight.getSize().y}, {this->gunRight.getSize().x / 2.0f, this->gunRight.getSize().y / 2.0f}, @@ -338,7 +396,7 @@ private: this->gunLeft.getTexture(), {0, 0, this->gunLeft.getSize().x, this->gunLeft.getSize().y}, {this->texture.getPosition().x + this->texture.getSize().x / 2.0f, - this->texture.getPosition().y + this->texture.getSize().x / 2.0f, + this->texture.getPosition().y + this->texture.getSize().y / 2.0f, this->gunLeft.getSize().x, this->gunLeft.getSize().y}, {this->gunLeft.getSize().x / 2.0f, this->gunLeft.getSize().y / 2.0f}, @@ -352,9 +410,9 @@ private: if (InputService::getInstance().isMouseButtonDown(MOUSE_BUTTON_LEFT) && GetTime() - prevShot > firingRate && groundCollision) { prevShot = GetTime(); - if (ammo == 0 || (GameService::getInstance().getMouseWorldPos().x > (this->texture.getPosition().x - this->gunLeft.getSize().x/2.0f) && spriteAnimation.y == Left) || - (GameService::getInstance().getMouseWorldPos().x < (this->texture.getPosition().x + this->texture.getSize().x + gunLeft.getSize().x/2.0f) && spriteAnimation.y == Right)) - { + if (ammo == 0 || (GameService::getInstance().getMouseWorldPos().x > (this->texture.getPosition().x - this->gunLeft.getSize().x / 2.0f) && spriteAnimation.y == Left) || + (GameService::getInstance().getMouseWorldPos().x < (this->texture.getPosition().x + this->texture.getSize().x + gunLeft.getSize().x / 2.0f) && spriteAnimation.y == Right)) + { // Play empty gun sound AssetService::getInstance().playSound(ESound::NO_AMMO); return; @@ -363,30 +421,23 @@ private: AssetService::getInstance().playSound(ESound::SHOOT); 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 + 22; - } - 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); + + float angleShot = atan2(mouseWorldPos.y - (this->texture.getPosition().y + this->texture.getSize().y / 2.0), + mouseWorldPos.x - (this->texture.getPosition().x + this->texture.getSize().x / 2.0)); + + /** Making the bullet originate from the gun's mouth */ + float offsetDistance = this->gunLeft.getSize().x / 2; + float offsetX = cos(angleShot) * offsetDistance; + float offsetY = sin(angleShot) * offsetDistance; + Vector2 bulletStartLocation = {this->texture.getPosition().x + this->texture.getSize().x / 2.0f + offsetX, + this->texture.getPosition().y + this->texture.getSize().y / 2.0f + offsetY}; + GameService::getInstance().addPlayerBullet(PBullet(bulletStartLocation, angleShot)); - // bulletDirections.push_back(angleShot); } } } diff --git a/include/entities/Powerup.h b/include/entities/Powerup.h new file mode 100644 index 0000000..7375531 --- /dev/null +++ b/include/entities/Powerup.h @@ -0,0 +1,58 @@ +#ifndef POWERUP_H +#define POWERUP_H + +#include "raylib.h" +#include "services/AssetService.h" +#include "entities/TextureWrapper.h" + +class Powerup { + public: + Powerup() { + this->object = TextureWrapper(AssetService::getInstance().getSprite(ESprite::POWERUP),{50,55}); + } + void logic(){ + animate(); + } + + void draw() { + DrawTextureRec(object.getTexture(), object.getSourceRect(), object.getPosition(), WHITE); + } + + float getExtraJumpPower() { + return this->extraJumpPower; + } + + void setPickedUp(bool pickedUp) { + this->pickedUp = pickedUp; + } + + bool hasBeenPickedUp() { + return this->pickedUp; + } + + TextureWrapper& getObject() { + return this->object; + } + + private: + TextureWrapper object; + float extraJumpPower = 2.0f; // Jump power gained by grabbing the powerup + bool pickedUp = false; // When the player has picked up the pack + float animationDelay = 0.08f; // How long to wait in between animation frames (in seconds) + double lastFrame; // Time since the last frame + u_int8_t currentFrame = 0; // Current frame of the animation + u_int8_t amountOfFrames = 8; // Total amount of animation frames + + void animate() { + if(GetTime() - lastFrame > animationDelay) { + currentFrame ++; + currentFrame %= amountOfFrames; + + object.setSourceRect({(float)currentFrame * 81 + 16, 10,object.getSize().x, object.getSize().y}); + lastFrame = GetTime(); + } + } +}; + + +#endif \ No newline at end of file diff --git a/include/services/CollectableService.h b/include/services/CollectableService.h index b391848..e5c44a2 100644 --- a/include/services/CollectableService.h +++ b/include/services/CollectableService.h @@ -7,6 +7,10 @@ #include "entities/Vector2i.h" #include "entities/Crate.h" #include "entities/PBullet.h" +#include "entities/Jelly.h" +#include "entities/AmmoPack.h" +#include "entities/HealthPack.h" +#include "entities/Powerup.h" #include class CollectableService : public Service @@ -15,52 +19,77 @@ public: void initCollectables() { initCrates(); + initJellies(); + initAmmoPacks(); + initHealthPacks(); + initPowerups(); } void collectableLogic() { crateLogic(); + jellyLogic(); + ammoPackLogic(); + healthPackLogic(); + powerupLogic(); } void drawCollectables() { drawCrates(); + drawJellies(); + drawAmmoPacks(); + drawHealthpacks(); + drawPowerups(); } - // void checkCratesForCollision(PBullet bullet) - // { - // for (auto it = crates.begin(); it != crates.end();) - // { - // auto &crate = *it; - // // if (*it % 2 == 0) { - // if (crate.bulletCollision(bullet)) - // { - // Vector2 pos = crate.getObject().getPosition(); - // Vector2i tilePos = Vector2i(pos.x / MapService::getInstance().getMap().getTileSize(), pos.y / MapService::getInstance().getMap().getTileSize()); - // MapService::getInstance().getMap().updateColmapTile(tilePos, false); - // it = crates.erase(it); // erase returns the next iterator - // } - // else - // { - // ++it; - // } - // } - // } - - std::vector& getCrates() { + std::vector &getCrates() + { return this->crates; } + std::vector &getAmmoPacks() + { + return this->ammoPacks; + } + + std::vector &getHealthPacks() + { + return this->healthPacks; + } + + std::vector &getPowerups() { + return this->powerUps; + } + + int getMaxAmountOfJellies() + { + return this->amountOfCrates; + } + + int getAmountOfJelliesFreed() + { + return this->jellies.size(); + } + private: + int amountOfCrates = 3; + int amountOfAmmoPacks = 4; + int amountOfHealthPacks = 4; + int amountOfPowerups = 1; + std::vector crates; + std::vector ammoPacks; + std::vector healthPacks; + std::vector jellies; + std::vector powerUps; + void initCrates() { crates.clear(); - Vector2 location; int tileSize = MapService::getInstance().getMap().getTileSize(); - for (int i = 0; i < 3; i++) + for (int i = 0; i < amountOfCrates; i++) { crates.push_back(Crate()); - // crateLocation.push_back(location); } crates[0].getObject().setPosition({38.0f * tileSize, 9.0f * tileSize}); crates[1].getObject().setPosition({41.0f * tileSize, 5.0f * tileSize}); @@ -71,17 +100,50 @@ private: Vector2i crateTilePos = Vector2i(crates[i].getObject().getPosition().x / tileSize, crates[i].getObject().getPosition().y / tileSize); MapService::getInstance().getMap().updateColmapTile(crateTilePos, true); } - // crates[0].y = 9 * tileSize; - - // crateLocation[1].x = 41 * tileSize; - // crateLocation[1].y = 5 * tileSize; - - // crateLocation[2].x = 68 * tileSize; - // crateLocation[2].y = 4 * tileSize; } void initJellies() { + jellies.clear(); + } + + void initAmmoPacks() + { + ammoPacks.clear(); + int tileSize = MapService::getInstance().getMap().getTileSize(); + for (int i = 0; i < amountOfAmmoPacks; i++) + { + ammoPacks.push_back(AmmoPack()); + } + ammoPacks[0].getObject().setPosition({32.0f * tileSize, 9.0f * tileSize}); + ammoPacks[1].getObject().setPosition({48.0f * tileSize, 5.0f * tileSize}); + ammoPacks[2].getObject().setPosition({88.0f * tileSize, 9.0f * tileSize}); + ammoPacks[3].getObject().setPosition({105.0f * tileSize, 15.0f * tileSize}); + } + + void initHealthPacks() + { + healthPacks.clear(); + int tileSize = MapService::getInstance().getMap().getTileSize(); + for (int i = 0; i < amountOfHealthPacks; i++) + { + healthPacks.push_back(HealthPack()); + } + healthPacks[0].getObject().setPosition({28.0f * tileSize, 10.0f * tileSize}); + healthPacks[1].getObject().setPosition({64.0f * tileSize, 6.0f * tileSize}); + healthPacks[2].getObject().setPosition({118.0f * tileSize, 11.0f * tileSize}); + healthPacks[3].getObject().setPosition({74.0f * tileSize, 8.0f * tileSize}); + } + + void initPowerups() + { + powerUps.clear(); + int tileSize = MapService::getInstance().getMap().getTileSize(); + for (int i = 0; i < amountOfPowerups; i++) + { + powerUps.push_back(Powerup()); + } + powerUps[0].getObject().setPosition({41.0f * tileSize+8, 10.0f * tileSize-25}); } void crateLogic() @@ -91,12 +153,16 @@ private: auto &crate = *it; /** * If the crate has been hit: - * 1. Remove the collision tile from the collision map - * + * 1. Create a Jelly on the location of the crate + * 2. Remove the collision tile from the collision map + * 3. Remove the crate */ if (crate.hasBeenHit()) { Vector2 pos = crate.getObject().getPosition(); + + jellies.push_back(Jelly(pos)); + Vector2i tilePos = Vector2i(pos.x / MapService::getInstance().getMap().getTileSize(), pos.y / MapService::getInstance().getMap().getTileSize()); MapService::getInstance().getMap().updateColmapTile(tilePos, false); it = crates.erase(it); @@ -108,35 +174,61 @@ private: } } - // void destroyCrate(int index) { - // Vector2 pos = crates[index].getObject().getPosition(); - // Vector2i tilePos = Vector2i(pos.x/MapService::getInstance().getMap().getTileSize(), pos.y/MapService::getInstance().getMap().getTileSize()); - // MapService::getInstance().getMap().updateColmapTile(tilePos, false); - // crates.erase(crates.begin() + index); - // } - - // void checkCratesForCollision(PBullet bullet) - // { - // for (auto it = crates.begin(); it != crates.end();) - // { - // auto &crate = *it; - // // if (*it % 2 == 0) { - // if (crate.bulletCollision(bullet)) - // { - // Vector2 pos = crate.getObject().getPosition(); - // Vector2i tilePos = Vector2i(pos.x / MapService::getInstance().getMap().getTileSize(), pos.y / MapService::getInstance().getMap().getTileSize()); - // MapService::getInstance().getMap().updateColmapTile(tilePos, false); - // it = crates.erase(it); // erase returns the next iterator - // } - // else - // { - // ++it; - // } - // } - // } - void jellyLogic() { + for (int i = 0; i < jellies.size(); i++) + { + jellies[i].logic(); + } + } + + void ammoPackLogic() + { + for (auto it = ammoPacks.begin(); it != ammoPacks.end();) + { + auto &ammoPack = *it; + if (ammoPack.hasBeenPickedUp()) + { + it = ammoPacks.erase(it); + } + else + { + ++it; + } + } + } + + void healthPackLogic() + { + for (auto it = healthPacks.begin(); it != healthPacks.end();) + { + auto &healthPack = *it; + if (healthPack.hasBeenPickedUp()) + { + it = healthPacks.erase(it); + } + else + { + ++it; + } + } + } + + void powerupLogic() + { + for (auto it = powerUps.begin(); it != powerUps.end();) + { + auto &powerUp = *it; + if (powerUp.hasBeenPickedUp()) + { + it = powerUps.erase(it); + } + else + { + powerUp.logic(); + ++it; + } + } } void drawCrates() @@ -149,36 +241,35 @@ private: void drawJellies() { - } - - void drawHudJellies() - { + for (int i = 0; i < jellies.size(); i++) + { + jellies[i].draw(); + } } void drawAmmoPacks() { + for (int i = 0; i < ammoPacks.size(); i++) + { + ammoPacks[i].draw(); + } } void drawHealthpacks() { + for (int i = 0; i < healthPacks.size(); i++) + { + healthPacks[i].draw(); + } } - // sf::Text jelliesFreed; // Holds the text that shows how many jellies are freed - // sf::Font jelliesFreedFont; // Holds the font used for the text of the display - - // sf::Sprite jelliesFreedSprite; // Holds the sprite of the jelly in the top right corner - - // Vector2i jellyDisplayLocation; // Holds the location where the amount of jellies freed are displayed - std::vector crates; - // std::vector crateSprite; // Holds the sprites of the crates - // std::vector jellySprite; // Holds the sprites of the jellies inside the crates - // std::vector crateLocation; // Holds the locations of the crates/jellies - // std::vector velocity; // Makes sure the jellies jump when the crate is destroyed - // std::vector collision; // Keeps track of whether or not the player has collided with a crate - // std::vector crateDestroyed; // Keeps track of whether or not a crate has been destroyed - - // unsigned int totalAmntCrates; // Holds the total amount of crates - // unsigned int amntCratesDestroyed; // Holds the amount of crates that have been destroyed + void drawPowerups() + { + for (int i = 0; i < powerUps.size(); i++) + { + powerUps[i].draw(); + } + } }; #endif \ No newline at end of file diff --git a/include/services/GameService.h b/include/services/GameService.h index 75e3190..fb00af9 100644 --- a/include/services/GameService.h +++ b/include/services/GameService.h @@ -52,13 +52,6 @@ public: Vector2 worldPos = {(float)pixelPos.x + camera.target.x - camera.offset.x, (float)pixelPos.y}; return worldPos; } - // void setGame(Game game) { - // this->game = game; - // } - - // Game& getGame() { - // return this->game; - // } void addPlayerBullet(PBullet bullet) { diff --git a/src/services/AssetService.cpp b/src/services/AssetService.cpp index 80e75d6..7b78e07 100644 --- a/src/services/AssetService.cpp +++ b/src/services/AssetService.cpp @@ -24,8 +24,10 @@ void AssetService::setAssets() SetSoundVolume(sounds[ESound::SHOOT], 0.4f); sounds[ESound::NO_AMMO] = loadSound("Audio/Sounds/outOfAmmo.wav"); sounds[ESound::CRATE_BREAK] = loadSound("Audio/Sounds/crateBreak.wav"); - SetSoundVolume(sounds[ESound::CRATE_BREAK], 1.0f); sounds[ESound::JELLY_FREED] = loadSound("Audio/Sounds/jellyFreed.wav"); + sounds[ESound::HEAL_PICKUP] = loadSound("Audio/Sounds/healmag.wav"); + sounds[ESound::AMMO_PICKUP] = loadSound("Audio/Sounds/shotgunReload.wav"); + sounds[ESound::POWERUP] = loadSound("Audio/Sounds/powerUpSound.wav"); backgrounds[EBackground::TUTORIAL] = loadTexture("Textures/TutorialBackground2.png"); backgrounds[EBackground::GAME1] = loadTexture("Textures/GameBackground_1.png");