Update drop-and-fusion-engine.ts

This commit is contained in:
syuilo 2024-01-09 16:30:12 +09:00
parent 14d4ffaa36
commit 17f368e228

View file

@ -45,12 +45,13 @@ export class DropAndFusionGame extends EventEmitter<{
public readonly DROP_INTERVAL = 500; public readonly DROP_INTERVAL = 500;
public readonly PLAYAREA_MARGIN = 25; public readonly PLAYAREA_MARGIN = 25;
private STOCK_MAX = 4; private STOCK_MAX = 4;
private METTER_ENGINE_UPDATE_DELTA = 1000 / 60; // 60fps private TICK_DELTA = 1000 / 60; // 60fps
private loaded = false; private loaded = false;
private frame = 0; private frame = 0;
private engine: Matter.Engine; private engine: Matter.Engine;
private render: Matter.Render; private render: Matter.Render;
private matterEngineUpdateRaf: ReturnType<typeof requestAnimationFrame> | null = null; private tickRaf: ReturnType<typeof requestAnimationFrame> | null = null;
private tickCallbackQueue: { frame: number; callback: () => void; }[] = [];
private overflowCollider: Matter.Body; private overflowCollider: Matter.Body;
private isGameOver = false; private isGameOver = false;
private gameWidth: number; private gameWidth: number;
@ -237,9 +238,12 @@ export class DropAndFusionGame extends EventEmitter<{
Matter.Composite.add(this.engine.world, body); Matter.Composite.add(this.engine.world, body);
// 連鎖してfusionした場合の分かりやすさのため少し間を置いてからfusion対象になるようにする // 連鎖してfusionした場合の分かりやすさのため少し間を置いてからfusion対象になるようにする
window.setTimeout(() => { this.tickCallbackQueue.push({
this.activeBodyIds.push(body.id); frame: this.frame + 100,
}, 100); callback: () => {
this.activeBodyIds.push(body.id);
},
});
const comboBonus = 1 + ((this.combo - 1) / 5); const comboBonus = 1 + ((this.combo - 1) / 5);
const additionalScore = Math.round(currentMono.score * comboBonus); const additionalScore = Math.round(currentMono.score * comboBonus);
@ -271,8 +275,8 @@ export class DropAndFusionGame extends EventEmitter<{
private gameOver() { private gameOver() {
this.isGameOver = true; this.isGameOver = true;
if (this.matterEngineUpdateRaf) window.cancelAnimationFrame(this.matterEngineUpdateRaf); if (this.tickRaf) window.cancelAnimationFrame(this.tickRaf);
this.matterEngineUpdateRaf = null; this.tickRaf = null;
this.emit('gameOver'); this.emit('gameOver');
} }
@ -342,10 +346,13 @@ export class DropAndFusionGame extends EventEmitter<{
this.fusion(bodyA, bodyB); this.fusion(bodyA, bodyB);
} else { } else {
fusionReservedPairs.push({ bodyA, bodyB }); fusionReservedPairs.push({ bodyA, bodyB });
window.setTimeout(() => { this.tickCallbackQueue.push({
fusionReservedPairs = fusionReservedPairs.filter(x => x.bodyA.id !== bodyA.id && x.bodyB.id !== bodyB.id); frame: this.frame + 100,
this.fusion(bodyA, bodyB); callback: () => {
}, 100); fusionReservedPairs = fusionReservedPairs.filter(x => x.bodyA.id !== bodyA.id && x.bodyB.id !== bodyB.id);
this.fusion(bodyA, bodyB);
},
});
} }
} else { } else {
const energy = pairs.collision.depth; const energy = pairs.collision.depth;
@ -371,11 +378,9 @@ export class DropAndFusionGame extends EventEmitter<{
}, 500); }, 500);
if (logs) { if (logs) {
let playingFrame = 0;
const playTick = () => { const playTick = () => {
playingFrame++; this.frame++;
const log = logs.find(x => x.frame === playingFrame - 1); const log = logs.find(x => x.frame === this.frame - 1);
if (log) { if (log) {
switch (log.operation) { switch (log.operation) {
case 'drop': { case 'drop': {
@ -390,8 +395,16 @@ export class DropAndFusionGame extends EventEmitter<{
break; break;
} }
} }
this.tickCallbackQueue = this.tickCallbackQueue.filter(x => {
if (x.frame === this.frame) {
x.callback();
return false;
} else {
return true;
}
});
Matter.Engine.update(this.engine, this.METTER_ENGINE_UPDATE_DELTA); Matter.Engine.update(this.engine, this.TICK_DELTA);
window.requestAnimationFrame(playTick); window.requestAnimationFrame(playTick);
}; };
@ -408,8 +421,16 @@ export class DropAndFusionGame extends EventEmitter<{
private tick() { private tick() {
this.frame++; this.frame++;
Matter.Engine.update(this.engine, this.METTER_ENGINE_UPDATE_DELTA); this.tickCallbackQueue = this.tickCallbackQueue.filter(x => {
this.matterEngineUpdateRaf = window.requestAnimationFrame(this.tick); if (x.frame === this.frame) {
x.callback();
return false;
} else {
return true;
}
});
Matter.Engine.update(this.engine, this.TICK_DELTA);
this.tickRaf = window.requestAnimationFrame(this.tick);
} }
public async load() { public async load() {
@ -506,8 +527,8 @@ export class DropAndFusionGame extends EventEmitter<{
public dispose() { public dispose() {
if (this.comboIntervalId) window.clearInterval(this.comboIntervalId); if (this.comboIntervalId) window.clearInterval(this.comboIntervalId);
if (this.matterEngineUpdateRaf) window.cancelAnimationFrame(this.matterEngineUpdateRaf); if (this.tickRaf) window.cancelAnimationFrame(this.tickRaf);
this.matterEngineUpdateRaf = null; this.tickRaf = null;
Matter.Render.stop(this.render); Matter.Render.stop(this.render);
Matter.World.clear(this.engine.world, false); Matter.World.clear(this.engine.world, false);
Matter.Engine.clear(this.engine); Matter.Engine.clear(this.engine);