|
|
|
@ -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<Triangle>& 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<Enemy>::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(); |
|
|
|
|