implement simulation shell

This commit is contained in:
2026-04-19 15:49:18 +02:00
parent 41fd2a83ee
commit ffe69f08b5
8 changed files with 275 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
SET(HDRS
${HDRS}
${CMAKE_CURRENT_SOURCE_DIR}/Simulation.h
${CMAKE_CURRENT_SOURCE_DIR}/TickDriver.h
PARENT_SCOPE
)
SET(SRCS
${SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/Simulation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/TickDriver.cpp
PARENT_SCOPE
)
set(LIB_INCLUDE_PATH
${LIB_INCLUDE_PATH}
${CMAKE_CURRENT_SOURCE_DIR}
PARENT_SCOPE
)

View File

@@ -0,0 +1,38 @@
#include "Simulation.h"
Simulation::Simulation(const GameConfig& config, unsigned int seed)
: m_config(config)
, m_rng(seed)
, m_currentTick(0)
, m_nextId(1)
{
}
void Simulation::tick()
{
++m_currentTick;
}
std::vector<FireEvent> Simulation::drainFireEvents()
{
std::vector<FireEvent> result;
result.swap(m_fireEvents);
return result;
}
std::vector<BlueprintDropEvent> Simulation::drainBlueprintDropEvents()
{
std::vector<BlueprintDropEvent> result;
result.swap(m_blueprintDropEvents);
return result;
}
Tick Simulation::currentTick() const
{
return m_currentTick;
}
EntityId Simulation::allocateId()
{
return m_nextId++;
}

41
src/lib/sim/Simulation.h Normal file
View File

@@ -0,0 +1,41 @@
#pragma once
#include <random>
#include <vector>
#include "EntityId.h"
#include "FireEvent.h"
#include "BlueprintDropEvent.h"
#include "GameConfig.h"
#include "Tick.h"
class Simulation
{
public:
explicit Simulation(const GameConfig& config, unsigned int seed = 0);
// Advances the simulation by one tick. Tick order per architecture.md §Tick Order.
// Currently a stub; subsystems are plugged in across Steps 3-7.
void tick();
// Returns all fire events accumulated since the last drain, clearing the
// internal queue. Call once per rendered frame (REQ-SHP-FIRING-BEAM).
std::vector<FireEvent> drainFireEvents();
// Returns all blueprint drop events since the last drain.
std::vector<BlueprintDropEvent> drainBlueprintDropEvents();
Tick currentTick() const;
private:
EntityId allocateId(); // Strictly increasing; never returns kInvalidEntityId.
const GameConfig& m_config;
std::mt19937 m_rng;
Tick m_currentTick;
EntityId m_nextId; // starts at 1; 0 is kInvalidEntityId.
std::vector<FireEvent> m_fireEvents;
std::vector<BlueprintDropEvent> m_blueprintDropEvents;
};

View File

@@ -0,0 +1,21 @@
#include "TickDriver.h"
#include "Tick.h"
int TickDriver::advance(double elapsedWallMs, double gameSpeedMultiplier)
{
m_accumulatorMs += elapsedWallMs * gameSpeedMultiplier;
int ticks = 0;
while (m_accumulatorMs >= kTickDurationMs)
{
m_accumulatorMs -= kTickDurationMs;
++ticks;
}
return ticks;
}
void TickDriver::reset()
{
m_accumulatorMs = 0.0;
}

21
src/lib/sim/TickDriver.h Normal file
View File

@@ -0,0 +1,21 @@
#pragma once
// Accumulator-based fixed-timestep driver. Decouples wall-clock render rate
// from the 30 Hz simulation tick rate. See architecture.md §Render Loop.
class TickDriver
{
public:
TickDriver() = default;
// Adds elapsedWallMs * gameSpeedMultiplier to the accumulator and returns
// how many simulation ticks should be stepped this frame. The remainder
// stays in the accumulator for the next call.
// A multiplier of 0.0 freezes accumulation (pause).
// Valid multipliers per REQ-UI-SPEED: 0, 0.5, 1, 2, 4.
int advance(double elapsedWallMs, double gameSpeedMultiplier);
void reset();
private:
double m_accumulatorMs = 0.0;
};