diff --git a/assets/PBData b/assets/PBData index 92625dc..416d668 100644 --- a/assets/PBData +++ b/assets/PBData @@ -1 +1 @@ -44669 64212 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 0.7 0.6 OneLoneHam Black \ No newline at end of file +42976 64212 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 0.8 0.6 OneLoneHam Black \ No newline at end of file diff --git a/assets/Trevor Lentz - Guinea Pig Hero.ogg b/assets/Trevor Lentz - Guinea Pig Hero.ogg new file mode 100644 index 0000000..387701b Binary files /dev/null and b/assets/Trevor Lentz - Guinea Pig Hero.ogg differ diff --git a/assets/sounds/footsteps_rock.wav b/assets/sounds/footsteps_rock.wav new file mode 100644 index 0000000..c37a82f Binary files /dev/null and b/assets/sounds/footsteps_rock.wav differ diff --git a/assets/sounds/jet_takeoff.wav b/assets/sounds/jet_takeoff.wav new file mode 100644 index 0000000..51c24de Binary files /dev/null and b/assets/sounds/jet_takeoff.wav differ diff --git a/assets/sounds/land_ground.wav b/assets/sounds/land_ground.wav new file mode 100644 index 0000000..367f6c6 Binary files /dev/null and b/assets/sounds/land_ground.wav differ diff --git a/assets/sounds/winneris.ogg b/assets/sounds/winneris.ogg new file mode 100644 index 0000000..780e06b Binary files /dev/null and b/assets/sounds/winneris.ogg differ diff --git a/src/Hamster.cpp b/src/Hamster.cpp index 792cbd6..677a6d4 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -75,6 +75,7 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.bumpTimer-=fElapsedTime; h.boostTimer=std::max(0.f,h.boostTimer-fElapsedTime); h.canCollectWheelPowerupTimer=std::max(0.f,h.canCollectWheelPowerupTimer-fElapsedTime); + h.lastCollisionSound+=fElapsedTime; h.HandleCollision(); switch(h.state){ case NORMAL:{ @@ -98,6 +99,7 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ } else{ h.waitTimer=4.f; + HamsterGame::PlaySFX(h.pos,"drown_burn.wav"); h.SetState(WAIT); } }break; @@ -124,6 +126,7 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ h.imgScale=std::max(0.f,h.imgScale-0.5f*fElapsedTime); }else{ h.waitTimer=4.f; + HamsterGame::PlaySFX(h.pos,"drown_burn.wav"); h.SetState(WAIT); } }break; @@ -455,6 +458,7 @@ void Hamster::HandlePlayerControls(){ if(HamsterGame::Game().GetKey(R).bPressed&&boostCounter>0){ boostCounter--; boostTimer=1.f; + HamsterGame::PlaySFX(pos,"wheel_boost.wav"); if(IsPlayerControlled)HamsterAI::OnBoost(this->pos); } if(HamsterGame::Game().GetKey(SPACE).bPressed){ @@ -466,11 +470,6 @@ void Hamster::HandlePlayerControls(){ } lastTappedSpace=0.f; } - if(HamsterGame::Game().GetKey(P).bPressed){ - ObtainPowerup(Powerup::JET); - Powerup tempJetPowerup{{},Powerup::JET}; - tempJetPowerup.OnPowerupObtain(*this); - } } void Hamster::TurnTowardsTargetDirection(){ @@ -525,15 +524,23 @@ void Hamster::HandleCollision(){ h.vel+=vf2d{h.GetBumpAmount(),collisionLine.vector().polar().y}.cart(); h.vel=vf2d{std::min(h.GetMaxSpeed(),h.vel.polar().x),h.vel.polar().y}.cart(); } + if(h.lastCollisionSound>1.f){ + if(util::random()%2==0)HamsterGame::PlaySFX(pos,"hit_hamster.wav"); + else HamsterGame::PlaySFX(pos,"hit_hamster_2.wav"); + + lastCollisionSound=h.lastCollisionSound=0.f; + } bumpTimer=h.bumpTimer=0.12f; } } for(Powerup&powerup:Powerup::GetPowerups()){ if(z<=0.1f&& - (!HasPowerup(powerup.GetType())||HasPowerup(Powerup::JET)&&powerup.GetType()==Powerup::JET&&jetFuel!=1.f||HasPowerup(Powerup::WHEEL)&&boostCounter<3&&canCollectWheelPowerupTimer==0.f) + (!HasPowerup(powerup.GetType())||HasPowerup(Powerup::JET)&&powerup.GetType()==Powerup::JET&&jetFuel!=1.f||powerup.GetType()==Powerup::WHEEL&&HasPowerup(Powerup::WHEEL)&&boostCounter<3&&canCollectWheelPowerupTimer==0.f) &&geom2d::overlaps(geom2d::circle(GetPos(),collisionRadius),geom2d::circle(powerup.GetPos(),20.f))){ ObtainPowerup(powerup.GetType()); if(IsPlayerControlled)HamsterAI::OnPowerupCollection(this->pos); + if(powerup.GetType()==Powerup::JET)HamsterGame::PlaySFX(pos,"obtain_jet.wav"); + else HamsterGame::PlaySFX(pos,"collect_powerup.wav"); powerup.OnPowerupObtain(*this); } } @@ -543,7 +550,10 @@ void Hamster::HandleCollision(){ FloatingText::CreateFloatingText(pos,std::format("{} / {}",checkpointsCollected.size(),Checkpoint::GetCheckpoints().size()),{WHITE,GREEN},{1.5f,2.f}); if(IsPlayerControlled)HamsterAI::OnCheckpointCollected(this->pos); if(IsPlayerControlled)checkpoint.OnCheckpointCollect(); - if(CollectedAllCheckpoints()){finishedRaceTime=HamsterGame::Game().GetRaceTime();} + if(CollectedAllCheckpoints()){ + finishedRaceTime=HamsterGame::Game().GetRaceTime(); + if(IsPlayerControlled)HamsterGame::PlaySFX("winneris.ogg"); + }else HamsterGame::PlaySFX(pos,"checkpoint_collection.wav"); lastObtainedCheckpointPos=checkpoint.GetPos(); } } @@ -728,7 +738,14 @@ void Hamster::SetPos(const vf2d pos){ this->pos=vf2d{this->pos.x,pos.y}; movedY=true; } - if(IsPlayerControlled&&(movedX||movedY)&&HamsterGame::Game().GetTerrainTypeAtPos(this->pos)!=Terrain::TUNNEL&&state!=FLYING)HamsterAI::OnMove(this->pos); + Terrain::TerrainType terrainAtPos{HamsterGame::Game().GetTerrainTypeAtPos(this->pos)}; + if(distanceTravelled-lastFootstep>32.f){ + lastFootstep=distanceTravelled; + if(terrainAtPos==Terrain::ROCK)HamsterGame::PlaySFX(pos,"footsteps_rock.wav"); + else if(terrainAtPos==Terrain::SAND||terrainAtPos==Terrain::SWAMP||terrainAtPos==Terrain::FOREST)HamsterGame::PlaySFX(pos,"sfx_movement_footsteps1b.wav"); + else HamsterGame::PlaySFX(pos,"sfx_movement_footsteps1a.wav"); + } + if(IsPlayerControlled&&(movedX||movedY)&&terrainAtPos!=Terrain::TUNNEL&&state!=FLYING)HamsterAI::OnMove(this->pos); } void Hamster::SetZ(const float z){ diff --git a/src/Hamster.h b/src/Hamster.h index 59265bc..09b4a7c 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -133,6 +133,8 @@ class Hamster{ std::optionalfinishedRaceTime; std::optionallastObtainedCheckpointPos; HamsterAI::AIType aiLevel{HamsterAI::AIType::NORMAL}; + float lastFootstep{}; + float lastCollisionSound{}; public: Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled=NPC); static const Hamster&GetPlayer(); diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index ddc9b20..79bce81 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -80,7 +80,8 @@ bool HamsterGame::OnUserCreate(){ const auto LoadSound=[this](const std::string&filename){ bgm.insert({filename,audio.LoadSound(ASSETS_DIR+filename)}); }; - + + LoadSound("Trevor Lentz - Guinea Pig Hero.ogg"); LoadSound("Jonathan So - Fields of Ice.ogg"); LoadSound("Juhani Junkala - Stage 2.ogg"); LoadSound("shiru8bit - Moonlight.ogg"); @@ -241,8 +242,12 @@ void HamsterGame::UpdateGame(const float fElapsedTime){ countdownTimer-=fElapsedTime; if(countdownTimer<=0.f){ countdownTimer=0.f; + PlaySFX("start_race_whistle.wav"); leaderboard.OnRaceStart(); net.StartRace(currentMapName); + }else if(int(countdownTimer)!=lastDigitPlayedSound){ + lastDigitPlayedSound=int(countdownTimer); + PlaySFX("countdown.wav"); } } vEye.z+=(Hamster::GetPlayer().GetZ()+zoom-vEye.z)*fLazyFollowRate*fElapsedTime; @@ -606,6 +611,7 @@ const Difficulty&HamsterGame::GetMapDifficulty()const{ void HamsterGame::OnPlayerFinishedRace(){ std::pairresult{net.FinishRace()}; std::cout<<"Finish Time: "<(self->camera.GetPosition(),pos).length()}; + float Xdiff{pos.x-self->camera.GetPosition().x}; //If it's positive the sound is to our right... + self->audio.Play("assets/sounds/"+filename,std::clamp(1-distanceFromCamera/250.f,0.f,1.f)*self->sfxVol,std::clamp(Xdiff/250.f,-1.f,1.f),util::random_range(0.9f,1.1f)); +} + int main() { HamsterGame game("Project Hamster"); diff --git a/src/HamsterGame.h b/src/HamsterGame.h index 8a57acb..da56f6e 100644 --- a/src/HamsterGame.h +++ b/src/HamsterGame.h @@ -127,6 +127,8 @@ public: void SaveOptions(); const std::string ColorToHamsterImage(const std::string&color)const; std::string hamsterColor{hamsterColorNames[0]}; + static void PlaySFX(const std::string&filename); + static void PlaySFX(vf2d pos,const std::string&filename); private: void UpdateGame(const float fElapsedTime); void DrawGame(); @@ -207,4 +209,5 @@ private: std::string hamsterColorLabel{"hamsterColor"}; float bgmVol{0.7f}; float sfxVol{0.7f}; + int lastDigitPlayedSound{}; }; diff --git a/src/HamsterJet.cpp b/src/HamsterJet.cpp index d25b0c3..157702d 100644 --- a/src/HamsterJet.cpp +++ b/src/HamsterJet.cpp @@ -70,6 +70,7 @@ void HamsterJet::Update(const float fElapsedTime){ targetPos=pos+vf2d{128.f,32}; targetZ=8.f; timer=3.f; + HamsterGame::PlaySFX(pos,"jet_takeoff.wav"); } }break; case RISE_UP:{ @@ -112,6 +113,7 @@ void HamsterJet::Update(const float fElapsedTime){ hamster.SetState(Hamster::NORMAL); if(hamster.IsPlayerControlled)HamsterGame::Game().SetZoom(1.f); timer=3.f; + HamsterGame::PlaySFX(pos,"land_ground.wav"); originalPos=hamster.GetPos(); targetPos={hamster.GetPos().x+128.f,hamster.GetPos().y+32.f}; std::pairlandingResult{Terrain::GetFuelDamageTakenAndKnockoutEffect(hamster.GetTerrainStandingOn(),GetLandingSpeed())}; @@ -124,6 +126,7 @@ void HamsterJet::Update(const float fElapsedTime){ case COMPLETE_LANDING:{ z=util::lerp(3.f,0.f,std::pow(timer/3.f,2)); if(timer<=0.f){ + HamsterGame::PlaySFX(pos,"jet_land.wav"); hamster.hamsterJet.reset(); return; }else{ @@ -202,6 +205,7 @@ void HamsterJet::HandlePlayerControls(){ if(lastTappedSpace<=0.6f&&state!=LANDING){ state=LANDING; easeInTimer=0.f; + HamsterGame::PlaySFX(pos,"sfx_sounds_falling7.wav"); if(hamster.IsPlayerControlled)HamsterAI::OnJetBeginLanding(pos); } lastTappedSpace=0.f; @@ -279,6 +283,7 @@ void HamsterJet::HandleAIControls(){ if(action.type!=HamsterAI::Action::MOVE)variance=172.f; if(diff.mag()=menuButtons.size())selectedButton=0; else selectedButton.value()++; + HamsterGame::PlaySFX("menu_hover.wav"); } if(game.GetKey(ENTER).bPressed||game.GetKey(SPACE).bPressed||menuButtons[selectedButton.value()].IsHovered(oldLayerPos+game.SCREEN_FRAME.pos)&&game.GetMouse(Mouse::LEFT).bPressed){ menuButtons[selectedButton.value()].OnClick(); @@ -205,6 +210,7 @@ std::vectorMenu::GetMenuButtons(const MenuType type){ }); buttons.emplace_back(HamsterGame::SCREEN_FRAME.size/2+vf2d{0.f,0.f},std::format("SFX: {}",int(round(HamsterGame::Game().sfxVol*100))),"button2.png","highlight_button2.png",Pixel{114,109,163},Pixel{79,81,128},[this](Button&self){ HamsterGame::Game().sfxVol=((int(round(HamsterGame::Game().sfxVol*100))+10)%110)/100.f; + HamsterGame::PlaySFX("wheel_boost.wav"); self.buttonText=std::format("SFX: {}",int(round(HamsterGame::Game().sfxVol*100))); HamsterGame::Game().emscripten_temp_val=std::to_string(HamsterGame::Game().sfxVol); #ifdef __EMSCRIPTEN__ @@ -222,6 +228,7 @@ std::vectorMenu::GetMenuButtons(const MenuType type){ HamsterGame::Game().TextEntryEnable(true,HamsterGame::Game().playerName); }); buttons.emplace_back(HamsterGame::SCREEN_FRAME.size/2+vf2d{0.f,64.f},"","smallbutton.png","smallhighlight_button.png",Pixel{114,109,163},Pixel{79,81,128},[this](Button&self){ + HamsterGame::PlaySFX("select_track_confirm_name_menu.wav"); int colorInd{0}; for(int ind{0};const std::string&color:HamsterGame::Game().hamsterColorNames){ if(color==HamsterGame::Game().hamsterColor){ @@ -254,6 +261,9 @@ void Menu::OnMenuTransition(){ newMenuButtons.clear(); menuButtons=GetMenuButtons(currentMenu); switch(currentMenu){ + case TITLE_SCREEN:{ + HamsterGame::Game().audio.Play(HamsterGame::Game().bgm["Trevor Lentz - Guinea Pig Hero.ogg"]); + }break; case LOADING:{ colorNumb=util::random()%8+1; loading=true; @@ -507,4 +517,6 @@ void Menu::OnTextEntryComplete(const std::string&text){ } } ignoreInputs=true; -} \ No newline at end of file + HamsterGame::PlaySFX("menu_set_name.wav"); +} + diff --git a/src/olcPGEX_MiniAudio.cpp b/src/olcPGEX_MiniAudio.cpp index 90f00b0..14e931f 100644 --- a/src/olcPGEX_MiniAudio.cpp +++ b/src/olcPGEX_MiniAudio.cpp @@ -1,4 +1,2 @@ #define OLC_PGEX_MINIAUDIO -#include "olcPGEX_MiniAudio.h" - - +#include "olcPGEX_MiniAudio.h" \ No newline at end of file diff --git a/src/olcPGEX_MiniAudio.h b/src/olcPGEX_MiniAudio.h index 84ac01c..c0646f6 100644 --- a/src/olcPGEX_MiniAudio.h +++ b/src/olcPGEX_MiniAudio.h @@ -90,7 +90,7 @@ namespace olc // plays a sample, can be set to loop void Play(const int id, const bool loop = false); // plays a sound file, as a one off, and automatically unloads it - void Play(const std::string& path); + void Play(const std::string& path,const float&vol,const float&pan,const float&pitch); // stops a sample, rewinds to beginning void Stop(const int id); // pauses a sample, does not change position @@ -336,7 +336,7 @@ namespace olc ma_sound_start(vecSounds.at(id)); } - void MiniAudio::Play(const std::string& path) + void MiniAudio::Play(const std::string& path,const float&vol,const float&pan,const float&pitch) { // create the sound ma_sound* sound = new ma_sound(); @@ -344,7 +344,10 @@ namespace olc // load it from the file and decode it if(ma_sound_init_from_file(&engine, path.c_str(), MA_SOUND_FLAG_DECODE | MA_SOUND_FLAG_ASYNC, NULL, NULL, sound) != MA_SUCCESS) throw MiniAudioSoundException(); - + + ma_sound_set_volume(sound,vol); + ma_sound_set_pan(sound,pan); + ma_sound_set_pitch(sound,pitch); ma_sound_start(sound); vecOneOffSounds.push_back(sound); } @@ -352,7 +355,7 @@ namespace olc void MiniAudio::Stop(const int id) { ma_sound_seek_to_pcm_frame(vecSounds.at(id), 0); - ma_sound_stop(vecSounds.at(id)); + ma_sound_stop_with_fade_in_milliseconds(vecSounds.at(id),300); } void MiniAudio::Pause(const int id)