diff --git a/Faceball2030/Editor.h b/Faceball2030/Editor.h index 4cd6007..f80de93 100644 --- a/Faceball2030/Editor.h +++ b/Faceball2030/Editor.h @@ -11,6 +11,7 @@ enum EnemyID { EXIT, START, SHOOTME, + ISHOOT, SONAR, COIN = 56, POWERUP_ARMOR = 57, diff --git a/Faceball2030/assets/enemies/IShoot.mtl b/Faceball2030/assets/enemies/IShoot.mtl new file mode 100644 index 0000000..b875557 --- /dev/null +++ b/Faceball2030/assets/enemies/IShoot.mtl @@ -0,0 +1,11 @@ +# Exported from Wings 3D 2.2.9 +newmtl IShoot +Ns 19.999999999999996 +d 1.0 +illum 2 +Kd 1.0 1.0 1.0 +Ka 0.0 0.0 0.0 +Ks 0.19 0.19 0.19 +Ke 0.0 0.0 0.0 +map_Kd IShoot.png + diff --git a/Faceball2030/assets/enemies/IShoot.png b/Faceball2030/assets/enemies/IShoot.png new file mode 100644 index 0000000..2d8f5a7 Binary files /dev/null and b/Faceball2030/assets/enemies/IShoot.png differ diff --git a/Faceball2030/assets/enemies/IShoot.wings b/Faceball2030/assets/enemies/IShoot.wings new file mode 100644 index 0000000..5f3fafa Binary files /dev/null and b/Faceball2030/assets/enemies/IShoot.wings differ diff --git a/Faceball2030/assets/enemies/auvBG.png b/Faceball2030/assets/enemies/auvBG.png new file mode 100644 index 0000000..db95ba4 Binary files /dev/null and b/Faceball2030/assets/enemies/auvBG.png differ diff --git a/Faceball2030/main.cpp b/Faceball2030/main.cpp index d78792d..18b8fe4 100644 --- a/Faceball2030/main.cpp +++ b/Faceball2030/main.cpp @@ -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& 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&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(); diff --git a/Faceball2030/main.h b/Faceball2030/main.h index 1581070..f0c0fe0 100644 --- a/Faceball2030/main.h +++ b/Faceball2030/main.h @@ -162,7 +162,7 @@ struct EnemyData { float rotSpd = PI / 8; int ammo = 2; float fireDelay = 1; - float reloadTime = 3; + float radius = 0.2f; }; struct mat4x4 @@ -170,7 +170,12 @@ struct mat4x4 float m[4][4] = { 0 }; }; -struct Enemy : Object { +enum class Phase { + DEFAULT, + TURNING, +}; + +struct Enemy : public Object { private: EnemyID id; int health=1; @@ -178,7 +183,9 @@ struct Enemy : Object { float fireDelay=0; float deathTimer=0; float colorFactor = 0; + Phase phase=Phase::DEFAULT; public: + float turnAmt = 0; Enemy(EnemyID id, vec3d pos, float rot, float radius); EnemyID GetID(); void Hurt(); @@ -188,6 +195,11 @@ struct Enemy : Object { void increaseColorFactor(float fElapsedTime); float getColorFactor(); void decreaseColorFactor(); + Phase GetPhase(); + void SetPhase(Phase phase); + bool CanShoot(); + void ShootBullet(); + void ReloadBullet(float fElapsedTime); }; class FaceBall : public PixelGameEngine @@ -204,16 +216,15 @@ class FaceBall : public PixelGameEngine std::mapenemyData; std::vectorenemies; private: - Mesh mapWalls,mapFloor,enemy_ShootMe,bullet,green_bullet,undefined, - enemy_Sonar, mapExit; + Mesh mapWalls,mapFloor,enemy_ShootMe,undefined, + enemy_Sonar, mapExit,enemy_IShoot; Decal* dot, * enemy_ShootMe_tex,*bullet_tex,*wall_tex,*floor_tex, - *enemy_Sonar_tex,*hud,*exit_wall_tex; + *enemy_Sonar_tex,*hud,*exit_wall_tex,*enemy_IShoot_tex; vi2d MAP_SIZE; vi2d exitCoords = { 0,0 }; std::vector>map; std::vectorobjects; - std::vectorbullets; GAMEMODE mode=GAMEMODE::GAME; Editor editor; int MapWallsObjectIndex = -1; @@ -240,7 +251,6 @@ class FaceBall : public PixelGameEngine float freeRoamCamera_pitch = pitch; float freeRoamCamera_yaw = fYaw; - float shotSpd = 4.0f; float moveSpd = 2.0f; float hudOffset = 0; float hudOffsetAcc = 0; @@ -277,10 +287,15 @@ class FaceBall : public PixelGameEngine void InitializeEnemyData(); void InitializeBulletColors(); void LoadLevel(int level); + void RenderBulletMesh(mat4x4& matView, std::vector& vecTrianglesToRaster, Bullet& b); void RenderMesh(mat4x4&matView, std::vector&vecTrianglesToRaster,Object&o); void RunEnemyAI(Enemy& e,float fElapsedTime); void RenderHud(float fElapsedTime); + void ConvertBulletColor(Mesh& bullet, Pixel col); public: + std::vectorbullets; + Mesh bullet; + float shotSpd = 4.0f; static bool CheckCollision(vec3d movementVector,vf2d pos,float radius); static int CheckEnemyCollision(vec3d movementVector, vf2d pos, float radius); void SubtractTag();