|
|
|
@ -12,12 +12,7 @@ FaceBall* game; |
|
|
|
|
|
|
|
|
|
Enemy::Enemy(EnemyID id,vec3d pos,float rot,float radius) |
|
|
|
|
:id(id), health(game->enemyData[id].health), fireDelay(0), |
|
|
|
|
Object({game->enemyData[id].mesh,pos,rot,radius}) { |
|
|
|
|
EnemyData data = game->enemyData[id]; |
|
|
|
|
for (int i = 0; i < data.ammo; i++) { |
|
|
|
|
shots.push_back({ data.reloadTime }); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Object({game->enemyData[id].mesh,pos,rot,radius}) {} |
|
|
|
|
|
|
|
|
|
EnemyID Enemy::GetID() { |
|
|
|
|
return id; |
|
|
|
@ -51,12 +46,34 @@ void Enemy::decreaseColorFactor() { |
|
|
|
|
colorFactor--; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Phase Enemy::GetPhase() { |
|
|
|
|
return phase; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Enemy::SetPhase(Phase phase) { |
|
|
|
|
this->phase = phase; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Enemy::CanShoot() { |
|
|
|
|
return fireDelay <= 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Enemy::ShootBullet() { |
|
|
|
|
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 }); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Enemy::ReloadBullet(float fElapsedTime) { |
|
|
|
|
fireDelay -= fElapsedTime; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::InitializeEnemyData() { |
|
|
|
|
enemyData[EnemyID::NONE] = { "VOID",undefined,BLACK }; |
|
|
|
|
enemyData[EXIT] = { "EXIT",undefined,GREEN }; |
|
|
|
|
enemyData[START] = { "SPAWN POSITION",undefined,{128,64,0} }; |
|
|
|
|
enemyData[SHOOTME] = { "SHOOTME",enemy_ShootMe,YELLOW,1,1,PI / 8,2,1,3 }; |
|
|
|
|
enemyData[SONAR] = { "Sonar",enemy_Sonar,RED,5,1,PI / 8,2,1,3 }; |
|
|
|
|
enemyData[SHOOTME] = { "SHOOTME",enemy_ShootMe,YELLOW,1,1,PI / 8,2,1 }; |
|
|
|
|
enemyData[ISHOOT] = { "ISHOOT",enemy_IShoot,YELLOW,1,1,PI / 6,2,1,0.4f }; |
|
|
|
|
enemyData[SONAR] = { "Sonar",enemy_Sonar,RED,5,1,PI / 8,2,1 }; |
|
|
|
|
enemyData[COIN] = { "Coin",undefined,BLUE }; |
|
|
|
|
enemyData[POWERUP_ARMOR] = { "Armor",undefined,{96,0,96} }; |
|
|
|
|
enemyData[POWERUP_SPEED] = { "Speed",undefined,{96,0,96} }; |
|
|
|
@ -67,12 +84,11 @@ void FaceBall::InitializeEnemyData() { |
|
|
|
|
enemyData[AREA_MAP] = { "Map",undefined,GREEN }; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::InitializeBulletColors() { |
|
|
|
|
green_bullet = bullet; |
|
|
|
|
for (Triangle& t : green_bullet.tris) { |
|
|
|
|
t.col[0] = GREEN; |
|
|
|
|
t.col[1] = GREEN; |
|
|
|
|
t.col[2] = GREEN; |
|
|
|
|
void FaceBall::ConvertBulletColor(Mesh& bullet, Pixel col) { |
|
|
|
|
for (Triangle& t : bullet.tris) { |
|
|
|
|
t.col[0] = col; |
|
|
|
|
t.col[1] = col; |
|
|
|
|
t.col[2] = col; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -97,7 +113,7 @@ void FaceBall::LoadLevel(int level) |
|
|
|
|
mapFloor.tris.push_back({ {{(float)x + 1,0,(float)y},{(float)x,0,(float)y + 1},{(float)x + 1,0,(float)y + 1}},{{1,0},{0,1},{1,1}},{WHITE,WHITE,WHITE}, floor_tex }); |
|
|
|
|
EnemyID id = mapData[y][x].enemyId; |
|
|
|
|
if (id>=SHOOTME&& id < COIN) { |
|
|
|
|
enemies.push_back({ id,vec3d{x + 0.5f,0,y + 0.5f},((int)mapData[y][x].facingDir-1)*PI/2,0.2f}); |
|
|
|
|
enemies.push_back({ id,vec3d{x + 0.5f,0,y + 0.5f},((int)mapData[y][x].facingDir-1)*PI/2,enemyData[id].radius}); |
|
|
|
|
} |
|
|
|
|
if (id == EXIT) { |
|
|
|
|
exitCoords = { x,y }; |
|
|
|
@ -546,6 +562,15 @@ int FaceBall::Triangle_ClipAgainstPlane(vec3d plane_p, vec3d plane_n, Triangle& |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::RenderBulletMesh(mat4x4& matView, std::vector<Triangle>& vecTrianglesToRaster, Bullet& b) { |
|
|
|
|
for (auto& tri : b.mesh.tris) { |
|
|
|
|
tri.col[0] = b.col; |
|
|
|
|
tri.col[1] = b.col; |
|
|
|
|
tri.col[2] = b.col; |
|
|
|
|
} |
|
|
|
|
RenderMesh(matView, vecTrianglesToRaster, b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::RenderMesh(mat4x4&matView,std::vector<Triangle>&vecTrianglesToRaster, Object&o) { |
|
|
|
|
for (auto& tri : o.mesh.tris) { |
|
|
|
|
Triangle triProjected, triTransformed, triViewed; |
|
|
|
@ -710,7 +735,7 @@ void FaceBall::RenderWorld() { |
|
|
|
|
RenderMesh(matView, vecTrianglesToRaster, enemy); |
|
|
|
|
} |
|
|
|
|
for (auto& bullet : bullets) { |
|
|
|
|
RenderMesh(matView, vecTrianglesToRaster, bullet); |
|
|
|
|
RenderBulletMesh(matView, vecTrianglesToRaster, bullet); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//std::sort(vecTrianglesToRaster.begin(),vecTrianglesToRaster.end(),[](triangle&t1,triangle&t2){return (t1.p[0].z+t1.p[1].z+t1.p[2].z)/3.0f>(t2.p[0].z+t2.p[1].z+t2.p[2].z)/3.0f;});
|
|
|
|
@ -797,7 +822,7 @@ void FaceBall::HandleKeys(float fElapsedTime) { |
|
|
|
|
else { |
|
|
|
|
pitch = 0; |
|
|
|
|
if (GetMouse(0).bPressed) { |
|
|
|
|
bullets.push_back({ green_bullet,{player.GetPos().x,player.GetPos().y - 0.15f, player.GetPos().z},fYaw,0.125f,{shotSpd * std::cosf(fYaw),shotSpd * std::sinf(fYaw)},GREEN,true }); |
|
|
|
|
bullets.push_back({ bullet,{player.GetPos().x,player.GetPos().y - 0.15f, player.GetPos().z},fYaw,0.125f,{shotSpd * std::cosf(fYaw),shotSpd * std::sinf(fYaw)},GREEN,true }); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (GetKey(Q).bHeld) { |
|
|
|
@ -941,8 +966,10 @@ bool FaceBall::OnUserCreate() |
|
|
|
|
enemy_Sonar_tex = new Decal(new Sprite("assets/enemies/Sonar.png")); |
|
|
|
|
hud = new Decal(new Sprite("assets/hud.png")); |
|
|
|
|
exit_wall_tex = new Decal(new Sprite("assets/exitwall.png")); |
|
|
|
|
enemy_IShoot_tex = new Decal(new Sprite("assets/enemies/IShoot.png")); |
|
|
|
|
|
|
|
|
|
enemy_ShootMe = { "assets/enemies/ShootMe.obj", enemy_ShootMe_tex }; |
|
|
|
|
enemy_IShoot = { "assets/enemies/IShoot.obj", enemy_IShoot_tex }; |
|
|
|
|
enemy_Sonar = { "assets/enemies/Sonar.obj", enemy_Sonar_tex }; |
|
|
|
|
bullet = { "assets/enemies/bullet.obj",bullet_tex }; |
|
|
|
|
mapExit = { "assets/Exit.obj",dot }; |
|
|
|
@ -950,7 +977,6 @@ bool FaceBall::OnUserCreate() |
|
|
|
|
mapFloor.texture = floor_tex; |
|
|
|
|
|
|
|
|
|
InitializeEnemyData(); |
|
|
|
|
InitializeBulletColors(); |
|
|
|
|
|
|
|
|
|
LoadLevel(1); |
|
|
|
|
|
|
|
|
@ -1124,10 +1150,40 @@ void FaceBall::RunEnemyAI(Enemy& e,float fElapsedTime) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
EnemyData dat = enemyData[e.GetID()]; |
|
|
|
|
e.ReloadBullet(fElapsedTime); |
|
|
|
|
switch (e.GetID()) { |
|
|
|
|
case SHOOTME: { |
|
|
|
|
e.rot += 0.5 * fElapsedTime; |
|
|
|
|
}break; |
|
|
|
|
case ISHOOT: { |
|
|
|
|
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)) { |
|
|
|
|
e.pos.x += movementVec.x; |
|
|
|
|
e.pos.z += movementVec.y; |
|
|
|
|
if (e.CanShoot()) { |
|
|
|
|
e.ShootBullet(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
e.SetPhase(Phase::TURNING); |
|
|
|
|
e.turnAmt = PI; |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
case Phase::TURNING: { |
|
|
|
|
if (e.turnAmt > 0) { |
|
|
|
|
float rotAmt = std::min(e.turnAmt,dat.rotSpd * fElapsedTime); |
|
|
|
|
e.turnAmt -= rotAmt; |
|
|
|
|
e.rot += rotAmt; |
|
|
|
|
if (e.turnAmt <= 0) { |
|
|
|
|
e.SetPhase(Phase::DEFAULT); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1189,6 +1245,7 @@ void FaceBall::OnTextEntryComplete(const std::string& sText) { |
|
|
|
|
|
|
|
|
|
int main() |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
FaceBall demo; |
|
|
|
|
if (demo.Construct(1280, 720, 1, 1)) |
|
|
|
|
demo.Start(); |
|
|
|
|