|
|
|
@ -66,7 +66,7 @@ bool Enemy::CanShoot() { |
|
|
|
|
|
|
|
|
|
void Enemy::ShootBullet(int myIndex) { |
|
|
|
|
fireDelay = game->enemyData[GetID()].fireDelay; |
|
|
|
|
game->bullets.push_back({ game->bullet, {pos.x,pos.y+0.15f,pos.z},rot,0.2f,{std::cosf(rot) * game->shotSpd,std::sinf(rot) * game->shotSpd }, YELLOW,false,GetID(),myIndex,blinking}); |
|
|
|
|
game->bullets.push_back({ game->bullet, {pos.x,pos.y+0.15f,pos.z},rot,0.2f,1,true,{std::cosf(rot) * game->shotSpd,std::sinf(rot) * game->shotSpd }, YELLOW,false,GetID(),myIndex,blinking}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Enemy::ReloadBullet(float fElapsedTime) { |
|
|
|
@ -94,6 +94,7 @@ bool Enemy::isExplosive() { |
|
|
|
|
|
|
|
|
|
void Enemy::setExploded(bool exploded) { |
|
|
|
|
this->exploded = exploded; |
|
|
|
|
game->RegenerateMinimap(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Enemy Enemy::freshCopy(bool randomizeLoc){ |
|
|
|
@ -216,6 +217,11 @@ bool Enemy::Update(float fElapsedTime) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else
|
|
|
|
|
if (fElapsedTime > 3/120.f) { |
|
|
|
|
mesh.tris.clear(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -237,6 +243,9 @@ void Enemy::OnDeathEvent() { |
|
|
|
|
if (game->enemyData[id].powerupDrop != PowerupType::NONE) { |
|
|
|
|
game->SpawnPowerup(game->enemyData[id].powerupDrop, pos); |
|
|
|
|
} |
|
|
|
|
if (game->PlayerHasMapUpgrade()){ |
|
|
|
|
game->RegenerateMinimap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vf2d FaceBall::GetPlayerPos() { |
|
|
|
@ -254,8 +263,10 @@ void FaceBall::InitializeEnemyData() { |
|
|
|
|
enemyData[SHOOTME] = { "SHOOTME",enemy_ShootMe,YELLOW,1,1,0.5,2,1,0.2f,true }; |
|
|
|
|
enemyData[SHOOTME2] = { "SHOOTME2",enemy_ShootMe2,YELLOW,1,1,PI / 6,2,1,0.35f,true }; |
|
|
|
|
enemyData[ISHOOT] = { "ISHOOT",enemy_IShoot,YELLOW,1,1,0.5,2,3,0.4f,true }; |
|
|
|
|
enemyData[ISHOOT2] = { "ISHOOT2",enemy_IShoot2,YELLOW,1,1,PI / 6,2,1,0.35f,true }; |
|
|
|
|
enemyData[SHOOTME_ARMOR] = { "SHOOTME",enemy_ShootMe,YELLOW,6,1,0.5,2,1,0.3f,true,PowerupType::ARMOR,true }; |
|
|
|
|
enemyData[ISHOOT_MAP] = { "ISHOOT",enemy_IShoot,YELLOW,7,1,0.5,2,2,0.3f,true,PowerupType::MAP,true }; |
|
|
|
|
enemyData[ISHOOT2_SPEED] = { "ISHOOT2",enemy_IShoot2,YELLOW,6,1,PI / 6,2,1,0.35f,true,PowerupType::SPEED,true }; |
|
|
|
|
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} }; |
|
|
|
@ -424,8 +435,65 @@ void FaceBall::LoadLevel(int level) |
|
|
|
|
walls = { mapWalls }; |
|
|
|
|
MapWallsObjectIndex = objects.size()-1; |
|
|
|
|
objects.push_back({ mapFloor,{0,0,0},0,0 }); |
|
|
|
|
objects.push_back({ worldSkyBox,{MAP_SIZE.x/2.f,0,MAP_SIZE.y/2.f},0,0,std::max(float(MAP_SIZE.x),float(MAP_SIZE.y))*2,false }); |
|
|
|
|
//objects.push_back({ game->mapExit,{(float)exitCoords.x+0.5f,0,(float)exitCoords.y+0.5f},0,0.4f });
|
|
|
|
|
exit = { game->mapExit,{(float)exitCoords.x + 0.5f,0.02f,(float)exitCoords.y + 0.5f},0,0.4f }; |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::RegenerateMinimap(){ |
|
|
|
|
vf2d mapCenter = {float(ScreenWidth()-364),float(164)}; |
|
|
|
|
vf2d mapSprSize = {float(mapSpr->width),float(mapSpr->height)}; |
|
|
|
|
SetDrawTarget(mapSpr); |
|
|
|
|
Clear(BLACK); |
|
|
|
|
const int MAP_VISIBILITY=6; |
|
|
|
|
for (int x=0;x<MAP_SIZE.x;x++){ |
|
|
|
|
for (int y=0;y<MAP_SIZE.y;y++){ |
|
|
|
|
float dist = std::sqrtf(std::pow(player.GetPos().x-x,2)+std::pow(player.GetPos().z-y,2)); |
|
|
|
|
if (dist<MAP_VISIBILITY){ |
|
|
|
|
try{ |
|
|
|
|
MapSquare&square=map.at(y).at(x); |
|
|
|
|
vf2d squareLoc = vf2d{x*minimapGridSize.x,y*minimapGridSize.y}; |
|
|
|
|
uint8_t transparency=uint8_t((1-(float(dist)/MAP_VISIBILITY))*255); |
|
|
|
|
if (square.wallN){ |
|
|
|
|
DrawLine(squareLoc,squareLoc+vf2d{1.f,0.f}*minimapGridSize,Pixel{255,255,255,transparency}); |
|
|
|
|
} |
|
|
|
|
if (square.wallS){ |
|
|
|
|
DrawLine(squareLoc+vf2d{0,1.f}*minimapGridSize,squareLoc+vf2d{1,1}*minimapGridSize,Pixel{255,255,255,transparency}); |
|
|
|
|
} |
|
|
|
|
if (square.wallE){ |
|
|
|
|
DrawLine(squareLoc+vf2d{1,0}*minimapGridSize,squareLoc+vf2d{1,1}*minimapGridSize,Pixel{255,255,255,transparency}); |
|
|
|
|
} |
|
|
|
|
if (square.wallW){ |
|
|
|
|
DrawLine(squareLoc,squareLoc+vf2d{0,1}*minimapGridSize,Pixel{255,255,255,transparency}); |
|
|
|
|
} |
|
|
|
|
if (hasMapUpgrade){ |
|
|
|
|
for (Enemy&e:enemies){ |
|
|
|
|
if (!e.isDead()){ |
|
|
|
|
if (vi2d{int(e.pos.x),int(e.pos.z)}==vi2d{x,y}){ |
|
|
|
|
FillCircle(vi2d{int(squareLoc.x+0.5*minimapGridSize.x),int(squareLoc.y+0.5*minimapGridSize.y)},3,enemyData[e.GetID()].col*(1-(float(dist)/MAP_VISIBILITY))); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} catch (std::out_of_range const& exc) { |
|
|
|
|
std::cout << exc.what() << '\n'; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
float dist = std::sqrtf(std::pow(player.GetPos().x-exitCoords.x,2)+std::pow(player.GetPos().z-exitCoords.y,2)); |
|
|
|
|
if (tagsRemaining>0){ |
|
|
|
|
vf2d squareLoc = vf2d{exitCoords.x*minimapGridSize.x,exitCoords.y*minimapGridSize.y}; |
|
|
|
|
uint8_t transparency=uint8_t((1-(float(dist)/MAP_VISIBILITY))*255); |
|
|
|
|
DrawLine(squareLoc,squareLoc+vf2d{1.f,0.f}*minimapGridSize,Pixel{DARK_RED.r,DARK_RED.g,DARK_RED.b,transparency}); |
|
|
|
|
DrawLine(squareLoc+vf2d{0,1.f}*minimapGridSize,squareLoc+vf2d{1,1}*minimapGridSize,Pixel{DARK_RED.r,DARK_RED.g,DARK_RED.b,transparency}); |
|
|
|
|
DrawLine(squareLoc+vf2d{1,0}*minimapGridSize,squareLoc+vf2d{1,1}*minimapGridSize,Pixel{DARK_RED.r,DARK_RED.g,DARK_RED.b,transparency}); |
|
|
|
|
DrawLine(squareLoc,squareLoc+vf2d{0,1}*minimapGridSize,Pixel{DARK_RED.r,DARK_RED.g,DARK_RED.b,transparency}); |
|
|
|
|
} |
|
|
|
|
FillCircle(vi2d{int(exitCoords.x*minimapGridSize.x+0.5*minimapGridSize.x),int(exitCoords.y*minimapGridSize.x+0.5*minimapGridSize.y)},3,MAGENTA*(1-(float(dist)/MAP_VISIBILITY))); |
|
|
|
|
SetDrawTarget(nullptr); |
|
|
|
|
mapDecal->Update(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool FaceBall::CheckCollision(vec3d movementVector,vf2d pos,float radius){ |
|
|
|
@ -850,23 +918,32 @@ void FaceBall::RenderBulletMesh(mat4x4& matView, std::vector<Triangle>& vecTrian |
|
|
|
|
void FaceBall::RenderMesh(mat4x4&matView,std::vector<Triangle>&vecTrianglesToRaster, Object&o,bool translucent) { |
|
|
|
|
for (auto& tri : o.mesh.tris) { |
|
|
|
|
if (translucent&&tri.tex != exit_wall_tex && tri.tex != bullet_tex ||!translucent&&(tri.tex==exit_wall_tex || tri.tex == bullet_tex)) { continue; } |
|
|
|
|
Triangle triProjected, triTransformed, triViewed; |
|
|
|
|
Triangle triScaled,triProjected, triTransformed, triViewed; |
|
|
|
|
mat4x4 localMat = Matrix_MakeIdentity(); |
|
|
|
|
mat4x4 rotMat = Matrix_MakeRotationY(o.rot); |
|
|
|
|
localMat = Matrix_MultiplyMatrix(localMat, rotMat); |
|
|
|
|
mat4x4 matTrans = Matrix_MakeTranslation(o.pos.x, o.pos.y, o.pos.z); |
|
|
|
|
localMat = Matrix_MultiplyMatrix(localMat, matTrans); |
|
|
|
|
|
|
|
|
|
triTransformed.p[0] = Matrix_MultiplyVector(localMat, tri.p[0]); |
|
|
|
|
triTransformed.p[1] = Matrix_MultiplyVector(localMat, tri.p[1]); |
|
|
|
|
triTransformed.p[2] = Matrix_MultiplyVector(localMat, tri.p[2]); |
|
|
|
|
triTransformed.uv[0] = tri.uv[0]; |
|
|
|
|
triTransformed.uv[1] = tri.uv[1]; |
|
|
|
|
triTransformed.uv[2] = tri.uv[2]; |
|
|
|
|
triTransformed.col[0] = tri.col[0]; |
|
|
|
|
triTransformed.col[1] = tri.col[1]; |
|
|
|
|
triTransformed.col[2] = tri.col[2]; |
|
|
|
|
triTransformed.tex = tri.tex; |
|
|
|
|
for (int i = 0; i < 3; i++) { |
|
|
|
|
triScaled.p[i].x = tri.p[i].x*o.scale; |
|
|
|
|
triScaled.p[i].y = tri.p[i].y * o.scale; |
|
|
|
|
triScaled.p[i].z = tri.p[i].z * o.scale; |
|
|
|
|
triScaled.uv[i] = tri.uv[i]; |
|
|
|
|
triScaled.col[i] = tri.col[i]; |
|
|
|
|
} |
|
|
|
|
triScaled.tex = tri.tex; |
|
|
|
|
|
|
|
|
|
triTransformed.p[0] = Matrix_MultiplyVector(localMat, triScaled.p[0]); |
|
|
|
|
triTransformed.p[1] = Matrix_MultiplyVector(localMat, triScaled.p[1]); |
|
|
|
|
triTransformed.p[2] = Matrix_MultiplyVector(localMat, triScaled.p[2]); |
|
|
|
|
triTransformed.uv[0] = triScaled.uv[0]; |
|
|
|
|
triTransformed.uv[1] = triScaled.uv[1]; |
|
|
|
|
triTransformed.uv[2] = triScaled.uv[2]; |
|
|
|
|
triTransformed.col[0] = triScaled.col[0]; |
|
|
|
|
triTransformed.col[1] = triScaled.col[1]; |
|
|
|
|
triTransformed.col[2] = triScaled.col[2]; |
|
|
|
|
triTransformed.tex = triScaled.tex; |
|
|
|
|
|
|
|
|
|
vec3d normal, line1, line2; |
|
|
|
|
line1 = Vector_Sub(triTransformed.p[1], triTransformed.p[0]); |
|
|
|
@ -877,7 +954,7 @@ void FaceBall::RenderMesh(mat4x4&matView,std::vector<Triangle>&vecTrianglesToRas |
|
|
|
|
|
|
|
|
|
vec3d vCameraRay = Vector_Sub(triTransformed.p[0], freeRoam ? freeRoamCamera : player.GetPos()); |
|
|
|
|
|
|
|
|
|
if (Vector_DotProduct(normal, vCameraRay) < 0) { |
|
|
|
|
if (Vector_DotProduct(normal, vCameraRay) < 0||!o.affectedByLighting) { |
|
|
|
|
vec3d light_dir = Vector_Mul(vLookDir, -1); |
|
|
|
|
light_dir = Vector_Normalise(light_dir); |
|
|
|
|
|
|
|
|
@ -889,9 +966,11 @@ void FaceBall::RenderMesh(mat4x4&matView,std::vector<Triangle>&vecTrianglesToRas |
|
|
|
|
triViewed.uv[0] = triTransformed.uv[0]; |
|
|
|
|
triViewed.uv[1] = triTransformed.uv[1]; |
|
|
|
|
triViewed.uv[2] = triTransformed.uv[2]; |
|
|
|
|
triViewed.col[0] = Pixel(triTransformed.col[0].r * dp * dp, triTransformed.col[0].g * dp * dp, triTransformed.col[0].b * dp * dp); |
|
|
|
|
triViewed.col[1] = Pixel(triTransformed.col[1].r * dp * dp, triTransformed.col[1].g * dp * dp, triTransformed.col[1].b * dp * dp); |
|
|
|
|
triViewed.col[2] = Pixel(triTransformed.col[2].r * dp * dp, triTransformed.col[2].g * dp * dp, triTransformed.col[2].b * dp * dp); |
|
|
|
|
if (o.affectedByLighting) { |
|
|
|
|
triViewed.col[0] = Pixel(triTransformed.col[0].r * dp * dp, triTransformed.col[0].g * dp * dp, triTransformed.col[0].b * dp * dp); |
|
|
|
|
triViewed.col[1] = Pixel(triTransformed.col[1].r * dp * dp, triTransformed.col[1].g * dp * dp, triTransformed.col[1].b * dp * dp); |
|
|
|
|
triViewed.col[2] = Pixel(triTransformed.col[2].r * dp * dp, triTransformed.col[2].g * dp * dp, triTransformed.col[2].b * dp * dp); |
|
|
|
|
} |
|
|
|
|
Pixel originalCol[3] = { triViewed.col[0],triViewed.col[1],triViewed.col[2] }; |
|
|
|
|
float dist = std::sqrtf(std::powf((freeRoam ? freeRoamCamera : player.GetPos()).x - triTransformed.p[0].x, 2) + std::powf((freeRoam ? freeRoamCamera : player.GetPos()).y - triTransformed.p[0].y, 2) + std::powf((freeRoam ? freeRoamCamera : player.GetPos()).z - triTransformed.p[0].z, 2)); |
|
|
|
|
float dist2 = std::sqrtf(std::powf((freeRoam ? freeRoamCamera : player.GetPos()).x - triTransformed.p[1].x, 2) + std::powf((freeRoam ? freeRoamCamera : player.GetPos()).y - triTransformed.p[1].y, 2) + std::powf((freeRoam ? freeRoamCamera : player.GetPos()).z - triTransformed.p[1].z, 2)); |
|
|
|
@ -899,22 +978,31 @@ void FaceBall::RenderMesh(mat4x4&matView,std::vector<Triangle>&vecTrianglesToRas |
|
|
|
|
float colorMult = dist > 5 * PI / 3 ? 0 : std::sinf(0.3 * dist + PI / 2); |
|
|
|
|
float colorMult2 = dist2 > 5 * PI / 3 ? 0 : std::sinf(0.3 * dist2 + PI / 2); |
|
|
|
|
float colorMult3 = dist3 > 5 * PI / 3 ? 0 : std::sinf(0.3 * dist3 + PI / 2); |
|
|
|
|
triViewed.col[0] = Pixel(triViewed.col[0].r * colorMult, triViewed.col[0].g * colorMult, triViewed.col[0].b * colorMult); |
|
|
|
|
triViewed.col[1] = Pixel(triViewed.col[1].r * colorMult2, triViewed.col[1].g * colorMult2, triViewed.col[1].b * colorMult2); |
|
|
|
|
triViewed.col[2] = Pixel(triViewed.col[2].r * colorMult3, triViewed.col[2].g * colorMult3, triViewed.col[2].b * colorMult3); |
|
|
|
|
if (o.affectedByLighting) { |
|
|
|
|
triViewed.col[0] = Pixel(triViewed.col[0].r * colorMult, triViewed.col[0].g * colorMult, triViewed.col[0].b * colorMult); |
|
|
|
|
triViewed.col[1] = Pixel(triViewed.col[1].r * colorMult2, triViewed.col[1].g * colorMult2, triViewed.col[1].b * colorMult2); |
|
|
|
|
triViewed.col[2] = Pixel(triViewed.col[2].r * colorMult3, triViewed.col[2].g * colorMult3, triViewed.col[2].b * colorMult3); |
|
|
|
|
} |
|
|
|
|
if (!o.affectedByLighting) { |
|
|
|
|
triViewed.col[0] = originalCol[0]; |
|
|
|
|
triViewed.col[1] = originalCol[1]; |
|
|
|
|
triViewed.col[2] = originalCol[2]; |
|
|
|
|
} |
|
|
|
|
triViewed.tex = triTransformed.tex; |
|
|
|
|
|
|
|
|
|
for (Bullet& b : bullets) { |
|
|
|
|
float dist = std::sqrtf(std::powf(b.pos.x - triTransformed.p[0].x, 2) + std::powf(b.pos.y - triTransformed.p[0].y, 2) + std::powf(b.pos.z - triTransformed.p[0].z, 2)); |
|
|
|
|
float dist2 = std::sqrtf(std::powf(b.pos.x - triTransformed.p[1].x, 2) + std::powf(b.pos.y - triTransformed.p[1].y, 2) + std::powf(b.pos.z - triTransformed.p[1].z, 2)); |
|
|
|
|
float dist3 = std::sqrtf(std::powf(b.pos.x - triTransformed.p[2].x, 2) + std::powf(b.pos.y - triTransformed.p[2].y, 2) + std::powf(b.pos.z - triTransformed.p[2].z, 2)); |
|
|
|
|
float colorMult = (dist < 2 ? std::sinf(0.75 * dist + PI / 2) * 4 :1); |
|
|
|
|
float colorMult2 = (dist2 < 2 ? std::sinf(0.75 * dist2 + PI / 2) * 4 : 1); |
|
|
|
|
float colorMult3 = (dist3 < 2 ? std::sinf(0.75 * dist3 + PI / 2) * 4 : 1); |
|
|
|
|
Pixel lightCol = b.col / 2 + Pixel{ 128, 128, 128 }; |
|
|
|
|
if (dist < 2) {triViewed.col[0] = Pixel(std::min(255, std::max((int)originalCol[0].r, (int)(originalCol[0].r * colorMult / float(255.f/lightCol.r)))), std::min(255, std::max((int)originalCol[0].g, (int)(originalCol[0].g * colorMult / float(255.f / lightCol.g)))), std::min(255, std::max((int)originalCol[0].b, (int)(originalCol[0].b * colorMult / float(255.f / lightCol.b)))));} |
|
|
|
|
if (dist2 < 2) {triViewed.col[1] = Pixel(std::min(255, std::max((int)originalCol[1].r, (int)(originalCol[1].r * colorMult2 / float(255.f / lightCol.r)))), std::min(255, std::max((int)originalCol[1].g, (int)(originalCol[1].g * colorMult2 / float(255.f / lightCol.g)))), std::min(255, std::max((int)originalCol[1].b, (int)(originalCol[1].b * colorMult2 / float(255.f / lightCol.b)))));} |
|
|
|
|
if (dist3 < 2) {triViewed.col[2] = Pixel(std::min(255, std::max((int)originalCol[2].r, (int)(originalCol[2].r * colorMult3 / float(255.f / lightCol.r)))), std::min(255, std::max((int)originalCol[2].g, (int)(originalCol[2].g * colorMult3 / float(255.f / lightCol.g)))), std::min(255, std::max((int)originalCol[2].b, (int)(originalCol[2].b * colorMult3 / float(255.f / lightCol.b)))));} |
|
|
|
|
if (o.affectedByLighting) { |
|
|
|
|
for (Bullet& b : bullets) { |
|
|
|
|
float dist = std::sqrtf(std::powf(b.pos.x - triTransformed.p[0].x, 2) + std::powf(b.pos.y - triTransformed.p[0].y, 2) + std::powf(b.pos.z - triTransformed.p[0].z, 2)); |
|
|
|
|
float dist2 = std::sqrtf(std::powf(b.pos.x - triTransformed.p[1].x, 2) + std::powf(b.pos.y - triTransformed.p[1].y, 2) + std::powf(b.pos.z - triTransformed.p[1].z, 2)); |
|
|
|
|
float dist3 = std::sqrtf(std::powf(b.pos.x - triTransformed.p[2].x, 2) + std::powf(b.pos.y - triTransformed.p[2].y, 2) + std::powf(b.pos.z - triTransformed.p[2].z, 2)); |
|
|
|
|
float colorMult = (dist < 2 ? std::sinf(0.75 * dist + PI / 2) * 4 : 1); |
|
|
|
|
float colorMult2 = (dist2 < 2 ? std::sinf(0.75 * dist2 + PI / 2) * 4 : 1); |
|
|
|
|
float colorMult3 = (dist3 < 2 ? std::sinf(0.75 * dist3 + PI / 2) * 4 : 1); |
|
|
|
|
Pixel lightCol = b.col / 2 + Pixel{ 128, 128, 128 }; |
|
|
|
|
if (dist < 2) { triViewed.col[0] = Pixel(std::min(255, std::max((int)originalCol[0].r, (int)(originalCol[0].r * colorMult / float(255.f / lightCol.r)))), std::min(255, std::max((int)originalCol[0].g, (int)(originalCol[0].g * colorMult / float(255.f / lightCol.g)))), std::min(255, std::max((int)originalCol[0].b, (int)(originalCol[0].b * colorMult / float(255.f / lightCol.b))))); } |
|
|
|
|
if (dist2 < 2) { triViewed.col[1] = Pixel(std::min(255, std::max((int)originalCol[1].r, (int)(originalCol[1].r * colorMult2 / float(255.f / lightCol.r)))), std::min(255, std::max((int)originalCol[1].g, (int)(originalCol[1].g * colorMult2 / float(255.f / lightCol.g)))), std::min(255, std::max((int)originalCol[1].b, (int)(originalCol[1].b * colorMult2 / float(255.f / lightCol.b))))); } |
|
|
|
|
if (dist3 < 2) { triViewed.col[2] = Pixel(std::min(255, std::max((int)originalCol[2].r, (int)(originalCol[2].r * colorMult3 / float(255.f / lightCol.r)))), std::min(255, std::max((int)originalCol[2].g, (int)(originalCol[2].g * colorMult3 / float(255.f / lightCol.g)))), std::min(255, std::max((int)originalCol[2].b, (int)(originalCol[2].b * colorMult3 / float(255.f / lightCol.b))))); } |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
//triViewed.col = triTransformed.col;
|
|
|
|
|
|
|
|
|
@ -1443,6 +1531,16 @@ void FaceBall::RenderWorld() { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int FaceBall::PlayerActiveShotCount(int playerNumb){ |
|
|
|
|
int count=0; |
|
|
|
|
for (Bullet&b:bullets){ |
|
|
|
|
if (b.playerIndex==playerNumb){ |
|
|
|
|
count++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return count; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::HandleKeys(float fElapsedTime) { |
|
|
|
|
vec3d vForward = Vector_Mul(vLookDir, std::min(player.GetRadius()-0.00001f,moveSpd*fElapsedTime)); |
|
|
|
|
if (freeRoam) { |
|
|
|
@ -1456,8 +1554,10 @@ void FaceBall::HandleKeys(float fElapsedTime) { |
|
|
|
|
else { |
|
|
|
|
pitch = 0; |
|
|
|
|
if (GetMouse(0).bPressed) { |
|
|
|
|
if (bullets.size() < shotLimit) { |
|
|
|
|
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 (PlayerActiveShotCount(0) < shotLimit) { |
|
|
|
|
Bullet newBullet={ bullet,{player.GetPos().x,player.GetPos().y - 0.15f, player.GetPos().z},fYaw,0.125f,1,true,{shotSpd * std::cosf(fYaw),shotSpd * std::sinf(fYaw)},GREEN,true }; |
|
|
|
|
newBullet.playerIndex=0; |
|
|
|
|
bullets.push_back(newBullet); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1638,6 +1738,10 @@ void FaceBall::HandleKeys(float fElapsedTime) { |
|
|
|
|
if (GetKey(olc::F1).bPressed) { |
|
|
|
|
freeRoam = !freeRoam; |
|
|
|
|
} |
|
|
|
|
if (vi2d{int(player.GetPos().x),int(player.GetPos().z)}!=playerRoundedCoords){ |
|
|
|
|
playerRoundedCoords = vi2d{int(player.GetPos().x),int(player.GetPos().z)}; |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::AddWall(int dir, vi2d gridSquare) { |
|
|
|
@ -1685,6 +1789,7 @@ bool FaceBall::OnUserCreate() |
|
|
|
|
exit_wall_tex = new Decal(new Sprite("assets/exitwall.png")); |
|
|
|
|
enemy_ShootMe2_tex = new Decal(new Sprite("assets/enemies/ShootMe2.png")); |
|
|
|
|
enemy_IShoot_tex = new Decal(new Sprite("assets/enemies/IShoot.png")); |
|
|
|
|
enemy_IShoot2_tex = new Decal(new Sprite("assets/enemies/IShoot2.png")); |
|
|
|
|
life4 = new Decal(new Sprite("assets/life4.png")); |
|
|
|
|
life3 = new Decal(new Sprite("assets/life3.png")); |
|
|
|
|
life2 = new Decal(new Sprite("assets/life2.png")); |
|
|
|
@ -1694,22 +1799,28 @@ bool FaceBall::OnUserCreate() |
|
|
|
|
powerup_tex = new Decal(new Sprite("assets/powerup.png")); |
|
|
|
|
powerup2_tex = new Decal(new Sprite("assets/powerup2.png")); |
|
|
|
|
powerups_tex = new Decal(new Sprite("assets/powerups.png")); |
|
|
|
|
worldSkyBox_tex = new Decal(new Sprite("assets/worldSkyBox.png")); |
|
|
|
|
|
|
|
|
|
enemy_ShootMe = { "assets/enemies/ShootMe.obj", enemy_ShootMe_tex }; |
|
|
|
|
enemy_ShootMe2 = { "assets/enemies/ShootMe2.obj", enemy_ShootMe2_tex }; |
|
|
|
|
enemy_Sonar = { "assets/enemies/Sonar.obj", enemy_Sonar_tex }; |
|
|
|
|
enemy_IShoot = { "assets/enemies/IShoot.obj", enemy_IShoot_tex}; |
|
|
|
|
enemy_IShoot2 = { "assets/enemies/IShoot2.obj", enemy_IShoot2_tex}; |
|
|
|
|
bullet = { "assets/enemies/bullet.obj",bullet_tex }; |
|
|
|
|
powerup = { "assets/Powerup.obj",powerup_tex}; |
|
|
|
|
powerup2 = { "assets/Powerup2.obj",powerup2_tex }; |
|
|
|
|
mapExit = { "assets/Exit.obj",dot }; |
|
|
|
|
worldSkyBox = { "assets/worldSkyBox.obj",worldSkyBox_tex }; |
|
|
|
|
mapWalls.texture = wall_tex; |
|
|
|
|
mapFloor.texture = floor_tex; |
|
|
|
|
|
|
|
|
|
mapSpr=new Sprite(minimapGridSize.x*20,minimapGridSize.y*20); |
|
|
|
|
mapDecal=new Decal(mapSpr); |
|
|
|
|
|
|
|
|
|
InitializeEnemyData(); |
|
|
|
|
InitializePowerupColors(); |
|
|
|
|
|
|
|
|
|
LoadLevel(1); |
|
|
|
|
LoadLevel(level); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
@ -1812,20 +1923,23 @@ bool Bullet::Update(float fElapsedTime) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void FaceBall::HurtPlayer(EnemyID id,int damage,bool blinking) { |
|
|
|
|
if (shieldDuration >= 0) { |
|
|
|
|
damage = 0; |
|
|
|
|
} |
|
|
|
|
hp = std::max(0, hp - damage); |
|
|
|
|
if (hp <= 0) { |
|
|
|
|
respawnTimer = 3.0f; |
|
|
|
|
} |
|
|
|
|
lastHitBy = id; |
|
|
|
|
lastHitByBlinking = blinking; |
|
|
|
|
if (shieldDuration < 0) { |
|
|
|
|
screenCol = enemyData[lastHitBy].col; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
screenCol = WHITE; |
|
|
|
|
if (respawnTimer<=0.0f){ |
|
|
|
|
if (shieldDuration >= 0) { |
|
|
|
|
damage = 0; |
|
|
|
|
} |
|
|
|
|
hp = std::max(0, hp - damage); |
|
|
|
|
if (hp <= 0) { |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
respawnTimer = 3.0f; |
|
|
|
|
} |
|
|
|
|
lastHitBy = id; |
|
|
|
|
lastHitByBlinking = blinking; |
|
|
|
|
if (shieldDuration < 0) { |
|
|
|
|
screenCol = enemyData[lastHitBy].col; |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
screenCol = WHITE; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1948,6 +2062,7 @@ void FaceBall::RenderHud(float fElapsedTime) { |
|
|
|
|
hudShakeAmt = std::sinf(40 * hudShakeTime); |
|
|
|
|
hudAdjustment.x += hudShakeAmt * 2; |
|
|
|
|
hudAdjustment.y += hudShakeAmt * 4; |
|
|
|
|
hudOffset += hudShakeAmt * 2; |
|
|
|
|
} |
|
|
|
|
vf2d hudLoc = { hudAdjustment.x + (hp>0?hudOffset:0),hudAdjustment.y}; |
|
|
|
|
if (hp > 0) { |
|
|
|
@ -1969,7 +2084,12 @@ void FaceBall::RenderHud(float fElapsedTime) { |
|
|
|
|
for (int x = -1; x <= 1; x++) { |
|
|
|
|
for (int y = -1; y <= 1; y++) { |
|
|
|
|
if (x != 0 && y != 0) { |
|
|
|
|
DrawStringDecal(vf2d{ hudOffset + float(ScreenWidth() / 2 - GetTextSize(hudDisplayText).x / 2 * 4) + 32,float(ScreenHeight() - 128 - GetTextSize(hudDisplayText).y * 4) + 18 } + vf2d{ float(x),float(y) }, hudDisplayText, DARK_BLUE, { 4,4 }); |
|
|
|
|
if (lookingAtText != "") { |
|
|
|
|
DrawStringDecal(vf2d{ hudOffset + float(ScreenWidth() / 2 - GetTextSize(lookingAtText).x / 2 * 4) + 32,float(ScreenHeight() - 128 - GetTextSize(lookingAtText).y * 4) + 18 } + vf2d{ float(x),float(y) }, lookingAtText, DARK_BLUE, { 4,4 }); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
DrawStringDecal(vf2d{ hudOffset + float(ScreenWidth() / 2 - GetTextSize(hudDisplayText).x / 2 * 4) + 32,float(ScreenHeight() - 128 - GetTextSize(hudDisplayText).y * 4) + 18 } + vf2d{ float(x),float(y) }, hudDisplayText, DARK_BLUE, { 4,4 }); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -1981,7 +2101,12 @@ void FaceBall::RenderHud(float fElapsedTime) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
DrawStringPropDecal(vf2d{ hudOffset + (float)(ScreenWidth() / 2 - GetTextSizeProp(std::to_string(score)).x * 4 / 2) + 32,(float)(36 - GetTextSizeProp(std::to_string(score)).y * 4) + 18 } + hudAdjustment, std::to_string(score), { 192,96,96 }, { 4,4 }); |
|
|
|
|
DrawStringDecal(vf2d{ hudOffset + float(ScreenWidth() / 2 - GetTextSize(hudDisplayText).x / 2 * 4) + 32,float(ScreenHeight() - 128 - GetTextSize(hudDisplayText).y * 4) + 18 }, hudDisplayText, { 192,192,255 }, { 4,4 }); |
|
|
|
|
if (lookingAtText != "") { |
|
|
|
|
DrawStringDecal(vf2d{ hudOffset + float(ScreenWidth() / 2 - GetTextSize(lookingAtText).x / 2 * 4) + 32,float(ScreenHeight() - 128 - GetTextSize(lookingAtText).y * 4) + 18 }, lookingAtText, { 192,192,255 }, { 4,4 }); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
DrawStringDecal(vf2d{ hudOffset + float(ScreenWidth() / 2 - GetTextSize(hudDisplayText).x / 2 * 4) + 32,float(ScreenHeight() - 128 - GetTextSize(hudDisplayText).y * 4) + 18 }, hudDisplayText, { 192,192,255 }, { 4,4 }); |
|
|
|
|
} |
|
|
|
|
DrawStringDecal({float(ScreenWidth()-128),24},std::to_string(wave2Enemies.size())); |
|
|
|
|
SetDecalMode(DecalMode::ADDITIVE); |
|
|
|
|
DrawDecal({ float(ScreenWidth() / 2 - crosshair->sprite->width / 2),float(ScreenHeight() / 2 - crosshair->sprite->height / 2) }, crosshair, { 1,1 }, {255,255,255,128}); |
|
|
|
@ -1994,6 +2119,10 @@ void FaceBall::RenderHud(float fElapsedTime) { |
|
|
|
|
if (camoDuration > 0) { |
|
|
|
|
DrawPartialDecal({ hudOffset + float(ScreenWidth() / 10 - 16), float(ScreenHeight() / 4 + ScreenHeight() / 4 * 2 - 16 * 4) }, vf2d{ 32,32 }*4, powerups_tex, { 5 * 32,0 }, { 32,32 },camoDuration>7?WHITE:camoDuration>2?std::abs(std::sin(10*camoDuration))>0.65?WHITE:BLACK: std::abs(std::sin(30 * camoDuration)) > 0.75 ? WHITE : BLACK); |
|
|
|
|
} |
|
|
|
|
vf2d mapCenter = {float(ScreenWidth()-364),float(164)}; |
|
|
|
|
SetDrawTarget(nullptr); |
|
|
|
|
DrawDecal(vf2d{mapCenter.x+hudOffset/2,mapCenter.y}-vf2d{2.5f,2.5f},dot,{5,5},GREEN); |
|
|
|
|
DrawRotatedDecal({mapCenter.x+hudOffset/2,mapCenter.y},mapDecal,-fYaw-PI/2,vf2d{int(player.GetPos().x)+0.5f,int(player.GetPos().z)+0.5f}*minimapGridSize,{1,1}); |
|
|
|
|
SetDecalMode(DecalMode::NORMAL); |
|
|
|
|
} |
|
|
|
|
GradientFillRectDecal({ 0,0 }, vf2d{ (float)ScreenWidth()/2,(float)ScreenHeight()/2 }, { (uint8_t)screenCol.r,(uint8_t)screenCol.g,(uint8_t)screenCol.b,(uint8_t)(hudShakeTime>0.2f?120:hudShakeTime>0?64:0) }, { (uint8_t)screenCol.r,(uint8_t)screenCol.g,(uint8_t)screenCol.b,(uint8_t)(hudShakeTime>0.2f?120:hudShakeTime>0?64:0) }, { (uint8_t)screenCol.r,(uint8_t)screenCol.g,(uint8_t)screenCol.b,(uint8_t)(hudShakeTime > 0.2f ? 64 : 0) }, { (uint8_t)screenCol.r,(uint8_t)screenCol.g,(uint8_t)screenCol.b,(uint8_t)(hudShakeTime>0.2f?120:hudShakeTime>0?64:0) }); |
|
|
|
@ -2125,7 +2254,8 @@ void FaceBall::RunEnemyAI(Enemy& e,float fElapsedTime,int myIndex) { |
|
|
|
|
e.ShootBullet(myIndex); |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
case ISHOOT2: { |
|
|
|
|
case ISHOOT2: |
|
|
|
|
case ISHOOT2_SPEED:{ |
|
|
|
|
switch (e.GetPhase()) { |
|
|
|
|
case Phase::DEFAULT: { |
|
|
|
|
vf2d movementVec = { std::cosf(e.rot) * dat.movSpd * fElapsedTime,std::sinf(e.rot) * dat.movSpd * fElapsedTime }; |
|
|
|
@ -2162,12 +2292,22 @@ void FaceBall::RunEnemyAI(Enemy& e,float fElapsedTime,int myIndex) { |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
} |
|
|
|
|
if (e.roundedCoords!=vi2d{int(e.pos.x),int(e.pos.z)}){ |
|
|
|
|
e.roundedCoords=vi2d{int(e.pos.x),int(e.pos.z)}; |
|
|
|
|
if (hasMapUpgrade){ |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool FaceBall::PlayerHasMapUpgrade(){ |
|
|
|
|
return hasMapUpgrade; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool FaceBall::OnUserUpdate(float fElapsedTime) |
|
|
|
|
{ |
|
|
|
|
fElapsedTime = std::min(0.01667f, fElapsedTime); |
|
|
|
|
fElapsedTime = std::min(2/60.f, fElapsedTime); |
|
|
|
|
gameTimer += fElapsedTime; |
|
|
|
|
switch (mode) { |
|
|
|
|
case GAME: { |
|
|
|
@ -2191,6 +2331,7 @@ bool FaceBall::OnUserUpdate(float fElapsedTime) |
|
|
|
|
!CheckPlayerCollision({0,0,0},{e.pos.x,e.pos.z},e.radius*6)){ |
|
|
|
|
enemies.push_back(e); |
|
|
|
|
wave2Enemies.erase(wave2Enemies.begin()+i); |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
goto spawningDone; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -2202,6 +2343,7 @@ bool FaceBall::OnUserUpdate(float fElapsedTime) |
|
|
|
|
!CheckPlayerCollision({0,0,0},{e.pos.x,e.pos.z},e.radius*6)){ |
|
|
|
|
enemies.push_back(e); |
|
|
|
|
wave3Enemies.erase(wave3Enemies.begin()+i); |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
goto spawningDone; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -2217,6 +2359,7 @@ bool FaceBall::OnUserUpdate(float fElapsedTime) |
|
|
|
|
!CheckPlayerCollision({0,0,0},{e.pos.x,e.pos.z},e.radius*6)){ |
|
|
|
|
enemies.push_back(e); |
|
|
|
|
wave2Enemies.erase(wave2Enemies.begin()+i); |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -2231,14 +2374,21 @@ bool FaceBall::OnUserUpdate(float fElapsedTime) |
|
|
|
|
it++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (int i = 0; i < enemies.size(); i++) { |
|
|
|
|
Enemy& e = enemies[i]; |
|
|
|
|
e.Update(fElapsedTime); |
|
|
|
|
if (e.isLastHitTimerActive()) { |
|
|
|
|
e.reduceLastHitTimer(fElapsedTime); |
|
|
|
|
int counter = 0; |
|
|
|
|
for (std::vector<Enemy>::iterator it = enemies.begin(); it != enemies.end();) { |
|
|
|
|
Enemy& e = *it; |
|
|
|
|
if (!e.Update(fElapsedTime)) { |
|
|
|
|
it = enemies.erase(it); |
|
|
|
|
} |
|
|
|
|
if (stopDuration < 0) { |
|
|
|
|
RunEnemyAI(e, fElapsedTime, i); |
|
|
|
|
else { |
|
|
|
|
if (e.isLastHitTimerActive()) { |
|
|
|
|
e.reduceLastHitTimer(fElapsedTime); |
|
|
|
|
} |
|
|
|
|
if (stopDuration < 0) { |
|
|
|
|
RunEnemyAI(e, fElapsedTime, counter); |
|
|
|
|
} |
|
|
|
|
it++; |
|
|
|
|
counter++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (std::vector<Powerup>::iterator it = powerups.begin(); it != powerups.end();) { |
|
|
|
@ -2283,6 +2433,7 @@ bool FaceBall::OnUserUpdate(float fElapsedTime) |
|
|
|
|
}break; |
|
|
|
|
case PowerupType::MAP: { |
|
|
|
|
hasMapUpgrade = true; |
|
|
|
|
RegenerateMinimap(); |
|
|
|
|
}break; |
|
|
|
|
case PowerupType::COIN: { |
|
|
|
|
AddScore(1000); |
|
|
|
@ -2294,6 +2445,25 @@ bool FaceBall::OnUserUpdate(float fElapsedTime) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (hp > 0) { |
|
|
|
|
vf2d checkPos = {player.GetPos().x, player.GetPos().z}; |
|
|
|
|
lookingAtText = ""; |
|
|
|
|
while (true) { |
|
|
|
|
if (checkPos.x<0 || checkPos.y<0 || checkPos.x>MAP_SIZE.x || checkPos.y>MAP_SIZE.y) break; |
|
|
|
|
vf2d checkVec = { std::cosf(fYaw) * 0.1f,std::sinf(fYaw) * 0.1f }; |
|
|
|
|
if (CheckCollision({ checkVec.x,0,checkVec.y }, checkPos, 0.05f)) break; |
|
|
|
|
checkPos.x += checkVec.x; |
|
|
|
|
checkPos.y += checkVec.y; |
|
|
|
|
for (Enemy&e : enemies) { |
|
|
|
|
if (!e.isDead()) { |
|
|
|
|
float dist = std::sqrtf(std::powf(checkPos.x - e.pos.x, 2) + std::powf(checkPos.y - e.pos.z, 2)); |
|
|
|
|
if (dist <= e.radius*2) { |
|
|
|
|
lookingAtText = enemyData[e.GetID()].name; |
|
|
|
|
goto afterPositionCheck; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
afterPositionCheck: |
|
|
|
|
HandleKeys(fElapsedTime); |
|
|
|
|
RenderWorld(); |
|
|
|
|
} |
|
|
|
@ -2408,7 +2578,7 @@ int FaceBall::EnemiesAlive(){ |
|
|
|
|
int main() |
|
|
|
|
{ |
|
|
|
|
FaceBall demo; |
|
|
|
|
if (demo.Construct(1280, 720, 2, 2)) |
|
|
|
|
if (demo.Construct(1280, 720, 2, 2, false, true)) |
|
|
|
|
demo.Start(); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|