unit interpolation

This commit is contained in:
2025-05-10 12:37:37 +02:00
parent a3a48cad40
commit c1f56c69aa
3 changed files with 85 additions and 28 deletions

View File

@@ -27,12 +27,12 @@ export class GameComponent implements OnInit {
async ngOnInit() {
const initialState: GameState = {
tick: 0,
units: [{ id: 'u1', x: 0, y: 0 }],
commandHistory: []
};
tick: 0,
units: [{ id: 'u1', x: 0, y: 0 }],
commandHistory: [],
};
const json = await fetch('/assets/gameData.json').then(r => r.json());
const json = await fetch('/assets/gameData.json').then((r) => r.json());
this.engine = new SimulationEngine(initialState, GameRules, json);
requestAnimationFrame(this.gameLoop.bind(this));
}
@@ -57,26 +57,64 @@ export class GameComponent implements OnInit {
this.engine.fastForwardToEnd();
}
async reloadGameData() {
const json = await fetch('/assets/gameData.json').then(r => r.json());
this.engine.reinitializeWithNewData(json);
}
issueMove() {
const cmd: Command = {
step: this.engine.currentStep + 1,
type: 'move',
payload: { id: 'u1', dx: 1, dy: 0 }
};
this.engine.issueCommand(cmd);
}
async reloadGameData() {
const json = await fetch('/assets/gameData.json').then((r) => r.json());
this.engine.reinitializeWithNewData(json);
}
issueMove() {
const cmd: Command = {
step: this.engine.currentStep + 1,
type: 'move',
payload: { id: 'u1', dx: 1, dy: 0 },
};
this.engine.issueCommand(cmd);
}
ngAfterViewInit(): void {
this.resizeCanvas();
requestAnimationFrame(this.render);
window.addEventListener('resize', this.resizeCanvas.bind(this));
}
render = (now: number) => {
if (!this.engine) return;
const [prevState, currState] = this.engine.getRenderStates();
// Compute interpolation factor (0..1)
const lastStepTime = this.engine.isRunning ? this.engine.lastStepTime : now;
const t = this.engine.isRunning
? Math.max(Math.min((now - lastStepTime) / this.engine.interval, 1), 0)
: 1; // fully render the last known state
this.renderFrame(prevState, currState, t);
requestAnimationFrame(this.render);
};
renderFrame(prev: GameState, curr: GameState, t: number) {
const ctx = this.canvasRef.nativeElement.getContext('2d');
if (!ctx) return;
const canvas = this.canvasRef.nativeElement;
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < curr.units.length; i++) {
const currUnit = curr.units[i];
const prevUnit =
prev.units.find((u) => u.id === currUnit.id) ?? currUnit;
const x = prevUnit.x + (currUnit.x - prevUnit.x) * t;
const y = prevUnit.y + (currUnit.y - prevUnit.y) * t;
ctx.fillStyle = 'cyan';
ctx.beginPath();
ctx.arc(x * 10, y * 10, 5, 0, Math.PI * 2);
ctx.fill();
}
}
resizeCanvas(): void {
const wrapper = this.wrapperRef.nativeElement;
const canvas = this.canvasRef.nativeElement;