Skip to content

Commit

Permalink
feat: projectiles
Browse files Browse the repository at this point in the history
  • Loading branch information
araujo88 committed Apr 5, 2024
1 parent 193d966 commit 98420ed
Show file tree
Hide file tree
Showing 14 changed files with 238 additions and 49 deletions.
3 changes: 1 addition & 2 deletions include/NPC.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
#include <chrono>
#include <random>
#include <string>
#include <thread>

namespace nano {
class NPC : public Character {
Expand All @@ -24,7 +23,7 @@ class NPC : public Character {
void update() override;
std::string getName() override;
SDL_Rect getBoundingBox() override;
void handleCollision() override;
void handleCollision(IEntity *entity) override;
bool isColliding(const SDL_Rect &box) override;
~NPC() override = default;
};
Expand Down
6 changes: 2 additions & 4 deletions include/character.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@

#include "constants.hpp"
#include "entity.hpp"
#include <chrono>
#include <random>
#include <string>
#include <thread>

namespace nano {
class Character : public IEntity {
protected:
int x = 0, y = 0;
SDL_Texture *texture;
std::string spritePath;
enum Direction { UP = 0, DOWN, RIGHT, LEFT };

public:
Character(std::string name, int x, int y, SDL_Renderer *renderer,
Expand All @@ -25,7 +23,7 @@ class Character : public IEntity {
virtual ~Character();
std::string getName() override;
SDL_Rect getBoundingBox() override;
void handleCollision() override;
void handleCollision(IEntity *entity) override;
};
} // namespace nano
#endif
5 changes: 4 additions & 1 deletion include/entity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class IEntity {
protected:
SDL_Rect boundingBox;
std::string name;
bool toBeDestroyed = false;

public:
virtual void render(SDL_Renderer *renderer) = 0;
Expand All @@ -21,7 +22,9 @@ class IEntity {
virtual bool isColliding(const SDL_Rect &box) = 0;
virtual std::string getName() = 0;
virtual SDL_Rect getBoundingBox() = 0;
virtual void handleCollision() = 0;
virtual void handleCollision(IEntity *entity) = 0;
bool shouldDestroy() const { return toBeDestroyed; }
void markForDestruction() { toBeDestroyed = true; }
};
} // namespace nano

Expand Down
2 changes: 2 additions & 0 deletions include/game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <algorithm>
#include <iostream>
#include <list>
#include <memory>

namespace nano {
class Game {
Expand Down
13 changes: 12 additions & 1 deletion include/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@

#include "character.hpp"
#include "constants.hpp"
#include "projectile.hpp"
#include <algorithm>
#include <memory>
#include <string>
#include <vector>

namespace nano {
class Player : public Character {
private:
int speed;
bool isFacingUp;
bool isFacingDown;
bool isFacingRight;
bool isFacingLeft;
SDL_Renderer *renderer;
std::vector<std::unique_ptr<Projectile>> bullets;

public:
Player(std::string name, SDL_Renderer *renderer, std::string spritePath);
Expand All @@ -23,8 +33,9 @@ class Player : public Character {
void update() override;
std::string getName() override;
SDL_Rect getBoundingBox() override;
void handleCollision() override;
void handleCollision(IEntity *entity) override;
bool isColliding(const SDL_Rect &box) override;
void attack();
~Player() override = default;
};
} // namespace nano
Expand Down
31 changes: 31 additions & 0 deletions include/projectile.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#ifndef PROJECTILE_H_
#define PROJECTILE_H_

#include "character.hpp"
#include "constants.hpp"
#include <string>

namespace nano {
class Projectile : public Character {
private:
const int speed = 20;
Direction direction;
Uint32 lastMoveTime = 0;

public:
Projectile(std::string name, int x, int y, SDL_Renderer *renderer,
std::string spritePath, Direction direction);
void move();
void render(SDL_Renderer *renderer) override;
void handleEvent(SDL_Event *event) override;
void update() override;
std::string getName() override;
SDL_Rect getBoundingBox() override;
void handleCollision(IEntity *entity) override;
bool isColliding(const SDL_Rect &box) override;
bool isOutOfBounds();
~Projectile() override;
};
} // namespace nano

#endif
2 changes: 1 addition & 1 deletion include/world.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class World : public IEntity {
void update() override;
std::string getName() override;
SDL_Rect getBoundingBox() override;
void handleCollision() override;
void handleCollision(IEntity *entity) override;
bool isColliding(const SDL_Rect &box) override;
~World();
};
Expand Down
Binary file added sprites/pepe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 18 additions & 11 deletions src/character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,22 @@ using namespace nano;

Character::Character(std::string name, int x, int y, SDL_Renderer *renderer,
std::string spritePath) {
texture = IMG_LoadTexture(renderer, spritePath.c_str());
if (!texture) {
SDL_Log("Failed to load character texture: %s", IMG_GetError());
exit(1);
}
this->name = name;
this->x = x;
this->y = y;
this->boundingBox = {this->x, this->y, TILE_SIZE, TILE_SIZE};

SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION,
"%s bounding box: h:%d,w:%d,x:%d,y:%d", this->name.c_str(),
this->boundingBox.h, this->boundingBox.w, this->boundingBox.x,
this->boundingBox.y);
this->texture = IMG_LoadTexture(renderer, spritePath.c_str());
if (!texture) {
SDL_Log("Sprite %s: failed to load character texture: %s", name.c_str(),
IMG_GetError());
exit(1);
}

// SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION,
// "%s bounding box: h:%d,w:%d,x:%d,y:%d", this->name.c_str(),
// this->boundingBox.h, this->boundingBox.w, this->boundingBox.x,
// this->boundingBox.y);
};

void Character::render(SDL_Renderer *renderer) {
Expand All @@ -40,6 +42,11 @@ std::string Character::getName() { return this->name; };

SDL_Rect Character::getBoundingBox() { return this->boundingBox; };

void Character::handleCollision() {}
void Character::handleCollision(IEntity *entity) {}

Character::~Character() { SDL_DestroyTexture(texture); }
Character::~Character() {
if (texture != NULL) {
SDL_DestroyTexture(texture);
texture = NULL; // Prevent potential use after free
}
}
38 changes: 14 additions & 24 deletions src/game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,38 +43,28 @@ void Game::clear() {
void Game::update() {
SDL_RenderPresent(renderer);

IEntity *player = nullptr;
// Find the player entity, if it exists
for (auto &entity : entities) {
if (entity->getName() == "Player") {
player = entity; // Directly use the raw pointer since entities are raw
// pointers
break; // Stop the loop once the player is found
}
}

// Update all entities
for (auto &entity : entities) {
entity->update();
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION,
"%s bounding box: h:%d,w:%d,x:%d,y:%d",
entity->getName().c_str(), entity->getBoundingBox().h,
entity->getBoundingBox().w, entity->getBoundingBox().x,
entity->getBoundingBox().y);
}

// If a player is found, then check for collisions with other entities
if (player) {
for (auto &character : entities) {
// Make sure not to check the player against itself
if (character != player &&
player->isColliding(character->getBoundingBox())) {
character->handleCollision();
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION,
"Collision detected between Player and another entity.");
// Check for collisions between all entities
for (auto &entity1 : entities) {
for (auto &entity2 : entities) {
// Avoid self-collision and redundant checks
if (entity1 != entity2 &&
entity1->isColliding(entity2->getBoundingBox())) {
entity1->handleCollision(entity2);
entity2->handleCollision(entity1);
}
}
}

// Remove all entities marked for destruction
entities.erase(
std::remove_if(entities.begin(), entities.end(),
[](IEntity *entity) { return entity->shouldDestroy(); }),
entities.end());
}

void Game::handleEvents() {
Expand Down
2 changes: 1 addition & 1 deletion src/npc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ std::string NPC::getName() { return Character::getName(); };

SDL_Rect NPC::getBoundingBox() { return Character::getBoundingBox(); };

void NPC::handleCollision() {}
void NPC::handleCollision(IEntity *entity) {}

void NPC::handleEvent(SDL_Event *event) {}
74 changes: 71 additions & 3 deletions src/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Player::Player(std::string name, SDL_Renderer *renderer, std::string spritePath)
this->x = 0;
this->y = 0;
this->speed = 10;
this->renderer = renderer;
};

Player::Player(std::string name, int x, int y, int speed,
Expand All @@ -15,6 +16,7 @@ Player::Player(std::string name, int x, int y, int speed,
this->x = x;
this->y = y;
this->speed = speed;
this->renderer = renderer;
};

void Player::moveUp() {
Expand All @@ -23,6 +25,11 @@ void Player::moveUp() {
y -= speed;
}
this->boundingBox.y = y;

isFacingUp = true;
isFacingDown = false;
isFacingRight = false;
isFacingLeft = false;
}

void Player::moveDown() {
Expand All @@ -31,6 +38,11 @@ void Player::moveDown() {
y += speed;
}
this->boundingBox.y = y;

isFacingUp = false;
isFacingDown = true;
isFacingRight = false;
isFacingLeft = false;
}

void Player::moveLeft() {
Expand All @@ -39,6 +51,11 @@ void Player::moveLeft() {
x -= speed;
}
this->boundingBox.x = x;

isFacingUp = false;
isFacingDown = false;
isFacingRight = false;
isFacingLeft = true;
}

void Player::moveRight() {
Expand All @@ -47,6 +64,11 @@ void Player::moveRight() {
x += speed;
}
this->boundingBox.x = x;

isFacingUp = false;
isFacingDown = false;
isFacingRight = true;
isFacingLeft = false;
}

void Player::handleEvent(SDL_Event *event) {
Expand All @@ -67,11 +89,42 @@ void Player::handleEvent(SDL_Event *event) {
case SDLK_RIGHT:
moveRight();
break;
case SDLK_RETURN:
attack();
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "enter pressed!!!!");
}
}
}

void Player::render(SDL_Renderer *renderer) { Character::render(renderer); }
void Player::attack() {
if (isFacingDown) {
auto bullet = std::make_unique<Projectile>(
"Bullet", x, y, renderer, "sprites/pepe.png", Direction::DOWN);
bullets.push_back(std::move(bullet));
}
if (isFacingUp) {
auto bullet = std::make_unique<Projectile>(
"Bullet", x, y, renderer, "sprites/pepe.png", Direction::UP);
bullets.push_back(std::move(bullet));
}
if (isFacingRight) {
auto bullet = std::make_unique<Projectile>(
"Bullet", x, y, renderer, "sprites/pepe.png", Direction::RIGHT);
bullets.push_back(std::move(bullet));
}
if (isFacingLeft) {
auto bullet = std::make_unique<Projectile>(
"Bullet", x, y, renderer, "sprites/pepe.png", Direction::LEFT);
bullets.push_back(std::move(bullet));
}
}

void Player::render(SDL_Renderer *renderer) {
Character::render(renderer);
for (auto &bullet : bullets) {
bullet->render(renderer);
}
}

bool Player::isColliding(const SDL_Rect &box) {
return Character::isColliding(box);
Expand All @@ -81,6 +134,21 @@ std::string Player::getName() { return Character::getName(); };

SDL_Rect Player::getBoundingBox() { return Character::getBoundingBox(); };

void Player::handleCollision() {}
void Player::handleCollision(IEntity *entity) {
for (auto &bullet : bullets) {
bullet->handleCollision(entity);
}
}

void Player::update() {
for (auto &bullet : bullets) {
bullet->update();
}

void Player::update() {}
// Remove bullets that are out of bounds or have collided with something
bullets.erase(std::remove_if(bullets.begin(), bullets.end(),
[](const std::unique_ptr<Projectile> &bullet) {
return bullet->isOutOfBounds();
}),
bullets.end());
}
Loading

0 comments on commit 98420ed

Please sign in to comment.