diff --git a/assets/hamster.xcf b/assets/hamster.xcf index 5ce675f..fe7aa13 100644 Binary files a/assets/hamster.xcf and b/assets/hamster.xcf differ diff --git a/assets/hamster2.png b/assets/hamster2.png new file mode 100644 index 0000000..78e3a2e Binary files /dev/null and b/assets/hamster2.png differ diff --git a/assets/hamster3.png b/assets/hamster3.png new file mode 100644 index 0000000..b905ab2 Binary files /dev/null and b/assets/hamster3.png differ diff --git a/assets/hamster4.png b/assets/hamster4.png new file mode 100644 index 0000000..9664abf Binary files /dev/null and b/assets/hamster4.png differ diff --git a/assets/hamster5.png b/assets/hamster5.png new file mode 100644 index 0000000..e245c71 Binary files /dev/null and b/assets/hamster5.png differ diff --git a/assets/hamster6.png b/assets/hamster6.png new file mode 100644 index 0000000..1b759ba Binary files /dev/null and b/assets/hamster6.png differ diff --git a/assets/hamster7.png b/assets/hamster7.png new file mode 100644 index 0000000..db42a86 Binary files /dev/null and b/assets/hamster7.png differ diff --git a/assets/hamster8.png b/assets/hamster8.png new file mode 100644 index 0000000..f7acb25 Binary files /dev/null and b/assets/hamster8.png differ diff --git a/src/Hamster.cpp b/src/Hamster.cpp index 83947a8..bfafeb6 100644 --- a/src/Hamster.cpp +++ b/src/Hamster.cpp @@ -49,8 +49,15 @@ const uint8_t Hamster::MAX_HAMSTER_COUNT{100U}; const uint8_t Hamster::NPC_HAMSTER_COUNT{5U}; const std::vectorHamster::NPC_HAMSTER_IMAGES{ "hamster.png", + "hamster2.png", + "hamster3.png", + "hamster4.png", + "hamster5.png", + "hamster6.png", + "hamster7.png", + "hamster8.png", }; -const std::string Hamster::PLAYER_HAMSTER_IMAGE{"hamster.png"}; +std::string Hamster::PLAYER_HAMSTER_IMAGE{"hamster.png"}; std::optionalHamster::playerHamster; Hamster::Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled) @@ -219,52 +226,92 @@ void Hamster::UpdateHamsters(const float fElapsedTime){ } } -void Hamster::LoadHamsters(const geom2d::rectstartingLoc){ +void Hamster::CreateHamsters(const HamsterGame::GameMode mode){ HAMSTER_LIST.clear(); playerHamster.reset(); HAMSTER_LIST.reserve(MAX_HAMSTER_COUNT); if(NPC_HAMSTER_COUNT+1>MAX_HAMSTER_COUNT)throw std::runtime_error{std::format("WARNING! Max hamster count is too high! Please expand the MAX_HAMSTER_COUNT if you want more hamsters. Requested {} hamsters.",MAX_HAMSTER_COUNT)}; - playerHamster=&HAMSTER_LIST.emplace_back(vf2d{util::random_range(startingLoc.pos.x,startingLoc.pos.x+startingLoc.size.x),util::random_range(startingLoc.pos.y,startingLoc.pos.y+startingLoc.size.y)},PLAYER_HAMSTER_IMAGE,PLAYER_CONTROLLED); + playerHamster=&HAMSTER_LIST.emplace_back(vf2d{},PLAYER_HAMSTER_IMAGE,PLAYER_CONTROLLED); + std::vectorhamsterColorChoices{NPC_HAMSTER_IMAGES}; + std::erase(hamsterColorChoices,PLAYER_HAMSTER_IMAGE); for(int i:std::ranges::iota_view(0U,NPC_HAMSTER_COUNT)){ - Hamster&npcHamster{HAMSTER_LIST.emplace_back(vf2d{util::random_range(startingLoc.pos.x,startingLoc.pos.x+startingLoc.size.x),util::random_range(startingLoc.pos.y,startingLoc.pos.y+startingLoc.size.y)},NPC_HAMSTER_IMAGES.at(util::random()%NPC_HAMSTER_IMAGES.size()),NPC)}; - int MAX_AI_FILES{100}; - int aiFileCount{0}; - while(MAX_AI_FILES>0){ - if(!std::filesystem::exists(std::format("{}{}.{}",HamsterGame::ASSETS_DIR,HamsterGame::Game().GetCurrentMapName(),aiFileCount)))break; - aiFileCount++; - MAX_AI_FILES--; - } + std::string colorChoice{hamsterColorChoices.at(util::random()%hamsterColorChoices.size())}; + std::erase(hamsterColorChoices,colorChoice); + Hamster&npcHamster{HAMSTER_LIST.emplace_back(vf2d{},colorChoice,NPC)}; HamsterAI::AIType typeChosen{HamsterAI::DUMB}; - int randPct{util::random()%100}; - switch(HamsterGame::Game().GetMapDifficulty()){ - case Difficulty::EASY:{ - if(randPct<=40&&randPct>20)typeChosen=HamsterAI::NORMAL; - else if(randPct<=20)typeChosen=HamsterAI::SMART; + switch(mode){ + case HamsterGame::GameMode::GRAND_PRIX_1:{ + int randPct{util::random()%100}; + if(randPct<=25)typeChosen=HamsterAI::DUMB; + else if(randPct<=75)typeChosen=HamsterAI::NORMAL; + else typeChosen=HamsterAI::SMART; + }break; + case HamsterGame::GameMode::GRAND_PRIX_2:{ + int randPct{util::random()%100}; + if(randPct<=10)typeChosen=HamsterAI::DUMB; + else if(randPct<=2)typeChosen=HamsterAI::NORMAL; + else typeChosen=HamsterAI::SMART; + }break; + case HamsterGame::GameMode::GRAND_PRIX_3:{ + int randPct{util::random()%100}; + if(randPct<=1)typeChosen=HamsterAI::DUMB; + else if(randPct<=20)typeChosen=HamsterAI::NORMAL; + else typeChosen=HamsterAI::SMART; }break; - case Difficulty::MEDIUM:{ - typeChosen=HamsterAI::NORMAL; - if(randPct<=100&&randPct>80)typeChosen=HamsterAI::DUMB; - else if(randPct<=20)typeChosen=HamsterAI::SMART; + case HamsterGame::GameMode::SINGLE_RACE:{ + int randPct{util::random()%100}; + switch(HamsterGame::Game().GetMapDifficulty()){ + case Difficulty::EASY:{ + if(randPct<=40&&randPct>20)typeChosen=HamsterAI::NORMAL; + else if(randPct<=20)typeChosen=HamsterAI::SMART; + }break; + case Difficulty::MEDIUM:{ + typeChosen=HamsterAI::NORMAL; + if(randPct<=100&&randPct>80)typeChosen=HamsterAI::DUMB; + else if(randPct<=20)typeChosen=HamsterAI::SMART; + }break; + case Difficulty::HARD:{ + typeChosen=HamsterAI::SMART; + if(randPct<=20)typeChosen=HamsterAI::NORMAL; + }break; + } }break; - case Difficulty::HARD:{ - typeChosen=HamsterAI::SMART; - if(randPct<=20)typeChosen=HamsterAI::NORMAL; + case HamsterGame::GameMode::MARATHON:{ + int randPct{util::random()%100}; + if(randPct<=1)typeChosen=HamsterAI::DUMB; + else if(randPct<=20)typeChosen=HamsterAI::NORMAL; + else typeChosen=HamsterAI::SMART; }break; } + npcHamster.aiLevel=typeChosen; + } +} + +void Hamster::MoveHamstersToSpawn(const geom2d::rectstartingLoc){ + int MAX_AI_FILES{100}; + int aiFileCount{0}; + while(MAX_AI_FILES>0){ + if(!std::filesystem::exists(std::format("{}{}.{}",HamsterGame::ASSETS_DIR,HamsterGame::Game().GetCurrentMapName(),aiFileCount)))break; + aiFileCount++; + MAX_AI_FILES--; + } + for(Hamster&hamster:HAMSTER_LIST){ + hamster.SetPos(vf2d{util::random_range(startingLoc.pos.x,startingLoc.pos.x+startingLoc.size.x),util::random_range(startingLoc.pos.y,startingLoc.pos.y+startingLoc.size.y)}); + std::vectorpossibleAIs{}; for(int i:std::ranges::iota_view(0,aiFileCount)){ - if(i%3==int(typeChosen))possibleAIs.emplace_back(i); + if(i%3==hamster.aiLevel)possibleAIs.emplace_back(i); } if(possibleAIs.size()==0){ - std::cout<<"WARNING! No AI files for AI Type "<0)npcHamster.ai.LoadAI(HamsterGame::Game().GetCurrentMapName(),possibleAIs[util::random()%possibleAIs.size()]); + if(possibleAIs.size()>0)hamster.ai.LoadAI(HamsterGame::Game().GetCurrentMapName(),possibleAIs[util::random()%possibleAIs.size()]); } } diff --git a/src/Hamster.h b/src/Hamster.h index 39d2c2f..d557dd6 100644 --- a/src/Hamster.h +++ b/src/Hamster.h @@ -75,7 +75,7 @@ class Hamster{ static const uint8_t NPC_HAMSTER_COUNT; static const std::vectorNPC_HAMSTER_IMAGES; - static const std::string PLAYER_HAMSTER_IMAGE; + static std::string PLAYER_HAMSTER_IMAGE; const float DEFAULT_MAX_SPD{128.f}; const float DEFAULT_TIME_TO_MAX_SPD{0.3f}; @@ -129,11 +129,13 @@ class Hamster{ float boostTimer{}; float canCollectWheelPowerupTimer{}; float SEARCH_RANGE{1.f}; + HamsterAI::AIType aiLevel; public: Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled=NPC); static const Hamster&GetPlayer(); static void UpdateHamsters(const float fElapsedTime); - static void LoadHamsters(const geom2d::rectstartingLoc); + static void CreateHamsters(const HamsterGame::GameMode mode); + static void MoveHamstersToSpawn(const geom2d::rectstartingLoc); static void DrawHamsters(TransformedView&tv); static void DrawOverlay(); const Animate2D::Frame&GetCurrentAnimation()const; diff --git a/src/HamsterGame.cpp b/src/HamsterGame.cpp index 1ec0e8f..303c247 100644 --- a/src/HamsterGame.cpp +++ b/src/HamsterGame.cpp @@ -42,8 +42,11 @@ bool HamsterGame::OnUserCreate(){ LoadSound("shiru8bit - A Little Journey.ogg"); LoadSound("nene - Boss Battle #3 Alternate.ogg"); LoadSound("nene - Boss Battle #5 V2.ogg"); - + LoadLevel("StageV.tmx"); //THIS IS TEMPORARY. + Hamster::CreateHamsters(mode); + Hamster::MoveHamstersToSpawn(currentMap.value().GetData().GetSpawnZone()); + camera.SetTarget(Hamster::GetPlayer().GetPos()); border.ChangeBorder(Border::DEFAULT); @@ -119,6 +122,13 @@ void HamsterGame::LoadAnimations(){ LoadAnimation(AnimationState::WHEEL_BOTTOM,"hamster.png",{{64,96},{96,96}},0.1f); LoadAnimation(AnimationState::KNOCKOUT,"hamster.png",{{64,32},{96,32}},0.2f); LoadAnimation(AnimationState::SIDE_VIEW,"hamster.png",{{0,0},{32,0}},0.3f); + for(int i:std::ranges::iota_view(2,9)){ + LoadAnimation(AnimationState::DEFAULT,std::format("hamster{}.png",i),{{0,32},{32,32}},0.3f); + LoadAnimation(AnimationState::WHEEL_TOP,std::format("hamster{}.png",i),{{0,96},{32,96}},0.1f); + LoadAnimation(AnimationState::WHEEL_BOTTOM,std::format("hamster{}.png",i),{{64,96},{96,96}},0.1f); + LoadAnimation(AnimationState::KNOCKOUT,std::format("hamster{}.png",i),{{64,32},{96,32}},0.2f); + LoadAnimation(AnimationState::SIDE_VIEW,std::format("hamster{}.png",i),{{0,0},{32,0}},0.3f); + } Animate2D::FrameSequence&waterAnimFrames{(*ANIMATED_TILE_IDS.insert({1384,Animate2D::FrameSequence{0.2f}}).first).second}; for(vf2d&sourcePos:std::vector{{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}}}); @@ -147,9 +157,6 @@ void HamsterGame::LoadLevel(const std::string&mapName){ camera.SetTarget(currentMap.value().GetData().GetSpawnZone().middle()); camera.Update(0.f); camera.SetMode(Camera2D::Mode::LazyFollow); - - Hamster::LoadHamsters(currentMap.value().GetData().GetSpawnZone()); - camera.SetTarget(Hamster::GetPlayer().GetPos()); mapImage.Create(currentMap.value().GetData().GetMapData().width*16,currentMap.value().GetData().GetMapData().height*16); SetDrawTarget(mapImage.Sprite()); diff --git a/src/HamsterGame.h b/src/HamsterGame.h index 7d5549c..c8e6e38 100644 --- a/src/HamsterGame.h +++ b/src/HamsterGame.h @@ -60,6 +60,13 @@ struct Letter{ class HamsterGame : public olc::PixelGameEngine { public: + enum class GameMode{ + GRAND_PRIX_1, + GRAND_PRIX_2, + GRAND_PRIX_3, + SINGLE_RACE, + MARATHON, + }; const static std::string ASSETS_DIR; HamsterGame()=delete; HamsterGame(const std::string&appName); @@ -122,4 +129,5 @@ private: std::string currentMapName; MiniAudio audio; std::unordered_mapbgm; + GameMode mode{GameMode::SINGLE_RACE}; }; \ No newline at end of file