From 20c5ce9c5c06f34010f74ac5431ff16592081fad Mon Sep 17 00:00:00 2001 From: sigonasr2 Date: Sun, 16 Apr 2023 18:38:27 -0500 Subject: [PATCH] Physical collisions with enemies and getting shot causes blinking to occur. --- Faceball2030/assets/map/map1.map | 2 +- Faceball2030/main.cpp | 84 +++++++++++++++++++++++--------- Faceball2030/main.h | 13 +++-- 3 files changed, 71 insertions(+), 28 deletions(-) diff --git a/Faceball2030/assets/map/map1.map b/Faceball2030/assets/map/map1.map index e6b3bdd..c80fd62 100644 --- a/Faceball2030/assets/map/map1.map +++ b/Faceball2030/assets/map/map1.map @@ -9,7 +9,7 @@ 8200 8204 40969 -32776 +41368 24576 8194 8202 diff --git a/Faceball2030/main.cpp b/Faceball2030/main.cpp index 805af74..bd6557f 100644 --- a/Faceball2030/main.cpp +++ b/Faceball2030/main.cpp @@ -18,8 +18,14 @@ EnemyID Enemy::GetID() { return id; } -void Enemy::Hurt() { - health--; +void Enemy::Hurt(int damage) { + lastHitTime = 0.2f; + for (Triangle& t : mesh.tris) { + t.col[0] = BLACK; + t.col[1] = BLACK; + t.col[2] = BLACK; + } + health-=damage; } bool Enemy::isDead() { @@ -58,15 +64,30 @@ bool Enemy::CanShoot() { return fireDelay <= 0; } -void Enemy::ShootBullet() { +void Enemy::ShootBullet(int myIndex) { fireDelay = game->enemyData[GetID()].fireDelay; - game->bullets.push_back({ game->bullet, pos,rot,0.2f,{std::cosf(rot) * game->shotSpd,std::sinf(rot) * game->shotSpd }, YELLOW,false,GetID(),blinking}); + game->bullets.push_back({ game->bullet, pos,rot,0.2f,{std::cosf(rot) * game->shotSpd,std::sinf(rot) * game->shotSpd }, YELLOW,false,GetID(),myIndex,blinking}); } void Enemy::ReloadBullet(float fElapsedTime) { fireDelay -= fElapsedTime; } +void Enemy::reduceLastHitTimer(float fElapsedTime) { + lastHitTime -= fElapsedTime; + if (lastHitTime <= 0.0f) { + for (Triangle&t:mesh.tris) { + t.col[0] = WHITE; + t.col[1] = WHITE; + t.col[2] = WHITE; + } + } +} + +bool Enemy::isLastHitTimerActive() { + return lastHitTime > 0.0f; +} + void FaceBall::InitializeEnemyData() { enemyData[EnemyID::NONE] = { "VOID",undefined,BLACK }; enemyData[EXIT] = { "EXIT",undefined,GREEN }; @@ -1114,20 +1135,28 @@ bool FaceBall::OnUserCreate() return true; } +//Collisions will not occur if the player is dead. bool FaceBall::CheckPlayerCollision(vec3d movementVector, vf2d pos, float radius) { + if (game->hp <= 0) { return false; } vf2d newpos = { pos.x + movementVector.x,pos.y + movementVector.z }; float dist = std::sqrtf(std::powf(newpos.x - game->player.GetPos().x, 2) + std::powf(newpos.y - game->player.GetPos().z, 2)); return dist < radius + game->player.GetRadius(); } -int FaceBall::CheckEnemyCollision(vec3d movementVector, vf2d pos, float radius) { +//This returns the index of an enemy that collided (Or -1 if nothing was collided with). +//Collisions will not occur if the enemy is dead. +int FaceBall::CheckEnemyCollision(vec3d movementVector, vf2d pos, float radius,int ignoreIndex) { vf2d newpos = { pos.x + movementVector.x,pos.y + movementVector.z }; for (int i = 0; i < game->enemies.size();i++) { - Enemy& e = game->enemies[i]; - float dist = std::sqrtf(std::powf(newpos.x - e.pos.x, 2) + std::powf(newpos.y - e.pos.z, 2)); - if (dist < radius + e.radius) { - return i; + if (i != ignoreIndex) { + Enemy& e = game->enemies[i]; + if (!e.isDead()) { + float dist = std::sqrtf(std::powf(newpos.x - e.pos.x, 2) + std::powf(newpos.y - e.pos.z, 2)); + if (dist < radius + e.radius) { + return i; + } + } } } return -1; @@ -1139,19 +1168,25 @@ bool Bullet::Update(float fElapsedTime) { int collided_enemy = FaceBall::CheckEnemyCollision(adjustedSpd, { pos.x,pos.z }, 0.1); if (collided_enemy!=-1) { Enemy& enemy = game->enemies[collided_enemy]; - if (!enemy.isDead()) { - enemy.Hurt(); - if (enemy.isDead()) { - game->SubtractTag(); - } - return false; + enemy.Hurt(); + if (enemy.isDead()) { + game->SubtractTag(); } + return false; } } else { if (FaceBall::CheckPlayerCollision(adjustedSpd,{pos.x,pos.z},0.1)) { game->HurtPlayer(shooterID,shooterBlinking); return false; + } else + { + int enemyCollisionIndex = FaceBall::CheckEnemyCollision(adjustedSpd, { pos.x,pos.z }, 0.1, shooterIndex); + if (enemyCollisionIndex != -1) { + Enemy& enemy = game->enemies[enemyCollisionIndex]; + enemy.Hurt(0); + return false; + } } } if (!FaceBall::CheckCollision(adjustedSpd, {pos.x,pos.z}, 0.05)) { @@ -1280,7 +1315,7 @@ void FaceBall::RenderHud(float fElapsedTime) { DrawStringDecal({ float(ScreenWidth() / 2 - GetTextSize(bottomText).x / 2 * 3),float(ScreenHeight() - 140.f) }, bottomText, { 96,96,255 }, { 3,6 }); } vf2d hudAdjustment = { -32,-18 }; - vf2d hudLoc = { hudAdjustment.x + hp>0?hudOffset:0,hudAdjustment.y}; + vf2d hudLoc = { hudAdjustment.x + (hp>0?hudOffset:0),hudAdjustment.y}; DrawDecal(hudLoc, hud, { 1.05,1.05 }); DrawDecal(hudLoc + vf2d{ 704,56 } - hudAdjustment, life4, { 1,1 }, float(hp) / maxHP > 0.75f ? WHITE : VERY_DARK_GREEN); DrawDecal(hudLoc + vf2d{ 704 - 64,56 } - hudAdjustment, life3, { 1,1 }, float(hp) / maxHP > 0.34f && float(hp) / maxHP <= 0.75f ? WHITE : VERY_DARK_GREEN); @@ -1363,7 +1398,7 @@ void FaceBall::SubtractTag() { } } -void FaceBall::RunEnemyAI(Enemy& e,float fElapsedTime) { +void FaceBall::RunEnemyAI(Enemy& e,float fElapsedTime,int myIndex) { if (e.isDead()) { if (!e.deathAnimationOver()) { std::vector& tris = e.mesh.tris; @@ -1418,11 +1453,12 @@ void FaceBall::RunEnemyAI(Enemy& e,float fElapsedTime) { switch (e.GetPhase()) { case Phase::DEFAULT: { vf2d movementVec = {std::cosf(e.rot) * dat.movSpd * fElapsedTime,std::sinf(e.rot) * dat.movSpd * fElapsedTime }; - if (!CheckCollision({movementVec.x,0,movementVec.y},{e.pos.x,e.pos.z}, e.radius)) { + if (-1==CheckEnemyCollision({ movementVec.x,0,movementVec.y },{e.pos.x,e.pos.z},e.radius,myIndex)&& + !CheckCollision({movementVec.x,0,movementVec.y},{e.pos.x,e.pos.z}, e.radius)) { e.pos.x += movementVec.x; e.pos.z += movementVec.y; if (e.CanShoot()) { - e.ShootBullet(); + e.ShootBullet(myIndex); } } else { @@ -1458,9 +1494,12 @@ bool FaceBall::OnUserUpdate(float fElapsedTime) } } } - for (std::vector::iterator it = enemies.begin(); it != enemies.end(); ++it) { - Enemy& e = *it; - RunEnemyAI(e,fElapsedTime); + for (int i = 0; i < enemies.size(); i++) { + Enemy& e = enemies[i]; + if (e.isLastHitTimerActive()) { + e.reduceLastHitTimer(fElapsedTime); + } + RunEnemyAI(e, fElapsedTime,i); } switch (mode) { case GAME: { @@ -1503,7 +1542,6 @@ void FaceBall::OnTextEntryComplete(const std::string& sText) { int main() { - FaceBall demo; if (demo.Construct(1280, 720, 1, 1)) demo.Start(); diff --git a/Faceball2030/main.h b/Faceball2030/main.h index db16b03..c0ff13b 100644 --- a/Faceball2030/main.h +++ b/Faceball2030/main.h @@ -151,6 +151,7 @@ struct Bullet : Object{ Pixel col = GREEN; bool friendly=true; EnemyID shooterID; + int shooterIndex = -1; bool shooterBlinking = false; bool Update(float fElapsedTime); }; @@ -187,11 +188,13 @@ struct Enemy : public Object { float colorFactor = 0; Phase phase=Phase::DEFAULT; bool blinking = false; //TODO TO BE IMPLEMENTED. + float lastHitTime = 0; public: float turnAmt = 0; Enemy(EnemyID id, vec3d pos, float rot, float radius); EnemyID GetID(); - void Hurt(); + //Can set the damage to 0 to cause just a visual hit. + void Hurt(int damage=1); bool isDead(); void increaseDeathTimer(float fElapsedTime); bool deathAnimationOver(); @@ -201,8 +204,10 @@ struct Enemy : public Object { Phase GetPhase(); void SetPhase(Phase phase); bool CanShoot(); - void ShootBullet(); + void ShootBullet(int myIndex); void ReloadBullet(float fElapsedTime); + bool isLastHitTimerActive(); + void reduceLastHitTimer(float fElapsedTime); }; class FaceBall : public PixelGameEngine @@ -299,7 +304,7 @@ class FaceBall : public PixelGameEngine void RenderBulletMesh(mat4x4& matView, std::vector& vecTrianglesToRaster, Bullet& b); void RenderMesh(mat4x4&matView, std::vector&vecTrianglesToRaster,Object&o); void RenderMeshDeathScreen(mat4x4& matView, std::vector& vecTrianglesToRaster, Object& o); - void RunEnemyAI(Enemy& e,float fElapsedTime); + void RunEnemyAI(Enemy& e,float fElapsedTime,int myIndex); void RenderHud(float fElapsedTime); void ConvertBulletColor(Mesh& bullet, Pixel col); public: @@ -307,7 +312,7 @@ class FaceBall : public PixelGameEngine Mesh bullet; float shotSpd = 4.0f; static bool CheckCollision(vec3d movementVector,vf2d pos,float radius); - static int CheckEnemyCollision(vec3d movementVector, vf2d pos, float radius); + static int CheckEnemyCollision(vec3d movementVector, vf2d pos, float radius, int ignoreIndex = -1); static bool CheckPlayerCollision(vec3d movementVector, vf2d pos, float radius); void SubtractTag(); void HurtPlayer(EnemyID id, bool blinking = false);