mirror of
https://github.com/sigonasr2/hamster.git
synced 2025-04-17 22:29:40 -05:00
Added Fall-o-meter HUD elements, added crash landing mechanics, and fuel.
This commit is contained in:
parent
5b188afc85
commit
002b00f018
BIN
assets/fuelbar_outline.png
Normal file
BIN
assets/fuelbar_outline.png
Normal file
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 |
194
src/Hamster.cpp
194
src/Hamster.cpp
@ -92,61 +92,7 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
|
||||
h.imgScale=1.f;
|
||||
h.drownTimer=0.f;
|
||||
if(!h.lastSafeLocation.has_value()){
|
||||
#pragma region Safe Terrain Outline Search Algorithm
|
||||
{
|
||||
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.lastSafeLocation=h.GetNearestSafeLocation();
|
||||
}
|
||||
h.SetPos(h.lastSafeLocation.value());
|
||||
h.state=NORMAL;
|
||||
@ -162,6 +108,13 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
|
||||
h.state=WAIT;
|
||||
}
|
||||
}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.state!=FLYING){
|
||||
@ -182,6 +135,12 @@ void Hamster::UpdateHamsters(const float fElapsedTime){
|
||||
}
|
||||
h.TurnTowardsTargetDirection();
|
||||
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)){
|
||||
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){
|
||||
@ -216,10 +177,44 @@ void Hamster::DrawHamsters(TransformedView&tv){
|
||||
}
|
||||
|
||||
void Hamster::DrawOverlay(){
|
||||
if(GetPlayer().hamsterJet.has_value()){
|
||||
GetPlayer().hamsterJet.value().DrawOverlay();
|
||||
HamsterGame::Game().DrawDecal(vf2d{96.f,0.f}+HamsterGame::SCREEN_FRAME.size,HamsterGame::GetGFX("fuelmeter.png").Decal());
|
||||
if(GetPlayer().hamsterJet.has_value())GetPlayer().hamsterJet.value().DrawOverlay();
|
||||
|
||||
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{
|
||||
@ -265,7 +260,11 @@ void Hamster::HandlePlayerControls(){
|
||||
}
|
||||
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(){
|
||||
@ -276,6 +275,9 @@ void Hamster::MoveHamster(){
|
||||
SetPos(GetPos()+vel*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
|
||||
if(frictionEnabled){
|
||||
@ -314,9 +316,11 @@ void Hamster::HandleCollision(){
|
||||
}
|
||||
}
|
||||
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());
|
||||
powerup.OnPowerupObtain();
|
||||
powerup.OnPowerupObtain(*this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -451,3 +455,71 @@ void Hamster::OnUserDestroy(){
|
||||
void Hamster::SetDrawingOffsetY(const float 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,
|
||||
WAIT,
|
||||
BURNING,
|
||||
KNOCKOUT,
|
||||
};
|
||||
|
||||
static std::vector<Hamster>HAMSTER_LIST;
|
||||
@ -103,6 +104,12 @@ class Hamster{
|
||||
std::optional<HamsterJet>hamsterJet;
|
||||
float lastTappedSpace{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:
|
||||
Hamster(const vf2d spawnPos,const std::string_view img,const PlayerControlled IsPlayerControlled=NPC);
|
||||
static const Hamster&GetPlayer();
|
||||
@ -129,6 +136,7 @@ public:
|
||||
const bool HasPowerup(const Powerup::PowerupType powerup)const;
|
||||
void RemoveAllPowerups();
|
||||
const bool IsLethalTerrain(const vf2d pos)const;
|
||||
const bool IsSolidTerrain(const vf2d pos)const;
|
||||
const bool IsDrowning()const;
|
||||
const bool IsBurning()const;
|
||||
const float GetDrownRatio()const;
|
||||
@ -137,4 +145,7 @@ public:
|
||||
void SetZ(const float z);
|
||||
static void OnUserDestroy();
|
||||
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("fuelmeter.png");
|
||||
_LoadImage("fuelbar.png");
|
||||
_LoadImage("fuelbar_outline.png");
|
||||
UpdateMatrixTexture();
|
||||
}
|
||||
|
||||
@ -75,6 +76,7 @@ void HamsterGame::LoadAnimations(){
|
||||
LoadAnimation(DEFAULT,"hamster.png",{{0,32},{32,32}},0.3f);
|
||||
LoadAnimation(WHEEL_TOP,"hamster.png",{{0,96},{32,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};
|
||||
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}}});
|
||||
|
@ -64,6 +64,7 @@ public:
|
||||
WHEEL_BOTTOM,
|
||||
JET_LIGHTS,
|
||||
JET_FLAMES,
|
||||
KNOCKOUT,
|
||||
};
|
||||
|
||||
HamsterGame();
|
||||
|
@ -80,19 +80,22 @@ void HamsterJet::Update(const float fElapsedTime){
|
||||
hamster.SetPos(pos);
|
||||
hamster.SetZ(z+0.03f);
|
||||
if(timer<=0.f){
|
||||
state=PLAYER_CONTROL;
|
||||
state=HAMSTER_CONTROL;
|
||||
HamsterGame::Game().SetZoom(0.6f);
|
||||
easeInTimer=0.6f;
|
||||
}
|
||||
}break;
|
||||
case PLAYER_CONTROL:{
|
||||
case HAMSTER_CONTROL:{
|
||||
jetState[TOP_LEFT]=jetState[BOTTOM_LEFT]=jetState[BOTTOM_RIGHT]=jetState[TOP_RIGHT]=OFF;
|
||||
HandleJetControls();
|
||||
pos=hamster.GetPos();
|
||||
}break;
|
||||
case LANDING:{
|
||||
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();
|
||||
hamster.SetZ(hamster.GetZ()-fallSpd*fElapsedTime);
|
||||
z=hamster.GetZ();
|
||||
@ -104,6 +107,14 @@ void HamsterJet::Update(const float fElapsedTime){
|
||||
timer=3.f;
|
||||
originalPos=hamster.GetPos();
|
||||
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;
|
||||
case COMPLETE_LANDING:{
|
||||
@ -121,11 +132,11 @@ void HamsterJet::Update(const float fElapsedTime){
|
||||
void HamsterJet::Draw(){
|
||||
float drawingOffsetY{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().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);
|
||||
hamster.SetDrawingOffsetY(util::lerp(48.f,0.f,easeInTimer/0.6f));
|
||||
}
|
||||
@ -168,7 +179,7 @@ void HamsterJet::HandleJetControls(){
|
||||
jetState[BOTTOM_RIGHT]=ON;
|
||||
jetState[TOP_RIGHT]=ON;
|
||||
}
|
||||
if(aimingDir!=vf2d{}){
|
||||
if(aimingDir!=vf2d{}&&hamster.jetFuel>0.f){
|
||||
hamster.targetRot=aimingDir.norm().polar().y;
|
||||
const vf2d currentVel{hamster.vel};
|
||||
hamster.vel+=vf2d{currentVel.polar().x+(hamster.GetMaxSpeed()*HamsterGame::Game().GetElapsedTime())/hamster.GetTimeToMaxSpeed(),hamster.rot}.cart();
|
||||
|
@ -47,7 +47,7 @@ public:
|
||||
enum State{
|
||||
SWOOP_DOWN,
|
||||
RISE_UP,
|
||||
PLAYER_CONTROL,
|
||||
HAMSTER_CONTROL,
|
||||
LANDING,
|
||||
COMPLETE_LANDING,
|
||||
};
|
||||
|
@ -38,6 +38,7 @@ All rights reserved.
|
||||
|
||||
#include "HamsterGame.h"
|
||||
#include "Powerup.h"
|
||||
#include "Hamster.h"
|
||||
|
||||
std::vector<Powerup>Powerup::powerupList;
|
||||
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}};
|
||||
}
|
||||
|
||||
void Powerup::OnPowerupObtain(){
|
||||
void Powerup::OnPowerupObtain(Hamster&pickupHamster){
|
||||
spinSpd=0.3f;
|
||||
if(type==JET)pickupHamster.SetJetFuel(1.f);
|
||||
}
|
@ -41,6 +41,8 @@ All rights reserved.
|
||||
#include "olcUTIL_Geometry2D.h"
|
||||
#include "olcPGEX_TransformedView.h"
|
||||
|
||||
class Hamster;
|
||||
|
||||
class Powerup{
|
||||
public:
|
||||
enum PowerupType{
|
||||
@ -79,5 +81,5 @@ public:
|
||||
static void UpdatePowerups(const float fElapsedTime);
|
||||
static void DrawPowerups(TransformedView&tv);
|
||||
static const geom2d::rect<float>GetPowerupSubimageRect(const PowerupType powerupType);
|
||||
void OnPowerupObtain();
|
||||
void OnPowerupObtain(Hamster&pickupHamster);
|
||||
};
|
@ -74,3 +74,81 @@ const std::string Terrain::TerrainToString(const TerrainType type){
|
||||
}
|
||||
}
|
||||
}
|
||||
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,
|
||||
ICE,
|
||||
};
|
||||
enum CrashSpeed{
|
||||
MAX,
|
||||
MEDIUM,
|
||||
LIGHT,
|
||||
};
|
||||
using FuelDamage=float;
|
||||
using KnockoutOccurs=bool;
|
||||
const std::string TerrainToString(const TerrainType type);
|
||||
const std::pair<FuelDamage,KnockoutOccurs>GetFuelDamageTakenAndKnockoutEffect(const TerrainType type,const CrashSpeed crashSpeed);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user