| name | game-loop |
| description | Server-side game loop implementation with fixed timestep, physics simulation, and tick rate optimization |
| sasmp_version | 1.3.0 |
| version | 2.0.0 |
| bonded_agent | 05-game-loop-developer |
| bond_type | PRIMARY_BOND |
| parameters | [object Object] |
| retry_config | [object Object] |
| observability | [object Object] |
Server Game Loop
Implement deterministic game loops with fixed timestep for consistent gameplay.
Fixed Timestep Loop
class GameLoop {
constructor(tickRate = 60) {
this.tickRate = tickRate;
this.tickMs = 1000 / tickRate;
this.tick = 0;
this.running = false;
}
start() {
this.running = true;
this.lastTime = process.hrtime.bigint();
this.accumulator = 0n;
this.loop();
}
loop() {
if (!this.running) return;
const now = process.hrtime.bigint();
const deltaNs = now - this.lastTime;
this.lastTime = now;
this.accumulator += deltaNs;
const tickNs = BigInt(Math.round(this.tickMs * 1_000_000));
let ticksProcessed = 0;
while (this.accumulator >= tickNs && ticksProcessed < 5) {
this.update(this.tickMs);
this.tick++;
this.accumulator -= tickNs;
ticksProcessed++;
}
// Prevent spiral of death
if (ticksProcessed === 5) {
this.accumulator = 0n;
console.warn('Tick catchup limit reached');
}
const sleepMs = Math.max(1, this.tickMs - Number(this.accumulator) / 1_000_000);
setTimeout(() => this.loop(), sleepMs);
}
update(dt) {
this.processInputs();
this.updatePhysics(dt);
this.updateEntities(dt);
this.checkGameState();
this.broadcastState();
}
}
Tick Rate Guide
| Game Type |
Rate |
Budget |
Rationale |
| FPS |
60-128 Hz |
8-16ms |
Hit precision |
| MOBA |
30-60 Hz |
16-33ms |
Balance |
| BR |
20-30 Hz |
33-50ms |
Scale |
| MMO |
10-20 Hz |
50-100ms |
Massive |
Performance Monitoring
class TickMetrics {
constructor(size = 100) {
this.samples = [];
this.size = size;
}
record(ms) {
this.samples.push(ms);
if (this.samples.length > this.size) this.samples.shift();
}
stats() {
const sorted = [...this.samples].sort((a, b) => a - b);
return {
avg: this.samples.reduce((a, b) => a + b, 0) / this.samples.length,
p50: sorted[Math.floor(sorted.length * 0.5)],
p99: sorted[Math.floor(sorted.length * 0.99)]
};
}
}
Troubleshooting
Common Failure Modes
| Error |
Root Cause |
Solution |
| Tick spikes |
GC pauses |
Object pooling |
| Drift |
Float precision |
Fixed-point math |
| Explosion |
Large dt |
Cap dt value |
| Stuttering |
Variable tick |
Fixed timestep |
Debug Checklist
const stats = metrics.stats();
console.log(`Avg: ${stats.avg.toFixed(2)}ms`);
console.log(`P99: ${stats.p99.toFixed(2)}ms`);
console.log(`Budget: ${(stats.avg / tickBudget * 100).toFixed(1)}%`);
Unit Test Template
describe('GameLoop', () => {
test('maintains tick rate', async () => {
const loop = new GameLoop(60);
const ticks = [];
loop.update = () => ticks.push(Date.now());
loop.start();
await new Promise(r => setTimeout(r, 100));
loop.running = false;
expect(ticks.length).toBeGreaterThan(4);
});
});
Resources
assets/ - Loop templates
references/ - Optimization guides