feat: fast forward
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
namespace td {
|
||||
namespace game {
|
||||
|
||||
World::World() : m_CurrentState{.m_Teams{Team{TeamColor::Red}, Team{TeamColor::Blue}}}, m_NextState{.m_Teams{Team{TeamColor::Red}, Team{TeamColor::Blue}}} {}
|
||||
World::World() : m_CurrentState(std::make_shared<sim::WorldSnapshot>()), m_NextState(m_CurrentState) {}
|
||||
|
||||
const Color* World::GetTileColor(const TilePtr& tile) const {
|
||||
switch (tile->GetType()) {
|
||||
@@ -55,9 +55,15 @@ bool World::LoadMap(const protocol::pdata::WorldData& a_WorldData) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void World::Tick(const protocol::LockStep& a_LockStep, FpFloat a_Delta) {
|
||||
const std::shared_ptr<sim::WorldSnapshot>& World::Tick(const protocol::LockStep& a_LockStep, FpFloat a_Delta) {
|
||||
m_CurrentState = m_NextState;
|
||||
m_NextState = m_Ticker.NextStep(*this, m_NextState, a_LockStep, a_Delta);
|
||||
m_NextState = std::make_shared<sim::WorldSnapshot>(m_Ticker.NextStep(*this, *m_NextState, a_LockStep, a_Delta));
|
||||
return m_CurrentState;
|
||||
}
|
||||
|
||||
void World::ResetSnapshots(std::shared_ptr<sim::WorldSnapshot>& a_Current, std::shared_ptr<sim::WorldSnapshot>& a_Next) {
|
||||
m_CurrentState = a_Current;
|
||||
m_NextState = a_Next;
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
|
||||
@@ -119,6 +119,7 @@ void Display::PollEvents() {
|
||||
case SDL_EVENT_QUIT:
|
||||
case SDL_EVENT_WINDOW_CLOSE_REQUESTED: {
|
||||
m_ShouldClose = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_WINDOW_RESIZED: {
|
||||
@@ -126,6 +127,13 @@ void Display::PollEvents() {
|
||||
m_LastHeight = event.window.data2;
|
||||
m_AspectRatio = (float)m_LastWidth / m_LastHeight;
|
||||
OnAspectRatioChange(m_AspectRatio);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_KEY_DOWN: {
|
||||
if(!event.key.repeat)
|
||||
OnKeyDown(event.key.key);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
@@ -5,7 +5,9 @@ namespace sim {
|
||||
|
||||
CommandApply::CommandApply(const game::World& a_World, WorldSnapshot& a_Snapshot) : m_World(a_World), m_Snapshot(a_Snapshot) {}
|
||||
|
||||
void CommandApply::Handle(const protocol::commands::EndCommand& a_End) {}
|
||||
void CommandApply::Handle(const protocol::commands::EndCommand& a_End) {
|
||||
(void) m_World;
|
||||
}
|
||||
|
||||
void CommandApply::Handle(const protocol::commands::PlaceTowerCommand& a_PlaceTower) {
|
||||
static game::TowerFactory factory;
|
||||
|
||||
@@ -33,7 +33,7 @@ void GameHistory::FromPacket(td::protocol::pdata::LockSteps&& a_Steps) {
|
||||
}
|
||||
|
||||
td::protocol::packets::LockStepsPacket GameHistory::ToPacket(HistorySizeType a_StartIndex) {
|
||||
Array<protocol::LockStep, LOCKSTEP_BUFFER_SIZE> steps;
|
||||
std::array<protocol::LockStep, LOCKSTEP_BUFFER_SIZE> steps;
|
||||
for (int i = 0; i < LOCKSTEP_BUFFER_SIZE; i++) {
|
||||
steps[i] = GetLockStep(a_StartIndex + i);
|
||||
}
|
||||
|
||||
@@ -5,18 +5,37 @@
|
||||
namespace td {
|
||||
namespace sim {
|
||||
|
||||
const protocol::LockStep RealTimeSimulation::EMPTY_LOCKSTEP;
|
||||
|
||||
std::uint64_t GetTime() {
|
||||
return static_cast<std::uint64_t>(
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock().now().time_since_epoch()).count());
|
||||
}
|
||||
|
||||
RealTimeSimulation::RealTimeSimulation(game::World& a_World, GameHistory&& a_History, std::uint64_t a_StepTime) :
|
||||
RealTimeSimulation::RealTimeSimulation(game::World& a_World, const GameHistory& a_History, std::uint64_t a_StepTime) :
|
||||
m_StepTime(a_StepTime),
|
||||
m_World(a_World),
|
||||
m_History(std::move(a_History)),
|
||||
m_CurrentTime(0),
|
||||
m_LastTime(GetTime()),
|
||||
m_CurrentStep(0) {
|
||||
m_CurrentStep(0),
|
||||
m_LastSnapshot(std::make_shared<WorldSnapshot>()),
|
||||
m_LastValidStep(0) {
|
||||
m_History.reserve(a_History.size());
|
||||
for (const auto& lockstep : a_History) {
|
||||
m_History.emplace_back(lockstep);
|
||||
}
|
||||
Step();
|
||||
}
|
||||
|
||||
RealTimeSimulation::RealTimeSimulation(game::World& a_World, std::uint64_t a_StepTime) :
|
||||
m_StepTime(a_StepTime),
|
||||
m_World(a_World),
|
||||
m_History(std::numeric_limits<std::uint16_t>::max()),
|
||||
m_CurrentTime(0),
|
||||
m_LastTime(GetTime()),
|
||||
m_CurrentStep(0),
|
||||
m_LastSnapshot(std::make_shared<WorldSnapshot>()),
|
||||
m_LastValidStep(0) {
|
||||
Step();
|
||||
}
|
||||
|
||||
@@ -28,13 +47,47 @@ float RealTimeSimulation::Update() {
|
||||
Step();
|
||||
m_CurrentTime -= m_StepTime;
|
||||
}
|
||||
return (float) m_CurrentTime / (float) m_StepTime;
|
||||
return (float)m_CurrentTime / (float)m_StepTime;
|
||||
}
|
||||
|
||||
void RealTimeSimulation::Step() {
|
||||
m_World.Tick(m_History[m_CurrentStep], FpFloat(m_StepTime) / FpFloat(1000));
|
||||
const auto& step = m_History[m_CurrentStep];
|
||||
if (step.has_value()) {
|
||||
m_LastSnapshot = m_World.Tick(step.value(), FpFloat(m_StepTime) / FpFloat(1000));
|
||||
m_LastValidStep = m_CurrentStep;
|
||||
} else {
|
||||
m_World.Tick(EMPTY_LOCKSTEP, FpFloat(m_StepTime) / FpFloat(1000));
|
||||
}
|
||||
m_CurrentStep++;
|
||||
}
|
||||
|
||||
void RealTimeSimulation::HandlePacket(const protocol::packets::LockStepsPacket& a_LockSteps) {
|
||||
const auto& steps = a_LockSteps->m_LockSteps;
|
||||
for (std::size_t i = 0; i < LOCKSTEP_BUFFER_SIZE; i++) {
|
||||
m_History[a_LockSteps->m_FirstFrameNumber + i] = steps[i];
|
||||
}
|
||||
FastReplay();
|
||||
}
|
||||
|
||||
void RealTimeSimulation::HandlePacket(const protocol::packets::PredictCommandPacket& a_Predict) {}
|
||||
|
||||
void RealTimeSimulation::FastForward(std::size_t a_Count) {
|
||||
for (std::size_t i = 0; i < a_Count; i++) {
|
||||
Step();
|
||||
}
|
||||
}
|
||||
|
||||
void RealTimeSimulation::FastReplay() {
|
||||
if (m_LastValidStep >= m_CurrentStep)
|
||||
return;
|
||||
|
||||
m_World.ResetSnapshots(m_LastSnapshot, m_LastSnapshot);
|
||||
|
||||
const std::size_t stepCount = m_CurrentStep - m_LastValidStep;
|
||||
m_CurrentStep = m_LastValidStep;
|
||||
|
||||
FastForward(stepCount);
|
||||
}
|
||||
|
||||
} // namespace sim
|
||||
} // namespace td
|
||||
|
||||
Reference in New Issue
Block a user