Keep persistent data about hamsters between map loads. Add menu backgrounds.
BIN
assets/background1.png
Normal file
After Width: | Height: | Size: 652 B |
BIN
assets/background2.png
Normal file
After Width: | Height: | Size: 652 B |
BIN
assets/background3.png
Normal file
After Width: | Height: | Size: 650 B |
BIN
assets/background4.png
Normal file
After Width: | Height: | Size: 652 B |
BIN
assets/background5.png
Normal file
After Width: | Height: | Size: 652 B |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
@ -48,7 +48,7 @@ std::vector<Hamster>Hamster::HAMSTER_LIST;
|
||||
const uint8_t Hamster::MAX_HAMSTER_COUNT{100U};
|
||||
const uint8_t Hamster::NPC_HAMSTER_COUNT{5U};
|
||||
const std::vector<std::string>Hamster::NPC_HAMSTER_IMAGES{
|
||||
"hamster.png",
|
||||
"hamster1.png",
|
||||
"hamster2.png",
|
||||
"hamster3.png",
|
||||
"hamster4.png",
|
||||
@ -57,11 +57,11 @@ const std::vector<std::string>Hamster::NPC_HAMSTER_IMAGES{
|
||||
"hamster7.png",
|
||||
"hamster8.png",
|
||||
};
|
||||
std::string Hamster::PLAYER_HAMSTER_IMAGE{"hamster.png"};
|
||||
std::string Hamster::PLAYER_HAMSTER_IMAGE{"hamster1.png"};
|
||||
std::optional<Hamster*>Hamster::playerHamster;
|
||||
|
||||
Hamster::Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled)
|
||||
:pos(spawnPos),IsPlayerControlled(IsPlayerControlled),randomId(util::random()){
|
||||
:pos(spawnPos),IsPlayerControlled(IsPlayerControlled),randomId(util::random()),colorFilename(img){
|
||||
animations=HamsterGame::GetAnimations(img);
|
||||
animations.ChangeState(internalAnimState,AnimationState::DEFAULT);
|
||||
}
|
||||
@ -297,6 +297,28 @@ void Hamster::MoveHamstersToSpawn(const geom2d::rect<int>startingLoc){
|
||||
aiFileCount++;
|
||||
MAX_AI_FILES--;
|
||||
}
|
||||
|
||||
struct HamsterPersistentData{
|
||||
HamsterAI::AIType aiLevel;
|
||||
std::string colorFilename;
|
||||
Hamster::PlayerControlled IsPlayerControlled;
|
||||
int points;
|
||||
};
|
||||
|
||||
std::vector<HamsterPersistentData>persistentData;
|
||||
size_t previousHamsterCount{HAMSTER_LIST.size()};
|
||||
for(int i:std::ranges::iota_view(0U,HAMSTER_LIST.size())){
|
||||
Hamster&hamster{HAMSTER_LIST[i]};
|
||||
//Keep persistent data available and reset Hamster.
|
||||
persistentData.emplace_back(hamster.aiLevel,hamster.colorFilename,hamster.IsPlayerControlled,hamster.points);
|
||||
}
|
||||
|
||||
HAMSTER_LIST.clear();
|
||||
for(HamsterPersistentData&data:persistentData){
|
||||
Hamster&newHamster{HAMSTER_LIST.emplace_back(vf2d{},data.colorFilename,data.IsPlayerControlled)};
|
||||
newHamster.points=data.points;
|
||||
}
|
||||
|
||||
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)});
|
||||
|
||||
@ -538,6 +560,7 @@ 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(GetState()==NORMAL){
|
||||
|
@ -129,6 +129,9 @@ class Hamster{
|
||||
float boostTimer{};
|
||||
float canCollectWheelPowerupTimer{};
|
||||
float SEARCH_RANGE{1.f};
|
||||
std::string colorFilename;
|
||||
int points{};
|
||||
std::optional<int>finishedRaceTime;
|
||||
HamsterAI::AIType aiLevel{HamsterAI::AIType::NORMAL};
|
||||
public:
|
||||
Hamster(const vf2d spawnPos,const std::string&img,const PlayerControlled IsPlayerControlled=NPC);
|
||||
|
@ -96,6 +96,11 @@ void HamsterGame::LoadGraphics(){
|
||||
_LoadImage("radaricons.png");
|
||||
_LoadImage("boost.png");
|
||||
_LoadImage("boost_outline.png");
|
||||
_LoadImage("background1.png");
|
||||
_LoadImage("background2.png");
|
||||
_LoadImage("background3.png");
|
||||
_LoadImage("background4.png");
|
||||
_LoadImage("background5.png");
|
||||
}
|
||||
|
||||
void HamsterGame::LoadAnimations(){
|
||||
@ -114,13 +119,7 @@ void HamsterGame::LoadAnimations(){
|
||||
}
|
||||
ANIMATIONS[std::string(img)].AddState(state,newAnimation);
|
||||
};
|
||||
|
||||
LoadAnimation(AnimationState::DEFAULT,"hamster.png",{{0,32},{32,32}},0.3f);
|
||||
LoadAnimation(AnimationState::WHEEL_TOP,"hamster.png",{{0,96},{32,96}},0.1f);
|
||||
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)){
|
||||
for(int i:std::ranges::iota_view(1,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);
|
||||
@ -369,11 +368,9 @@ bool HamsterGame::OnUserUpdate(float fElapsedTime){
|
||||
net.InitSession();
|
||||
netInitialized=true;
|
||||
|
||||
net.SetName("Sig");
|
||||
net.SetColor("Yellow");
|
||||
LoadLevel("StageV.tmx"); //THIS IS TEMPORARY.
|
||||
camera.SetTarget(Hamster::GetPlayer().GetPos());
|
||||
net.StartRace(currentMapName);
|
||||
net.SetName("OneLoneHamster");
|
||||
net.SetColor(hamsterColorNames[0]);
|
||||
SetupAndStartRace();
|
||||
}
|
||||
|
||||
runTime+=fElapsedTime;
|
||||
@ -658,6 +655,16 @@ const HamsterGame::GameMode HamsterGame::GetGameMode(){
|
||||
return mode;
|
||||
}
|
||||
|
||||
void HamsterGame::SetupAndStartRace(){
|
||||
LoadLevel("StageV.tmx"); //THIS IS TEMPORARY.
|
||||
camera.SetTarget(Hamster::GetPlayer().GetPos());
|
||||
net.StartRace(currentMapName);
|
||||
}
|
||||
|
||||
const int HamsterGame::GetRaceTime(){
|
||||
return net.GetCurrentRaceTime();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
HamsterGame game("Project Hamster");
|
||||
|
@ -101,6 +101,7 @@ public:
|
||||
const GameMode GetGameMode();
|
||||
static void SavePB(const std::string&mapName,int ms);
|
||||
static void LoadPBs();
|
||||
const int GetRaceTime();
|
||||
private:
|
||||
void UpdateGame(const float fElapsedTime);
|
||||
void DrawGame();
|
||||
@ -113,6 +114,7 @@ private:
|
||||
static HamsterGame*self;
|
||||
Border border;
|
||||
void DrawLevelTiles();
|
||||
void SetupAndStartRace();
|
||||
std::optional<TMXParser>currentMap;
|
||||
std::optional<TSXParser>currentTileset;
|
||||
double runTime{};
|
||||
@ -158,6 +160,19 @@ private:
|
||||
"StageX.tmx",
|
||||
"StageXI.tmx",
|
||||
"StageXII.tmx",
|
||||
"Grand Prix I",
|
||||
"Grand Prix II",
|
||||
"Grand Prix III",
|
||||
};
|
||||
std::string emscripten_temp_val{"123456"};
|
||||
std::vector<std::string>hamsterColorNames{
|
||||
"Yellow",
|
||||
"Pink",
|
||||
"Cyan",
|
||||
"Black",
|
||||
"Green",
|
||||
"Purple"
|
||||
"Red",
|
||||
"Blue",
|
||||
};
|
||||
};
|
@ -192,10 +192,10 @@ void HamsterJet::HandlePlayerControls(){
|
||||
hamster.vel=vf2d{std::min(hamster.GetMaxSpeed(),hamster.vel.polar().x),hamster.vel.polar().y}.cart();
|
||||
hamster.frictionEnabled=false;
|
||||
}
|
||||
if(HamsterGame::Game().GetKey(UP).bHeld){
|
||||
if(GetState()==LANDING&&HamsterGame::Game().GetKey(UP).bHeld){
|
||||
fallSpd=std::min(5.f,fallSpd+5.f*HamsterGame::Game().GetElapsedTime());
|
||||
}
|
||||
if(HamsterGame::Game().GetKey(DOWN).bHeld){
|
||||
if(GetState()==LANDING&&HamsterGame::Game().GetKey(DOWN).bHeld){
|
||||
fallSpd=std::max(1.f,fallSpd-5.f*HamsterGame::Game().GetElapsedTime());
|
||||
}
|
||||
if(HamsterGame::Game().GetKey(SPACE).bPressed){
|
||||
|
50
src/HamsterLeaderboard.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma region License
|
||||
/*
|
||||
License (OLC-3)
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions or derivations of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions or derivative works in binary form must reproduce the above
|
||||
copyright notice. This list of conditions and the following disclaimer must be
|
||||
reproduced in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this software without specific
|
||||
prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
Portions of this software are copyright © 2024 The FreeType
|
||||
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
|
||||
All rights reserved.
|
||||
*/
|
||||
#pragma endregion
|
||||
#pragma once
|
||||
#include "Hamster.h"
|
||||
|
||||
class HamsterLeaderboard{
|
||||
class HamsterRanking{
|
||||
std::reference_wrapper<Hamster>hamster;
|
||||
float ranking; //The higher the ranking, the higher the hamster is placed.
|
||||
};
|
||||
std::vector<HamsterRanking>hamsterRanking;
|
||||
public:
|
||||
void OnRaceStart();
|
||||
void OnRaceFinished();
|
||||
};
|
@ -227,7 +227,7 @@ bool HamsterNet::StartRace(const std::string& map)
|
||||
return (hamsterNet__startRace() == 1);
|
||||
}
|
||||
|
||||
int HamsterNet::GetCurrentRaceTime(const std::string& map){
|
||||
int HamsterNet::GetCurrentRaceTime(){
|
||||
std::chrono::duration<double, std::milli> duration = std::chrono::system_clock::now() - m_tp1;
|
||||
return static_cast<int>(duration.count());
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public:
|
||||
|
||||
bool StartRace(const std::string& map);
|
||||
using FinishTime=int;
|
||||
int GetCurrentRaceTime(const std::string& map);
|
||||
int GetCurrentRaceTime();
|
||||
std::pair<FinishTime,bool> FinishRace();
|
||||
|
||||
std::vector<LeaderboardEntry> GetLeaderboard(const std::string& map, const int offset = 0, const int limit = 100, const std::string& sortBy = "time", bool ascending = true);
|
||||
|
79
src/TODO.txt
@ -154,6 +154,85 @@ Stage 11: Boss Battle #3 Alternate - nene
|
||||
Stage 12: Boss Battle #5 V2 - nene
|
||||
|
||||
|
||||
Live Placement Tracking
|
||||
Pulsating Animation based on terrain walking across
|
||||
|
||||
Sound Effects
|
||||
|
||||
Footstep sounds(Grass, Sand, Rock, Shore (Shared with Lava and Swamp), Ocean)
|
||||
Hamster Wheel sounds (Rolling)
|
||||
Hamster Jet Idle Sound
|
||||
Hamster Jet Rockets Sound
|
||||
Hamster Jet Landing Sound
|
||||
Powerup Collection Sound
|
||||
Hamster Wheel Boost Sound
|
||||
Checkpoint Collection Sound
|
||||
|
||||
Hamster Jet Launch Command Sound
|
||||
Fail to Boost/Jet Launch command sound
|
||||
|
||||
Race Finish sound
|
||||
Race Start sound
|
||||
Race Countdown timer sound
|
||||
|
||||
Menu Select/Back Sound
|
||||
|
||||
==========================
|
||||
Stages VI - XII: 7 Stages (1 hour each, 7 hours total)
|
||||
Menu Navigations (2 hours)
|
||||
Grand Prix Management (1 hour)
|
||||
Unlocks (1 hour)
|
||||
Leaderboard Management (1 hour)
|
||||
|
||||
Menus
|
||||
===========
|
||||
Title Screen
|
||||
Main Menu
|
||||
Grand Prix
|
||||
Single Race (Locked behind Grand Prix I)
|
||||
Options
|
||||
Quit
|
||||
(Bottom of Main Menu shows Research Progress)
|
||||
|
||||
Races:
|
||||
1st - 10
|
||||
2nd - 7
|
||||
3rd - 5
|
||||
4th - 3
|
||||
5th - 2
|
||||
6th - 1
|
||||
|
||||
Research Progress: Each Grand Prix has up to 40 points to earn, thus you need 120 Research points to beat the game.
|
||||
|
||||
Grand Prix
|
||||
Grand Prix I
|
||||
Grand Prix II (Locked behind Grand Prix I)
|
||||
Grand Prix III (Locked behind Grand Prix II)
|
||||
Marathon (Locked behind Game Completion)
|
||||
|
||||
Single Race
|
||||
Track I
|
||||
Track II
|
||||
Track III
|
||||
Track IV
|
||||
Track V
|
||||
Track VI
|
||||
Track VII
|
||||
Track VIII
|
||||
Track IX
|
||||
Track X
|
||||
Track XI
|
||||
Track XII
|
||||
|
||||
Options
|
||||
Volume Control
|
||||
Remap R / Space to different keys.
|
||||
|
||||
Racing
|
||||
|
||||
|
||||
|
||||
|
||||
Settings
|
||||
========
|
||||
Keybind Rebinds
|