[Added] Start of enemies
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include "entities/PBullet.h"
|
||||
|
||||
class Crate {
|
||||
public:
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
#ifndef ENEMY_H
|
||||
#define ENEMY_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/MapService.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
#include <cmath>
|
||||
|
||||
class Enemy
|
||||
{
|
||||
public:
|
||||
Enemy()
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY), {32, 32});
|
||||
this->gunRight = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY_GUN_RIGHT), {97, 27});
|
||||
this->gunLeft = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY_GUN_LEFT), {97, 27});
|
||||
prevFrame = GetTime();
|
||||
|
||||
/** Randomizes between 0 and 1 (+1 to get Left and Right in directions), so they dont all move in the same direction */
|
||||
int randDir = (int)((int)(GetTime() * 1000000) % 2);
|
||||
spriteAnimation = {0, randDir + 1};
|
||||
health = maxHealth;
|
||||
}
|
||||
Enemy(Vector2 startPos)
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::ENEMY), {32, 32}, startPos);
|
||||
prevFrame = GetTime();
|
||||
|
||||
int randDir = (int)((int)(GetTime() * 1000000) % 2);
|
||||
spriteAnimation = {0, randDir + 1};
|
||||
health = maxHealth;
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
if (health == 0)
|
||||
{
|
||||
fall();
|
||||
}
|
||||
else
|
||||
{
|
||||
walk();
|
||||
checkForCollision();
|
||||
animate();
|
||||
// if (!hasCollided)
|
||||
// {
|
||||
// }
|
||||
}
|
||||
texture.move(velocity);
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
drawGun();
|
||||
drawHealthBar();
|
||||
DrawTextureRec(this->texture.getTexture(), this->texture.getSourceRect(), this->texture.getPosition(), WHITE);
|
||||
}
|
||||
|
||||
TextureWrapper &getObject()
|
||||
{
|
||||
return this->texture;
|
||||
}
|
||||
|
||||
u_int8_t getHealth()
|
||||
{
|
||||
return this->health;
|
||||
}
|
||||
|
||||
void takeDamage()
|
||||
{
|
||||
this->health = std::max(health - 1, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
TextureWrapper gunLeft;
|
||||
TextureWrapper gunRight;
|
||||
u_int8_t health;
|
||||
u_int8_t maxHealth = 5;
|
||||
Vector2 velocity = {0, 0};
|
||||
float spottingRange = 300; // From how far away enemies can spot the player
|
||||
float gravity = 0.6f;
|
||||
float moveSpeed = 1.5f;
|
||||
float animationDelay = 0.2f; // In seconds
|
||||
double prevFrame; // Time since the last frame
|
||||
bool hasCollided = false;
|
||||
Vector2i spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Enemy direction
|
||||
enum Direction
|
||||
{
|
||||
Down,
|
||||
Left,
|
||||
Right,
|
||||
Up
|
||||
}; // Used in conjuction with spriteAnimation, makes sure sprite direction matches with enemy direction
|
||||
|
||||
void walk()
|
||||
{
|
||||
if (spriteAnimation.y == Left)
|
||||
{
|
||||
velocity.x = -moveSpeed;
|
||||
}
|
||||
else
|
||||
{
|
||||
velocity.x = moveSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
void checkForCollision()
|
||||
{
|
||||
std::vector corners = getCorners();
|
||||
std::vector<std::vector<int>> colMap = MapService::getInstance().getMap().getColMap();
|
||||
hasCollided = false;
|
||||
|
||||
if (colMap[corners[2].y][corners[2].x] == 0 || colMap[corners[3].y][corners[3].x] == 0) // No ground below enemy
|
||||
{
|
||||
hasCollided = true;
|
||||
}
|
||||
else if (colMap[corners[0].y][corners[0].x] == 1 || colMap[corners[1].y][corners[1].x] == 1)
|
||||
{
|
||||
hasCollided = true;
|
||||
}
|
||||
|
||||
if (hasCollided)
|
||||
{
|
||||
if (spriteAnimation.y == Left)
|
||||
spriteAnimation.y = Right;
|
||||
else
|
||||
spriteAnimation.y = Left;
|
||||
|
||||
velocity.x *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vector2i> getCorners()
|
||||
{
|
||||
float bottom = texture.getPosition().y + texture.getSize().y + velocity.y;
|
||||
float left = texture.getPosition().x + velocity.x;
|
||||
float right = texture.getPosition().x + texture.getSize().x + velocity.x;
|
||||
float top = texture.getPosition().y + velocity.y;
|
||||
|
||||
int tileSize = MapService::getInstance().getMap().getTileSize();
|
||||
// Vector2i leftTop(Vector2i((int)left / tileSize, (int)(top + 5) / tileSize));
|
||||
// Vector2i leftBottom(Vector2i((int)left / tileSize, (int)(bottom - 5) / tileSize));
|
||||
Vector2i leftCenter = Vector2i((int)left / tileSize, (int)(bottom - texture.getSize().y / 2.0) / tileSize);
|
||||
// Vector2i rightTop(Vector2i((int)right / tileSize, (int)(top + 5) / tileSize));
|
||||
// Vector2i rightBottom(Vector2i((int)right / tileSize, (int)(bottom - 5) / tileSize));
|
||||
Vector2i rightCenter = Vector2i((int)right / tileSize, (int)(bottom - texture.getSize().y / 2.0) / 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
|
||||
|
||||
std::vector<Vector2i> corners;
|
||||
|
||||
corners.push_back(leftCenter);
|
||||
corners.push_back(rightCenter);
|
||||
// corners.push_back(leftBottom);
|
||||
// corners.push_back(rightTop);
|
||||
// corners.push_back(rightBottom);
|
||||
|
||||
corners.push_back(bottomLeft);
|
||||
corners.push_back(bottomRight);
|
||||
return corners;
|
||||
}
|
||||
|
||||
void animate()
|
||||
{
|
||||
if (GetTime() - prevFrame > animationDelay || hasCollided)
|
||||
{
|
||||
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 drawHealthBar()
|
||||
{
|
||||
float barLength = (this->texture.getSize().x / maxHealth) * health;
|
||||
DrawRectangle(this->texture.getPosition().x, this->texture.getPosition().y - 12.0f, barLength, 3, RED);
|
||||
}
|
||||
|
||||
void drawGun()
|
||||
{
|
||||
if (this->spriteAnimation.y == Right)
|
||||
{
|
||||
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().y / 2.0f,
|
||||
this->gunRight.getSize().x,
|
||||
this->gunRight.getSize().y},
|
||||
{this->gunRight.getSize().x / 3.0f, this->gunRight.getSize().y / 2.0f},
|
||||
this->gunRight.getRotation(),
|
||||
WHITE);
|
||||
}
|
||||
else if (this->spriteAnimation.y == Left)
|
||||
{
|
||||
DrawTexturePro(
|
||||
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().y / 2.0f,
|
||||
this->gunLeft.getSize().x,
|
||||
this->gunLeft.getSize().y},
|
||||
{this->gunLeft.getSize().x - this->gunLeft.getSize().x / 3.0f, this->gunLeft.getSize().y / 2.0f},
|
||||
this->gunLeft.getRotation(),
|
||||
WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void fall()
|
||||
{
|
||||
velocity.y += gravity;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef FLAG_H
|
||||
#define FLAG_H
|
||||
|
||||
#include "raylib.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "services/StateService.h"
|
||||
#include "entities/TextureWrapper.h"
|
||||
|
||||
class Flag
|
||||
{
|
||||
public:
|
||||
Flag()
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::FLAG), {40, 40});
|
||||
}
|
||||
Flag(Vector2 startPos)
|
||||
{
|
||||
this->texture = TextureWrapper(AssetService::getInstance().getSprite(ESprite::FLAG), {40, 40}, startPos);
|
||||
}
|
||||
|
||||
void logic()
|
||||
{
|
||||
if (touched)
|
||||
{
|
||||
StateService::getInstance().setScreen(EScreen::VICTORY);
|
||||
}
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
DrawTextureEx(texture.getTexture(), texture.getPosition(), 0.0f, texture.getSize().x/texture.getTexture().width, WHITE);
|
||||
}
|
||||
|
||||
TextureWrapper &getObject()
|
||||
{
|
||||
return this->texture;
|
||||
}
|
||||
|
||||
void setTouched(bool touched) {
|
||||
this->touched = touched;
|
||||
}
|
||||
|
||||
private:
|
||||
TextureWrapper texture;
|
||||
bool touched = false; // Whether the player has touched the flag
|
||||
};
|
||||
|
||||
#endif
|
||||
+11
-6
@@ -9,6 +9,7 @@
|
||||
#include "services/InputService.h"
|
||||
#include "services/GameService.h"
|
||||
#include "services/CollectableService.h"
|
||||
#include "services/EnemyService.h"
|
||||
#include "entities/Player.h"
|
||||
#include "entities/Text.h"
|
||||
#include "entities/Bullet.h"
|
||||
@@ -54,6 +55,7 @@ public:
|
||||
initHud();
|
||||
initPauseScreen();
|
||||
initGameOverScreen();
|
||||
EnemyService::getInstance().initEnemies();
|
||||
|
||||
InputService::getInstance().setKeysToWatch({KEY_A, KEY_W, KEY_S, KEY_D, KEY_ENTER}, {MOUSE_BUTTON_LEFT});
|
||||
AudioService::getInstance().setMusic(EMusic::GAME);
|
||||
@@ -89,8 +91,10 @@ public:
|
||||
GameService::getInstance().bulletLogic();
|
||||
CollectableService::getInstance().collectableLogic();
|
||||
|
||||
EnemyService::getInstance().enemyLogic();
|
||||
|
||||
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};
|
||||
@@ -112,6 +116,7 @@ public:
|
||||
GameService::getInstance().drawBullets();
|
||||
this->map.draw();
|
||||
CollectableService::getInstance().drawCollectables();
|
||||
EnemyService::getInstance().drawEnemies();
|
||||
this->player.draw();
|
||||
|
||||
EndMode2D();
|
||||
@@ -130,11 +135,11 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
// Camera2D camera;
|
||||
Background background;
|
||||
Map map;
|
||||
Player player;
|
||||
TextureWrapper crosshair;
|
||||
std::vector<Enemy> enemies;
|
||||
|
||||
std::vector<Text> pauseScreenButtons;
|
||||
int hoveredPauseScreenButton = 0;
|
||||
@@ -143,13 +148,13 @@ private:
|
||||
std::vector<Text> gameOverScreenButtons;
|
||||
int hoveredGameOverScreenButton = 0;
|
||||
|
||||
// Font hudJellyFont;
|
||||
Text hudJellyText;
|
||||
TextureWrapper hudJellyTexture;
|
||||
|
||||
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 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()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "services/CollectableService.h"
|
||||
#include "services/AssetService.h"
|
||||
#include "services/EnemyService.h"
|
||||
#include "entities/Bullet.h"
|
||||
#include <iostream>
|
||||
|
||||
@@ -29,6 +30,22 @@ private:
|
||||
this->hasCollided = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &enemy : EnemyService::getInstance().getEnemies())
|
||||
{
|
||||
/** If the enemy is already falling of the map, dont allow bullets to hit it anymore */
|
||||
if(enemy.getHealth() == 0)
|
||||
continue;
|
||||
|
||||
if(this->position.x + this->size > enemy.getObject().getPosition().x && this->position.x-this->size < enemy.getObject().getPosition().x + enemy.getObject().getSize().x &&
|
||||
this->position.y + this->size > enemy.getObject().getPosition().y && this->position.y-this->size < enemy.getObject().getPosition().y + enemy.getObject().getSize().y) {
|
||||
enemy.takeDamage();
|
||||
if(enemy.getHealth() == 0) {
|
||||
AssetService::getInstance().playSound(ESound::ENEMY_DEFEATED);
|
||||
}
|
||||
this->hasCollided = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+40
-28
@@ -28,7 +28,7 @@ public:
|
||||
this->prevShot = GetTime();
|
||||
this->health = max_health;
|
||||
}
|
||||
|
||||
|
||||
~Player()
|
||||
{
|
||||
}
|
||||
@@ -82,28 +82,28 @@ private:
|
||||
float jumpPower = 7.2f;
|
||||
float moveSpeed = 5.0f;
|
||||
float gravity = 0.6f;
|
||||
float animationDelay = 0.2f; // In seconds
|
||||
double prevFrame; // Time since the last frame
|
||||
Vector2i spriteAnimation; // Keeps track of (1) Sprite cycling and (2) Player direction
|
||||
float animationDelay = 0.2f; // In seconds
|
||||
double prevFrame; // Time since the last frame
|
||||
Vector2i 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
|
||||
}; // Used in conjuction with spriteAnimation, makes sure sprite direction matches with player direction
|
||||
|
||||
std::vector<Vector2i> tiles; // Holds eight points of the player for accurate collision
|
||||
std::vector<unsigned int> 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()
|
||||
@@ -301,9 +301,9 @@ private:
|
||||
/** 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 &&
|
||||
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);
|
||||
@@ -315,35 +315,47 @@ private:
|
||||
/** 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 &&
|
||||
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) {
|
||||
if (health < max_health)
|
||||
{
|
||||
healthPack.setPickedUp(true);
|
||||
AssetService::getInstance().playSound(ESound::HEAL_PICKUP);
|
||||
health = std::max(health+healthPack.getHealAmount(),(int)max_health);
|
||||
health = std::max(health + healthPack.getHealAmount(), (int)max_health);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &powerup : CollectableService::getInstance().getPowerups())
|
||||
/** Checks for collisions with powerups */
|
||||
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 &&
|
||||
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);
|
||||
powerup.setPickedUp(true);
|
||||
AssetService::getInstance().playSound(ESound::POWERUP);
|
||||
jumpPower += powerup.getExtraJumpPower();
|
||||
gainedPowerup = true;
|
||||
// health = std::max(health+powerup.getHealAmount(),(int)max_health);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks for collisions with the finish flag */
|
||||
auto &flag = CollectableService::getInstance().getFlag();
|
||||
if (this->texture.getPosition().x + this->texture.getSize().x > flag.getObject().getPosition().x &&
|
||||
this->texture.getPosition().x<flag.getObject().getPosition().x + flag.getObject().getSize().x &&
|
||||
this->texture.getPosition().y + this->texture.getSize().y> flag.getObject().getPosition().y &&
|
||||
this->texture.getPosition().y < flag.getObject().getPosition().y + flag.getObject().getSize().y)
|
||||
{
|
||||
flag.setTouched(true);
|
||||
}
|
||||
}
|
||||
|
||||
void outofboundsCheck()
|
||||
|
||||
@@ -15,7 +15,6 @@ class TextureWrapper {
|
||||
this->sourceRect = sourceRect;
|
||||
}
|
||||
~TextureWrapper() {
|
||||
|
||||
}
|
||||
|
||||
Texture2D getTexture() {
|
||||
|
||||
Reference in New Issue
Block a user