diff --git a/game/src/BulletManager.cpp b/game/src/BulletManager.cpp index 0a1108a2c4e7e88c829300b886ff367250ce7830..e77f0c8fb62e447a3572efe77637faf644073bc5 100644 --- a/game/src/BulletManager.cpp +++ b/game/src/BulletManager.cpp @@ -1,5 +1,6 @@ #include "BulletManager.hpp" #include <algorithm> +#include <box2d/b2_math.h> BulletManager::BulletManager(GameWindow *window, b2World* world) : m_world(world), m_window(window) {} @@ -21,16 +22,18 @@ void BulletManager::addPlayerProjectile(const b2Vec2 &player_position, const b2V { BulletObject *new_projectile = new BulletObject(m_world, player_position, b2Vec2(0.2f, 0.2f), 0.1f, 0.0f, m_window, "game/res/actor.spr"); new_projectile->ApplyLinearImpulse(impulse); - new_projectile->getBody()->GetUserData().pointer =1; // 1 = PlayerBullet (idenfier for contact listener) + new_projectile->getBody()->GetUserData().pointer = 1; // 1 = PlayerBullet (idenfier for contact listener) m_player_projectiles.emplace_back(new_projectile); } -void BulletManager::addEnemyProjectile(const b2Vec2 &enemy_position, const b2Vec2 &lify_velocity) +void BulletManager::addEnemyProjectile(const b2Vec2 &enemy_position, const b2Vec2& enemy_size, const float amplify_velocity) { b2Vec2 impulse = m_window->getPlayerPosition() - enemy_position; impulse.Normalize(); - impulse *= amplify_velocity.x; - BulletObject *new_projectile = new BulletObject(m_world, enemy_position, b2Vec2(0.2f, 0.2f), 0.1f, 0.0f, m_window, "game/res/actor.spr"); + //offset the enemy position to avoid self collision + b2Vec2 offset_position = enemy_position + enemy_size.x * impulse; //enemy_size.x is valid due to square hitbox + impulse *= amplify_velocity; + BulletObject *new_projectile = new BulletObject(m_world, offset_position, b2Vec2(0.2f, 0.2f), 0.1f, 0.0f, m_window, "game/res/actor.spr"); new_projectile->ApplyLinearImpulse(impulse); new_projectile->getBody()->GetUserData().pointer =3; // 3 = 'EnemyBullet (idenfier for contact listener) m_enemy_projectiles.emplace_back(new_projectile); diff --git a/game/src/BulletManager.hpp b/game/src/BulletManager.hpp index cda90bafc96f158635e7235f9145958aaa6e3eb4..c42cf85bbb7a1503371ed505c1c363b6201739a9 100644 --- a/game/src/BulletManager.hpp +++ b/game/src/BulletManager.hpp @@ -58,7 +58,7 @@ public: * @param enemy_position The position of the enemy firing the projectile in the world. * @param amplify_velocity The amplify velocity of the new projectile to speed up according to enemy type. */ - void addEnemyProjectile(const b2Vec2& enemy_position, const b2Vec2& amplify_velocity); + void addEnemyProjectile(const b2Vec2& enemy_position, const b2Vec2& enemy_size, const float amplify_velocity); /** * @brief Removes obsolete projectiles by handling destruction. diff --git a/game/src/ContactListener.cpp b/game/src/ContactListener.cpp index 10ac4f0daedbd5c5bb6173da6a363e0896d696c2..0479e59ca773dbda8f9aec19591cf96c5c48eb44 100644 --- a/game/src/ContactListener.cpp +++ b/game/src/ContactListener.cpp @@ -1,47 +1,71 @@ #include "ContactListener.hpp" +#include <iostream> -void ContactListener::BeginContact(b2Contact* contact) { - b2Fixture* fixtureA = contact->GetFixtureA(); - b2Fixture* fixtureB = contact->GetFixtureB(); +void ContactListener::BeginContact(b2Contact *contact) +{ + b2Fixture *fixtureA = contact->GetFixtureA(); + b2Fixture *fixtureB = contact->GetFixtureB(); - b2Body* bodyA = fixtureA->GetBody(); - b2Body* bodyB = fixtureB->GetBody(); + b2Body *bodyA = fixtureA->GetBody(); + b2Body *bodyB = fixtureB->GetBody(); HandleCollision(bodyA, bodyB); } -void ContactListener::EndContact(b2Contact* contact) { - +void ContactListener::EndContact(b2Contact *contact) +{ } -void ContactListener::HandleCollision(b2Body* bodyA, b2Body* bodyB) { +void ContactListener::HandleCollision(b2Body *bodyA, b2Body *bodyB) +{ // Player Bullet ID: 1 - // Enemy ID: 2 + // Player ID: 2 // Enemy Bullet ID: 3 + // Enemy ID: 4 - if (bodyA->GetUserData().pointer == 1) { + // Player Bullet Collision + + if (bodyA->GetUserData().pointer == 1) + { playerBulletsToDestroy.push_back(bodyA); - if (bodyB->GetUserData().pointer == 2) { + if (bodyB->GetUserData().pointer == 4) + { enemiesToDestroy.push_back(bodyB); - } } - if (bodyB->GetUserData().pointer == 1) { + if (bodyB->GetUserData().pointer == 1) + { playerBulletsToDestroy.push_back(bodyB); - if (bodyA->GetUserData().pointer == 2) { + if (bodyA->GetUserData().pointer == 4) + { enemiesToDestroy.push_back(bodyA); } } - if (bodyA->GetUserData().pointer == 3) { - enemyBulletsToDestroy.push_back(bodyA); - } + // Enemy Bullet Collision - if (bodyB->GetUserData().pointer == 3) { - enemyBulletsToDestroy.push_back(bodyB); + if (bodyA->GetUserData().pointer == 3) + { + enemyBulletsToDestroy.push_back(bodyA); + + if (bodyB->GetUserData().pointer == 2) + { + // Player Hit + std::cout << "Player Hit" << std::endl; + } } + if (bodyB->GetUserData().pointer == 3) + { + enemyBulletsToDestroy.push_back(bodyB); + + if (bodyA->GetUserData().pointer == 2) + { + // Player Hit + std::cout << "Player Hit" << std::endl; + } + } } diff --git a/game/src/Enemy.cpp b/game/src/Enemy.cpp index 81b5d243680815bfe6cbe57667aa9b682ca16275..d67721c4be6e85508291542fccd34b66b0910cce 100644 --- a/game/src/Enemy.cpp +++ b/game/src/Enemy.cpp @@ -2,31 +2,46 @@ #include <box2d/b2_math.h> Enemy::Enemy(b2World *world, const b2Vec2 &position, const b2Vec2 &size, float density, float friction, - BulletManager& bulletmanager, GameWindow *window, const std::string &filepath) - : DynamicObject(world, position, size, density, friction, window, filepath), m_bulletManager(bulletmanager) + BulletManager &bulletmanager, GameWindow *window, const std::string &filepath) + : DynamicObject(world, position, size, density, friction, window, filepath), m_bulletManager(bulletmanager), + m_lastFire(1000), m_fireRate(2), m_fireDelay(static_cast<Uint32>(std::round(1000.0 / m_fireRate))) { - m_body->GetUserData().pointer =2; // 2 = Enemy (idenfier for contact listener) + m_body->GetUserData().pointer = 4; // 4 = Enemy (idenfier for contact listener) } void Enemy::render() { - SDL_Rect rectangle; - rectangle.w = m_size.x; - rectangle.h = m_size.y; - rectangle.x = static_cast<int32_t>(getPosition().x) - m_size.x / 2; - rectangle.y = static_cast<int32_t>(getPosition().y) - m_size.y / 2; + SDL_Rect rectangle; + rectangle.w = m_size.x; + rectangle.h = m_size.y; + rectangle.x = static_cast<int32_t>(getPosition().x) - m_size.x / 2; + rectangle.y = static_cast<int32_t>(getPosition().y) - m_size.y / 2; - // Draw test Rectangle - SDL_SetRenderDrawColor(m_window->renderer(), 255, 0, 0, 255); - SDL_RenderFillRect(m_window->renderer(), &rectangle); + // Draw test Rectangle + SDL_SetRenderDrawColor(m_window->renderer(), 255, 0, 0, 255); + SDL_RenderFillRect(m_window->renderer(), &rectangle); } -void Enemy::shoot() +bool Enemy::shoot() { + Uint32 currentTime = SDL_GetTicks(); + if (currentTime - m_lastFire < m_fireDelay) + { + return false; + + } b2Vec2 enemy_position = getPosition(); - //offset the enemy position to avoid self collision - enemy_position += b2Vec2(0, 40.0f); - m_bulletManager.addEnemyProjectile(enemy_position, b2Vec2(5.0f, 5.0f)); + // offset the enemy position to avoid self collision -> now in BulletManager + // enemy_position += b2Vec2(0, 40.0f); + m_bulletManager.addEnemyProjectile(enemy_position, m_size, 5.0f); + m_lastFire = currentTime; + return true; +} + +void Enemy::set_fireRate(int rate) +{ + m_fireRate = rate; + m_fireDelay = static_cast<Uint32>(std::round(1000.0 / m_fireRate)); } b2Body *Enemy::getBody() diff --git a/game/src/Enemy.hpp b/game/src/Enemy.hpp index 0ba100b4146a1ff7593dcd8a8f86c3c25848b025..f350e6074bd111f5809c957c2e46f97d8a15b69e 100644 --- a/game/src/Enemy.hpp +++ b/game/src/Enemy.hpp @@ -55,11 +55,23 @@ public: * This method creates a new projectile at the enemy's position and fires it towards the player's * current position. The projectile is added to the `BulletManager` object for tracking and rendering. */ - void shoot(); + bool shoot(); + + /** + * @brief Sets the enemy's fire rate. + * + * This method adjusts the number of bullets the enemy can fire per second. + * + * @param rate The fire rate in bullets per second. + */ + void set_fireRate(int rate); private: int health; /**< The health of the enemy, representing its hit points. */ int damage; /**< The amount of damage the enemy can inflict on other objects. */ + int m_fireRate; /**< The rate at which the enemy can fire projectiles. */ + Uint32 m_fireDelay; /**< The delay between shots in milliseconds. */ + Uint32 m_lastFire; /**< The timestamp of the last shot fired. */ BulletManager& m_bulletManager; /**< The `BulletManager` object for handling enemy projectiles. */ }; diff --git a/game/src/EnemyManager.cpp b/game/src/EnemyManager.cpp index fb60017215834364c1afde76dd85b729e9a3b94a..ff13598c0fa5214b7f5c1369d8300af1a4358889 100644 --- a/game/src/EnemyManager.cpp +++ b/game/src/EnemyManager.cpp @@ -30,7 +30,8 @@ void EnemyManager::randomEnemyShoot() } int random = rand() % m_enemies.size(); // get random number between 0 and size of enemies vector - m_enemies[random]->shoot(); + bool successful = m_enemies[random]->shoot(); + //further logic can be added here } void EnemyManager::update(std::vector<b2Body *> enemiesToDestroy) diff --git a/game/src/Player.cpp b/game/src/Player.cpp index 736a9245506876c25e4b1c7f5a00fbc8cc37cce2..8fa94f98873082949a7983387e9fde61cba48706 100644 --- a/game/src/Player.cpp +++ b/game/src/Player.cpp @@ -5,7 +5,9 @@ Player::Player(b2World *world, const b2Vec2 &position, const b2Vec2 &size, float : DynamicObject(world, position, size, density, friction, window, filepath), m_alive(true), m_bulletManager(bulletmanager), m_lastFire(1000), m_fireRate(5), m_fireDelay(static_cast<Uint32>(std::round(1000.0 / m_fireRate))) -{} +{ + m_body->GetUserData().pointer = 2; // 2 = Player (idenfier for contact listener) +} Player::~Player() { // Empty implementation, but needed for vtable generation