Added Fall-o-meter HUD elements, added crash landing mechanics, and fuel.

main
sigonasr2 3 months ago
parent 5b188afc85
commit 002b00f018
  1. BIN
      assets/fuelbar_outline.png
  2. BIN
      assets/hamster.png
  3. BIN
      assets/hamster_jet.png
  4. 194
      src/Hamster.cpp
  5. 11
      src/Hamster.h
  6. 2
      src/HamsterGame.cpp
  7. 1
      src/HamsterGame.h
  8. 23
      src/HamsterJet.cpp
  9. 2
      src/HamsterJet.h
  10. 4
      src/Powerup.cpp
  11. 4
      src/Powerup.h
  12. 78
      src/Terrain.cpp
  13. 8
      src/Terrain.h

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 17 KiB

@ -92,61 +92,7 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
h.imgScale=1.f; h.imgScale=1.f;
h.drownTimer=0.f; h.drownTimer=0.f;
if(!h.lastSafeLocation.has_value()){ if(!h.lastSafeLocation.has_value()){
#pragma region Safe Terrain Outline Search Algorithm h.lastSafeLocation=h.GetNearestSafeLocation();
{
using TilePos=vi2d;
using TileDistance=int;
const vi2d playerTile{h.GetPos()/16};
geom2d::rect<int>searchRect{{-1,-1},{3,3}};
std::optional<std::pair<TilePos,TileDistance>>closestTile;
const auto DetermineAndUpdateClosestTile=[&h,&playerTile,&closestTile](const vi2d&tile){
if(!h.IsLethalTerrain(tile*16)){
std::pair<TilePos,TileDistance>closest{closestTile.value_or(std::pair<TilePos,TileDistance>{{},std::numeric_limits<int>::max()})};
int tileDist{abs(playerTile.x-tile.x)+abs(playerTile.y-tile.y)};
if(tileDist<=closest.second)closestTile.emplace(std::pair<TilePos,TileDistance>{tile,tileDist});
}
};
while(!closestTile.has_value()){
#pragma region Top Outline Check
{
for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){
const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.top().end.y}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
#pragma region Bottom Outline Check
{
for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){
const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.bottom().end.y}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
#pragma region Right Outline Check
{
for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){
const vi2d checkTile{playerTile+vi2d{searchRect.right().end.x,offsetY}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
#pragma region Left Outline Check
{
for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){
const vi2d checkTile{playerTile+vi2d{searchRect.left().end.x,offsetY}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
searchRect.pos-=1;
searchRect.size+=2;
}
h.lastSafeLocation=closestTile.value().first*16+8;
}
#pragma endregion
} }
h.SetPos(h.lastSafeLocation.value()); h.SetPos(h.lastSafeLocation.value());
h.state=NORMAL; h.state=NORMAL;
@ -162,6 +108,13 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
h.state=WAIT; h.state=WAIT;
} }
}break; }break;
case KNOCKOUT:{
h.knockoutTimer-=fElapsedTime;
if(h.knockoutTimer<=0.f){
h.state=NORMAL;
h.animations.ChangeState(h.internalAnimState,HamsterGame::DEFAULT);
}
}break;
} }
if(h.hamsterJet.has_value())h.hamsterJet.value().Update(fElapsedTime); if(h.hamsterJet.has_value())h.hamsterJet.value().Update(fElapsedTime);
if(h.state!=FLYING){ if(h.state!=FLYING){
@ -182,6 +135,12 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
} }
h.TurnTowardsTargetDirection(); h.TurnTowardsTargetDirection();
h.MoveHamster(); h.MoveHamster();
if(h.IsPlayerControlled){
h.hamsterJetDisplay.Update(fElapsedTime);
h.hamsterJetLightsDisplay.Update(fElapsedTime);
h.readyFlashTimer+=fElapsedTime;
h.jetFuelDisplayAmt+=(h.jetFuel-h.jetFuelDisplayAmt)*4.f*fElapsedTime;
}
} }
} }
@ -194,6 +153,8 @@ void Hamster::LoadHamsters(const vf2d startingLoc){
for(int i:std::ranges::iota_view(0U,NPC_HAMSTER_COUNT)){ for(int i:std::ranges::iota_view(0U,NPC_HAMSTER_COUNT)){
HAMSTER_LIST.emplace_back(startingLoc,NPC_HAMSTER_IMAGES.at(util::random()%NPC_HAMSTER_IMAGES.size()),NPC); HAMSTER_LIST.emplace_back(startingLoc,NPC_HAMSTER_IMAGES.at(util::random()%NPC_HAMSTER_IMAGES.size()),NPC);
} }
playerHamster.value()->hamsterJetDisplay.Initialize("hamster_jet.png",{78,223,208},{79,81,128});
playerHamster.value()->hamsterJetLightsDisplay.Initialize("hamster_jet.png",{245,233,130},{245,233,130});
} }
void Hamster::DrawHamsters(TransformedView&tv){ void Hamster::DrawHamsters(TransformedView&tv){
@ -216,10 +177,44 @@ void Hamster::DrawHamsters(TransformedView&tv){
} }
void Hamster::DrawOverlay(){ void Hamster::DrawOverlay(){
if(GetPlayer().hamsterJet.has_value()){ if(GetPlayer().hamsterJet.has_value())GetPlayer().hamsterJet.value().DrawOverlay();
GetPlayer().hamsterJet.value().DrawOverlay();
HamsterGame::Game().DrawDecal(vf2d{96.f,0.f}+HamsterGame::SCREEN_FRAME.size,HamsterGame::GetGFX("fuelmeter.png").Decal()); const vf2d jetDisplayOffset{HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f}};
Pixel jetDisplayCol{VERY_DARK_GREY};
if(!GetPlayer().hamsterJet.has_value()){
if(GetPlayer().HasPowerup(Powerup::JET))jetDisplayCol=WHITE;
const Animate2D::FrameSequence&lightAnim{HamsterGame::Game().GetAnimation("hamster_jet.png",HamsterGame::AnimationState::JET_LIGHTS)};
const Animate2D::Frame&lightFrame{lightAnim.GetFrame(HamsterGame::Game().GetRuntime())};
HamsterGame::Game().DrawPartialRotatedDecal(jetDisplayOffset+vf2d{48.f,80.f},GetPlayer().hamsterJetDisplay.Decal(),0.f,{24.f,24.f},{0.f,0.f},{48.f,48.f},{2.f,2.f},jetDisplayCol);
HamsterGame::Game().DrawPartialRotatedDecal(jetDisplayOffset+vf2d{48.f,80.f},GetPlayer().hamsterJetLightsDisplay.Decal(),0.f,{24.f,24.f},lightFrame.GetSourceRect().pos,lightFrame.GetSourceRect().size,{2.f,2.f},jetDisplayCol);
} }
if(GetPlayer().HasPowerup(Powerup::JET)&&!GetPlayer().hamsterJet.has_value()){
const std::string readyText{"READY!"};
const vi2d textSize{HamsterGame::Game().GetTextSize(readyText)};
for(int y:std::ranges::iota_view(-1,2)){
for(int x:std::ranges::iota_view(-1,2)){
if(x==0&&y==0)continue;
HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,116.f}+vi2d{x,y},readyText,0.f,textSize/2,fmod(GetPlayer().readyFlashTimer,1.5f)<=0.75f?DARK_RED:BLACK);
}
}
HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,116.f},readyText,0.f,textSize/2,GREEN);
HamsterGame::Game().DrawDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f},HamsterGame::GetGFX("fuelmeter.png").Decal());
const std::string launchText{"(SPACE)x2\nto Launch!"};
const vi2d launchTextSize{HamsterGame::Game().GetTextSize(launchText)};
for(int y:std::ranges::iota_view(-1,2)){
for(int x:std::ranges::iota_view(-1,2)){
if(x==0&&y==0)continue;
HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,224.f}+vi2d{x,y},launchText,0.f,launchTextSize/2,BLACK);
}
}
HamsterGame::Game().DrawRotatedStringDecal(jetDisplayOffset+vf2d{48.f,224.f},launchText,0.f,launchTextSize/2,WHITE);
}else{
HamsterGame::Game().DrawPartialDecal(HamsterGame::SCREEN_FRAME.pos+vf2d{HamsterGame::SCREEN_FRAME.size.x,0.f},HamsterGame::GetGFX("fuelmeter.png").Decal(),{0,0},{96,200});
}
const float jetFuelBarHeight{float(HamsterGame::GetGFX("fuelbar.png").Sprite()->height)};
HamsterGame::Game().DrawPartialDecal(jetDisplayOffset+vf2d{24.f,139.f}+vf2d{0.f,jetFuelBarHeight*(1.f-GetPlayer().jetFuelDisplayAmt)},HamsterGame::GetGFX("fuelbar.png").Decal(),{0.f,jetFuelBarHeight*(1.f-GetPlayer().jetFuelDisplayAmt)},{float(HamsterGame::GetGFX("fuelbar.png").Sprite()->width),jetFuelBarHeight*(GetPlayer().jetFuelDisplayAmt)});
if(GetPlayer().HasPowerup(Powerup::JET))HamsterGame::Game().DrawDecal(jetDisplayOffset+vf2d{22.f,137.f},HamsterGame::GetGFX("fuelbar_outline.png").Decal(),{1.f,1.f},GetPlayer().jetFuel<=0.2f?(fmod(GetPlayer().readyFlashTimer,1.f)<=0.5f?RED:BLACK):BLACK);
} }
const Animate2D::Frame&Hamster::GetCurrentAnimation()const{ const Animate2D::Frame&Hamster::GetCurrentAnimation()const{
@ -265,7 +260,11 @@ void Hamster::HandlePlayerControls(){
} }
lastTappedSpace=0.f; lastTappedSpace=0.f;
} }
if(HamsterGame::Game().GetKey(P).bPressed)ObtainPowerup(Powerup::JET); if(HamsterGame::Game().GetKey(P).bPressed){
ObtainPowerup(Powerup::JET);
Powerup tempJetPowerup{{},Powerup::JET};
tempJetPowerup.OnPowerupObtain(*this);
}
} }
void Hamster::TurnTowardsTargetDirection(){ void Hamster::TurnTowardsTargetDirection(){
@ -276,6 +275,9 @@ void Hamster::MoveHamster(){
SetPos(GetPos()+vel*HamsterGame::Game().GetElapsedTime()); SetPos(GetPos()+vel*HamsterGame::Game().GetElapsedTime());
distanceTravelled+=vel.mag()*HamsterGame::Game().GetElapsedTime(); distanceTravelled+=vel.mag()*HamsterGame::Game().GetElapsedTime();
if(state==FLYING){
jetFuel=std::max(0.f,jetFuel-vel.mag()*HamsterGame::Game().GetElapsedTime()/100000.f);
}
#pragma region Handle Friction #pragma region Handle Friction
if(frictionEnabled){ if(frictionEnabled){
@ -314,9 +316,11 @@ void Hamster::HandleCollision(){
} }
} }
for(Powerup&powerup:Powerup::GetPowerups()){ for(Powerup&powerup:Powerup::GetPowerups()){
if(z<=0.1f&&!HasPowerup(powerup.GetType())&&geom2d::overlaps(geom2d::circle<float>(GetPos(),collisionRadius),geom2d::circle<float>(powerup.GetPos(),20.f))){ if(z<=0.1f&&
(!HasPowerup(powerup.GetType())||HasPowerup(Powerup::JET)&&powerup.GetType()==Powerup::JET&&jetFuel!=1.f)
&&geom2d::overlaps(geom2d::circle<float>(GetPos(),collisionRadius),geom2d::circle<float>(powerup.GetPos(),20.f))){
ObtainPowerup(powerup.GetType()); ObtainPowerup(powerup.GetType());
powerup.OnPowerupObtain(); powerup.OnPowerupObtain(*this);
} }
} }
} }
@ -450,4 +454,72 @@ void Hamster::OnUserDestroy(){
void Hamster::SetDrawingOffsetY(const float offsetY){ void Hamster::SetDrawingOffsetY(const float offsetY){
drawingOffsetY=offsetY; drawingOffsetY=offsetY;
}
const vf2d Hamster::GetNearestSafeLocation()const{
using TilePos=vi2d;
using TileDistance=int;
const vi2d playerTile{GetPos()/16};
geom2d::rect<int>searchRect{{-1,-1},{3,3}};
std::optional<std::pair<TilePos,TileDistance>>closestTile;
const auto DetermineAndUpdateClosestTile=[this,&playerTile,&closestTile](const vi2d&tile){
if(!IsLethalTerrain(tile*16)&&!IsSolidTerrain(tile*16)){
std::pair<TilePos,TileDistance>closest{closestTile.value_or(std::pair<TilePos,TileDistance>{{},std::numeric_limits<int>::max()})};
int tileDist{abs(playerTile.x-tile.x)+abs(playerTile.y-tile.y)};
if(tileDist<=closest.second)closestTile.emplace(std::pair<TilePos,TileDistance>{tile,tileDist});
}
};
while(!closestTile.has_value()){
#pragma region Top Outline Check
{
for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){
const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.top().end.y}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
#pragma region Bottom Outline Check
{
for(int offsetX:std::ranges::iota_view(searchRect.pos.x,searchRect.size.x)){
const vi2d checkTile{playerTile+vi2d{offsetX,searchRect.bottom().end.y}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
#pragma region Right Outline Check
{
for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){
const vi2d checkTile{playerTile+vi2d{searchRect.right().end.x,offsetY}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
#pragma region Left Outline Check
{
for(int offsetY:std::ranges::iota_view(searchRect.pos.y+1,searchRect.size.y-2+1)){
const vi2d checkTile{playerTile+vi2d{searchRect.left().end.x,offsetY}};
DetermineAndUpdateClosestTile(checkTile);
}
}
#pragma endregion
searchRect.pos-=1;
searchRect.size+=2;
}
return closestTile.value().first*16+8;
}
const bool Hamster::IsSolidTerrain(const vf2d pos)const{
return HamsterGame::Game().IsTerrainSolid(pos);
}
void Hamster::SetJetFuel(const float amt){
jetFuel=amt;
}
void Hamster::Knockout(){
state=KNOCKOUT;
knockoutTimer=4.f;
animations.ChangeState(internalAnimState,HamsterGame::KNOCKOUT);
} }

@ -59,6 +59,7 @@ class Hamster{
FLYING, FLYING,
WAIT, WAIT,
BURNING, BURNING,
KNOCKOUT,
}; };
static std::vector<Hamster>HAMSTER_LIST; static std::vector<Hamster>HAMSTER_LIST;
@ -103,6 +104,12 @@ class Hamster{
std::optional<HamsterJet>hamsterJet; std::optional<HamsterJet>hamsterJet;
float lastTappedSpace{0.f}; float lastTappedSpace{0.f};
float drawingOffsetY{0.f}; float drawingOffsetY{0.f};
SpecialRenderable hamsterJetDisplay;
SpecialRenderable hamsterJetLightsDisplay;
float readyFlashTimer{};
float jetFuel{0.f};
float jetFuelDisplayAmt{0.f};
float knockoutTimer{0.f};
public: public:
Hamster(const vf2d spawnPos,const std::string_view img,const PlayerControlled IsPlayerControlled=NPC); Hamster(const vf2d spawnPos,const std::string_view img,const PlayerControlled IsPlayerControlled=NPC);
static const Hamster&GetPlayer(); static const Hamster&GetPlayer();
@ -129,6 +136,7 @@ public:
const bool HasPowerup(const Powerup::PowerupType powerup)const; const bool HasPowerup(const Powerup::PowerupType powerup)const;
void RemoveAllPowerups(); void RemoveAllPowerups();
const bool IsLethalTerrain(const vf2d pos)const; const bool IsLethalTerrain(const vf2d pos)const;
const bool IsSolidTerrain(const vf2d pos)const;
const bool IsDrowning()const; const bool IsDrowning()const;
const bool IsBurning()const; const bool IsBurning()const;
const float GetDrownRatio()const; const float GetDrownRatio()const;
@ -137,4 +145,7 @@ public:
void SetZ(const float z); void SetZ(const float z);
static void OnUserDestroy(); static void OnUserDestroy();
void SetDrawingOffsetY(const float offsetY); void SetDrawingOffsetY(const float offsetY);
const vf2d GetNearestSafeLocation()const;
void SetJetFuel(const float amt);
void Knockout();
}; };

@ -52,6 +52,7 @@ void HamsterGame::LoadGraphics(){
_LoadImage("fallometer_outline.png"); _LoadImage("fallometer_outline.png");
_LoadImage("fuelmeter.png"); _LoadImage("fuelmeter.png");
_LoadImage("fuelbar.png"); _LoadImage("fuelbar.png");
_LoadImage("fuelbar_outline.png");
UpdateMatrixTexture(); UpdateMatrixTexture();
} }
@ -75,6 +76,7 @@ void HamsterGame::LoadAnimations(){
LoadAnimation(DEFAULT,"hamster.png",{{0,32},{32,32}},0.3f); LoadAnimation(DEFAULT,"hamster.png",{{0,32},{32,32}},0.3f);
LoadAnimation(WHEEL_TOP,"hamster.png",{{0,96},{32,96}},0.1f); LoadAnimation(WHEEL_TOP,"hamster.png",{{0,96},{32,96}},0.1f);
LoadAnimation(WHEEL_BOTTOM,"hamster.png",{{64,96},{96,96}},0.1f); LoadAnimation(WHEEL_BOTTOM,"hamster.png",{{64,96},{96,96}},0.1f);
LoadAnimation(KNOCKOUT,"hamster.png",{{64,32},{96,32}},0.2f);
Animate2D::FrameSequence&waterAnimFrames{(*ANIMATED_TILE_IDS.insert({1384,Animate2D::FrameSequence{0.2f}}).first).second}; Animate2D::FrameSequence&waterAnimFrames{(*ANIMATED_TILE_IDS.insert({1384,Animate2D::FrameSequence{0.2f}}).first).second};
for(vf2d&sourcePos:std::vector<vf2d>{{192+16*0,784},{192+16*1,784},{192+16*2,784},{192+16*3,784},{192+16*4,784},{192+16*5,784},{192+16*6,784},{192+16*7,784}}){ for(vf2d&sourcePos:std::vector<vf2d>{{192+16*0,784},{192+16*1,784},{192+16*2,784},{192+16*3,784},{192+16*4,784},{192+16*5,784},{192+16*6,784},{192+16*7,784}}){
waterAnimFrames.AddFrame(Animate2D::Frame{&GetGFX("gametiles.png"),{sourcePos,{16,16}}}); waterAnimFrames.AddFrame(Animate2D::Frame{&GetGFX("gametiles.png"),{sourcePos,{16,16}}});

@ -64,6 +64,7 @@ public:
WHEEL_BOTTOM, WHEEL_BOTTOM,
JET_LIGHTS, JET_LIGHTS,
JET_FLAMES, JET_FLAMES,
KNOCKOUT,
}; };
HamsterGame(); HamsterGame();

@ -80,19 +80,22 @@ void HamsterJet::Update(const float fElapsedTime){
hamster.SetPos(pos); hamster.SetPos(pos);
hamster.SetZ(z+0.03f); hamster.SetZ(z+0.03f);
if(timer<=0.f){ if(timer<=0.f){
state=PLAYER_CONTROL; state=HAMSTER_CONTROL;
HamsterGame::Game().SetZoom(0.6f); HamsterGame::Game().SetZoom(0.6f);
easeInTimer=0.6f; easeInTimer=0.6f;
} }
}break; }break;
case PLAYER_CONTROL:{ case HAMSTER_CONTROL:{
jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF;
HandleJetControls(); HandleJetControls();
pos=hamster.GetPos(); pos=hamster.GetPos();
}break; }break;
case LANDING:{ case LANDING:{
jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF; jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF;
HandleJetControls(); if(hamster.IsPlayerControlled)HandleJetControls();
else{
//TODO: AI controls here!
}
pos=hamster.GetPos(); pos=hamster.GetPos();
hamster.SetZ(hamster.GetZ()-fallSpd*fElapsedTime); hamster.SetZ(hamster.GetZ()-fallSpd*fElapsedTime);
z=hamster.GetZ(); z=hamster.GetZ();
@ -104,6 +107,14 @@ void HamsterJet::Update(const float fElapsedTime){
timer=3.f; timer=3.f;
originalPos=hamster.GetPos(); originalPos=hamster.GetPos();
targetPos={hamster.GetPos().x+128.f,hamster.GetPos().y+32.f}; targetPos={hamster.GetPos().x+128.f,hamster.GetPos().y+32.f};
Terrain::CrashSpeed crashSpd{Terrain::LIGHT};
if(fallSpd>4.f)crashSpd=Terrain::MAX;
else if(fallSpd>2.f)crashSpd=Terrain::MEDIUM;
std::pair<Terrain::FuelDamage,Terrain::KnockoutOccurs>landingResult{Terrain::GetFuelDamageTakenAndKnockoutEffect(hamster.GetTerrainStandingOn(),crashSpd)};
hamster.jetFuel=std::max(0.f,hamster.jetFuel-landingResult.first);
if(landingResult.second)hamster.Knockout();
if(hamster.IsTerrainStandingOnSolid())hamster.SetPos(hamster.GetNearestSafeLocation());
if(hamster.jetFuel<=0.f)hamster.powerups.erase(Powerup::JET);
} }
}break; }break;
case COMPLETE_LANDING:{ case COMPLETE_LANDING:{
@ -121,11 +132,11 @@ void HamsterJet::Update(const float fElapsedTime){
void HamsterJet::Draw(){ void HamsterJet::Draw(){
float drawingOffsetY{0.f}; float drawingOffsetY{0.f};
hamster.SetDrawingOffsetY(0.f); hamster.SetDrawingOffsetY(0.f);
if((state==PLAYER_CONTROL||state==LANDING)&&z>2.f){ if((state==HAMSTER_CONTROL||state==LANDING)&&z>2.f){
HamsterGame::Game().SetZ(z/2.f); HamsterGame::Game().SetZ(z/2.f);
HamsterGame::Game().tv.DrawRotatedDecal(pos,HamsterGame::GetGFX("aimingTarget.png").Decal(),0.f,HamsterGame::GetGFX("aimingTarget.png").Sprite()->Size()/2); HamsterGame::Game().tv.DrawRotatedDecal(pos,HamsterGame::GetGFX("aimingTarget.png").Decal(),0.f,HamsterGame::GetGFX("aimingTarget.png").Sprite()->Size()/2);
} }
if(state==PLAYER_CONTROL){ if(state==HAMSTER_CONTROL){
drawingOffsetY=util::lerp(48.f,0.f,easeInTimer/0.6f); drawingOffsetY=util::lerp(48.f,0.f,easeInTimer/0.6f);
hamster.SetDrawingOffsetY(util::lerp(48.f,0.f,easeInTimer/0.6f)); hamster.SetDrawingOffsetY(util::lerp(48.f,0.f,easeInTimer/0.6f));
} }
@ -168,7 +179,7 @@ void HamsterJet::HandleJetControls(){
jetState[BOTTOM_RIGHT]=ON; jetState[BOTTOM_RIGHT]=ON;
jetState[TOP_RIGHT]=ON; jetState[TOP_RIGHT]=ON;
} }
if(aimingDir!=vf2d{}){ if(aimingDir!=vf2d{}&&hamster.jetFuel>0.f){
hamster.targetRot=aimingDir.norm().polar().y; hamster.targetRot=aimingDir.norm().polar().y;
const vf2d currentVel{hamster.vel}; const vf2d currentVel{hamster.vel};
hamster.vel+=vf2d{currentVel.polar().x+(hamster.GetMaxSpeed()*HamsterGame::Game().GetElapsedTime())/hamster.GetTimeToMaxSpeed(),hamster.rot}.cart(); hamster.vel+=vf2d{currentVel.polar().x+(hamster.GetMaxSpeed()*HamsterGame::Game().GetElapsedTime())/hamster.GetTimeToMaxSpeed(),hamster.rot}.cart();

@ -47,7 +47,7 @@ public:
enum State{ enum State{
SWOOP_DOWN, SWOOP_DOWN,
RISE_UP, RISE_UP,
PLAYER_CONTROL, HAMSTER_CONTROL,
LANDING, LANDING,
COMPLETE_LANDING, COMPLETE_LANDING,
}; };

@ -38,6 +38,7 @@ All rights reserved.
#include "HamsterGame.h" #include "HamsterGame.h"
#include "Powerup.h" #include "Powerup.h"
#include "Hamster.h"
std::vector<Powerup>Powerup::powerupList; std::vector<Powerup>Powerup::powerupList;
std::unordered_map<int,std::pair<Powerup::PowerupType,Powerup::TileType>>Powerup::powerupIds; std::unordered_map<int,std::pair<Powerup::PowerupType,Powerup::TileType>>Powerup::powerupIds;
@ -112,6 +113,7 @@ const geom2d::rect<float>Powerup::GetPowerupSubimageRect(const PowerupType power
return {POWERUP_TILESET_STARTING_POS+vf2d{int(powerupType)*32.f,0.f},{32,32}}; return {POWERUP_TILESET_STARTING_POS+vf2d{int(powerupType)*32.f,0.f},{32,32}};
} }
void Powerup::OnPowerupObtain(){ void Powerup::OnPowerupObtain(Hamster&pickupHamster){
spinSpd=0.3f; spinSpd=0.3f;
if(type==JET)pickupHamster.SetJetFuel(1.f);
} }

@ -41,6 +41,8 @@ All rights reserved.
#include "olcUTIL_Geometry2D.h" #include "olcUTIL_Geometry2D.h"
#include "olcPGEX_TransformedView.h" #include "olcPGEX_TransformedView.h"
class Hamster;
class Powerup{ class Powerup{
public: public:
enum PowerupType{ enum PowerupType{
@ -79,5 +81,5 @@ public:
static void UpdatePowerups(const float fElapsedTime); static void UpdatePowerups(const float fElapsedTime);
static void DrawPowerups(TransformedView&tv); static void DrawPowerups(TransformedView&tv);
static const geom2d::rect<float>GetPowerupSubimageRect(const PowerupType powerupType); static const geom2d::rect<float>GetPowerupSubimageRect(const PowerupType powerupType);
void OnPowerupObtain(); void OnPowerupObtain(Hamster&pickupHamster);
}; };

@ -73,4 +73,82 @@ const std::string Terrain::TerrainToString(const TerrainType type){
return "Void"; return "Void";
} }
} }
}
const std::pair<Terrain::FuelDamage,Terrain::KnockoutOccurs>Terrain::GetFuelDamageTakenAndKnockoutEffect(const TerrainType type,const CrashSpeed crashSpeed){
const auto GetHardSurfaceCrashResult=[&crashSpeed](){
switch(crashSpeed){
case MAX:{
return std::pair<FuelDamage,KnockoutOccurs>{1.f,true};
}break;
case MEDIUM:{
return std::pair<FuelDamage,KnockoutOccurs>{0.8f,false};
}break;
case LIGHT:{
return std::pair<FuelDamage,KnockoutOccurs>{0.5f,false};
}break;
}
};
const auto GetMediumSurfaceCrashResult=[&crashSpeed](){
switch(crashSpeed){
case MAX:{
return std::pair<FuelDamage,KnockoutOccurs>{0.8f,true};
}break;
case MEDIUM:{
return std::pair<FuelDamage,KnockoutOccurs>{0.5f,false};
}break;
case LIGHT:{
return std::pair<FuelDamage,KnockoutOccurs>{0.25f,false};
}break;
}
};
const auto GetSoftSurfaceCrashResult=[&crashSpeed](){
switch(crashSpeed){
case MAX:{
return std::pair<FuelDamage,KnockoutOccurs>{0.5f,false};
}break;
case MEDIUM:{
return std::pair<FuelDamage,KnockoutOccurs>{0.25f,false};
}break;
case LIGHT:{
return std::pair<FuelDamage,KnockoutOccurs>{0.25f,false};
}break;
}
};
switch(type){
case ROCK:{
return GetHardSurfaceCrashResult();
}break;
case GRASS:{
return GetMediumSurfaceCrashResult();
}break;
case SAND:{
return GetSoftSurfaceCrashResult();
}break;
case SWAMP:{
return GetSoftSurfaceCrashResult();
}break;
case LAVA:{
return GetSoftSurfaceCrashResult();
}break;
case SHORE:{
return GetMediumSurfaceCrashResult();
}break;
case OCEAN:{
return GetMediumSurfaceCrashResult();
}break;
case FOREST:{
return GetMediumSurfaceCrashResult();
}break;
case TUNNEL:{
return GetHardSurfaceCrashResult();
}break;
case ICE:{
return GetHardSurfaceCrashResult();
}break;
default:{
return GetMediumSurfaceCrashResult();
}
}
} }

@ -57,5 +57,13 @@ namespace Terrain{
TUNNEL, TUNNEL,
ICE, ICE,
}; };
enum CrashSpeed{
MAX,
MEDIUM,
LIGHT,
};
using FuelDamage=float;
using KnockoutOccurs=bool;
const std::string TerrainToString(const TerrainType type); const std::string TerrainToString(const TerrainType type);
const std::pair<FuelDamage,KnockoutOccurs>GetFuelDamageTakenAndKnockoutEffect(const TerrainType type,const CrashSpeed crashSpeed);
} }
Loading…
Cancel
Save