feat: fast forward
This commit is contained in:
@@ -80,7 +80,29 @@ public:
|
||||
std::uint8_t GetPlayerCount() const;
|
||||
};
|
||||
|
||||
typedef std::array<Team, 2> TeamList;
|
||||
struct TeamList {
|
||||
std::array<Team, 2> m_Teams;
|
||||
|
||||
TeamList() : m_Teams{Team{TeamColor::Red}, Team{TeamColor::Blue}}{
|
||||
|
||||
}
|
||||
|
||||
Team& operator[](std::size_t a_Index) {
|
||||
return m_Teams[a_Index];
|
||||
}
|
||||
|
||||
Team& operator[](TeamColor a_Index) {
|
||||
return m_Teams[static_cast<std::size_t>(a_Index)];
|
||||
}
|
||||
|
||||
const Team& operator[](std::size_t a_Index) const {
|
||||
return m_Teams[a_Index];
|
||||
}
|
||||
|
||||
const Team& operator[](TeamColor a_Index) const {
|
||||
return m_Teams[static_cast<std::size_t>(a_Index)];
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
|
||||
@@ -107,15 +107,15 @@ class ConcreteTower : public sp::ConcreteMessage<TowerData, Tower, Type, false>
|
||||
public:
|
||||
using HandlerType = typename sp::ConcreteMessage<TowerData, Tower, Type, false>::HandlerType;
|
||||
|
||||
virtual TowerSize GetSize() const {
|
||||
virtual TowerSize GetSize() const override {
|
||||
return Size;
|
||||
}
|
||||
|
||||
virtual TowerType GetType() const {
|
||||
virtual TowerType GetType() const override {
|
||||
return Type;
|
||||
}
|
||||
|
||||
virtual void Tick(std::uint64_t delta, World* world) {}
|
||||
virtual void Tick(std::uint64_t delta, World* world) override {}
|
||||
|
||||
virtual void Dispatch(HandlerType& handler) const override {
|
||||
handler.Handle(*this);
|
||||
|
||||
@@ -20,8 +20,8 @@ class World {
|
||||
|
||||
TilePalette m_TilePalette;
|
||||
|
||||
sim::WorldSnapshot m_CurrentState;
|
||||
sim::WorldSnapshot m_NextState;
|
||||
std::shared_ptr<sim::WorldSnapshot> m_CurrentState;
|
||||
std::shared_ptr<sim::WorldSnapshot> m_NextState;
|
||||
|
||||
private:
|
||||
sim::WorldTicker m_Ticker;
|
||||
@@ -82,52 +82,55 @@ class World {
|
||||
}
|
||||
|
||||
const MobList& GetMobList() const {
|
||||
return m_CurrentState.m_Mobs;
|
||||
return m_CurrentState->m_Mobs;
|
||||
}
|
||||
MobList& GetMobList() {
|
||||
return m_CurrentState.m_Mobs;
|
||||
return m_CurrentState->m_Mobs;
|
||||
}
|
||||
|
||||
const Color* GetTileColor(const TilePtr& tile) const;
|
||||
|
||||
Team& GetRedTeam() {
|
||||
return m_CurrentState.m_Teams[static_cast<std::uint8_t>(TeamColor::Red)];
|
||||
return m_CurrentState->m_Teams[TeamColor::Red];
|
||||
}
|
||||
const Team& GetRedTeam() const {
|
||||
return m_CurrentState.m_Teams[static_cast<std::uint8_t>(TeamColor::Red)];
|
||||
return m_CurrentState->m_Teams[TeamColor::Red];
|
||||
}
|
||||
|
||||
Team& GetBlueTeam() {
|
||||
return m_CurrentState.m_Teams[static_cast<std::uint8_t>(TeamColor::Blue)];
|
||||
return m_CurrentState->m_Teams[TeamColor::Blue];
|
||||
}
|
||||
const Team& GetBlueTeam() const {
|
||||
return m_CurrentState.m_Teams[static_cast<std::uint8_t>(TeamColor::Red)];
|
||||
return m_CurrentState->m_Teams[TeamColor::Red];
|
||||
}
|
||||
|
||||
Team& GetTeam(TeamColor team) {
|
||||
return m_CurrentState.m_Teams[static_cast<std::uint8_t>(team)];
|
||||
return m_CurrentState->m_Teams[team];
|
||||
}
|
||||
const Team& GetTeam(TeamColor team) const {
|
||||
return m_CurrentState.m_Teams[static_cast<std::uint8_t>(team)];
|
||||
return m_CurrentState->m_Teams[team];
|
||||
}
|
||||
|
||||
const TeamList& GetTeams() const {
|
||||
return m_CurrentState.m_Teams;
|
||||
return m_CurrentState->m_Teams;
|
||||
}
|
||||
|
||||
const TowerList& GetTowers() const {
|
||||
return m_CurrentState.m_Towers;
|
||||
return m_CurrentState->m_Towers;
|
||||
}
|
||||
|
||||
TowerPtr GetTowerById(TowerID tower);
|
||||
|
||||
const Player* GetPlayerById(PlayerID id) const;
|
||||
|
||||
void Tick(const protocol::LockStep& a_LockStep, FpFloat a_Delta);
|
||||
const std::shared_ptr<sim::WorldSnapshot>& Tick(const protocol::LockStep& a_LockStep, FpFloat a_Delta);
|
||||
|
||||
void ResetSnapshots(std::shared_ptr<sim::WorldSnapshot>& a_Current, std::shared_ptr<sim::WorldSnapshot>& a_Next);
|
||||
|
||||
private:
|
||||
void TickMobs(std::uint64_t delta);
|
||||
void CleanDeadMobs();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <SDL3/SDL_video.h>
|
||||
#include <SDL3/SDL_keycode.h>
|
||||
#include <td/misc/Signal.h>
|
||||
|
||||
namespace td {
|
||||
@@ -10,6 +11,7 @@ namespace td {
|
||||
class Display {
|
||||
public:
|
||||
utils::Signal<float> OnAspectRatioChange;
|
||||
utils::Signal<SDL_Keycode> OnKeyDown;
|
||||
|
||||
Display(int a_Width, int a_Height, const std::string& a_Title);
|
||||
~Display();
|
||||
|
||||
@@ -74,7 +74,7 @@ struct BeginGame {
|
||||
|
||||
struct LockSteps {
|
||||
std::uint16_t m_FirstFrameNumber;
|
||||
Array<LockStep, LOCKSTEP_BUFFER_SIZE> m_LockSteps;
|
||||
std::array<LockStep, LOCKSTEP_BUFFER_SIZE> m_LockSteps;
|
||||
};
|
||||
|
||||
struct WorldHeader {
|
||||
|
||||
@@ -1,34 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/game/World.h>
|
||||
#include <optional>
|
||||
|
||||
namespace td {
|
||||
namespace sim {
|
||||
|
||||
using GameHistory = std::vector<td::protocol::LockStep>;
|
||||
using GameBuffer = std::vector<std::optional<td::protocol::LockStep>>;
|
||||
|
||||
class RealTimeSimulation {
|
||||
private:
|
||||
std::uint64_t m_StepTime;
|
||||
game::World& m_World;
|
||||
GameHistory m_History;
|
||||
GameBuffer m_History;
|
||||
std::uint64_t m_CurrentTime;
|
||||
std::uint64_t m_LastTime;
|
||||
std::size_t m_CurrentStep;
|
||||
|
||||
std::shared_ptr<WorldSnapshot> m_LastSnapshot;
|
||||
std::uint64_t m_LastValidStep;
|
||||
|
||||
static const protocol::LockStep EMPTY_LOCKSTEP;
|
||||
|
||||
public:
|
||||
/**
|
||||
* \brief Replay constructor
|
||||
* \param a_StepTime in ms
|
||||
*/
|
||||
RealTimeSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime);
|
||||
RealTimeSimulation(game::World& a_World, const GameHistory& a_History, std::uint64_t a_StepTime);
|
||||
|
||||
/**
|
||||
* \brief Live update constructor (continuous game updates)
|
||||
* \param a_StepTime in ms
|
||||
*/
|
||||
RealTimeSimulation(game::World& a_World, std::uint64_t a_StepTime);
|
||||
|
||||
/**
|
||||
* \return the progress [0-1] between two steps
|
||||
*/
|
||||
float Update();
|
||||
|
||||
void HandlePacket(const protocol::packets::LockStepsPacket& a_LockSteps);
|
||||
void HandlePacket(const protocol::packets::PredictCommandPacket& a_Predict);
|
||||
|
||||
private:
|
||||
void Step();
|
||||
|
||||
/**
|
||||
* \brief Ticks a_Count times
|
||||
*/
|
||||
void FastForward(std::size_t a_Count);
|
||||
|
||||
/**
|
||||
* \brief Tries to recompute simulation if needed (for example in late command receival)
|
||||
*/
|
||||
void FastReplay();
|
||||
};
|
||||
|
||||
} // namespace sim
|
||||
|
||||
Reference in New Issue
Block a user