enhance(drop-and-fusion): リプレイの倍速再生対応
This commit is contained in:
@@ -44,7 +44,7 @@ export class DropAndFusionGame extends EventEmitter<{
|
||||
gameOver: () => void;
|
||||
}> {
|
||||
private PHYSICS_QUALITY_FACTOR = 16; // 低いほどパフォーマンスが高いがガタガタして安定しなくなる、逆に高すぎても何故か不安定になる
|
||||
private COMBO_INTERVAL = 1000;
|
||||
private COMBO_INTERVAL = 60; // frame
|
||||
public readonly DROP_INTERVAL = 500;
|
||||
public readonly PLAYAREA_MARGIN = 25;
|
||||
private STOCK_MAX = 4;
|
||||
@@ -76,7 +76,7 @@ export class DropAndFusionGame extends EventEmitter<{
|
||||
private latestDroppedBodyId: Matter.Body['id'] | null = null;
|
||||
|
||||
private latestDroppedAt = 0;
|
||||
private latestFusionedAt = 0;
|
||||
private latestFusionedAt = 0; // frame
|
||||
private stock: { id: string; mono: Mono }[] = [];
|
||||
private holding: { id: string; mono: Mono } | null = null;
|
||||
|
||||
@@ -100,6 +100,8 @@ export class DropAndFusionGame extends EventEmitter<{
|
||||
|
||||
private comboIntervalId: number | null = null;
|
||||
|
||||
public replayPlaybackRate = 1;
|
||||
|
||||
constructor(opts: {
|
||||
canvas: HTMLCanvasElement;
|
||||
width: number;
|
||||
@@ -219,13 +221,12 @@ export class DropAndFusionGame extends EventEmitter<{
|
||||
}
|
||||
|
||||
private fusion(bodyA: Matter.Body, bodyB: Matter.Body) {
|
||||
const now = Date.now();
|
||||
if (this.latestFusionedAt > now - this.COMBO_INTERVAL) {
|
||||
if (this.latestFusionedAt > this.frame - this.COMBO_INTERVAL) {
|
||||
this.combo++;
|
||||
} else {
|
||||
this.combo = 1;
|
||||
}
|
||||
this.latestFusionedAt = now;
|
||||
this.latestFusionedAt = this.frame;
|
||||
|
||||
// TODO: 単に位置だけでなくそれぞれの動きベクトルも融合する?
|
||||
const newX = (bodyA.position.x + bodyB.position.x) / 2;
|
||||
@@ -390,44 +391,43 @@ export class DropAndFusionGame extends EventEmitter<{
|
||||
}
|
||||
});
|
||||
|
||||
this.comboIntervalId = window.setInterval(() => {
|
||||
if (this.latestFusionedAt < Date.now() - this.COMBO_INTERVAL) {
|
||||
this.combo = 0;
|
||||
}
|
||||
}, 500);
|
||||
|
||||
if (logs) {
|
||||
const playTick = () => {
|
||||
this.frame++;
|
||||
const log = logs.find(x => x.frame === this.frame - 1);
|
||||
if (log) {
|
||||
switch (log.operation) {
|
||||
case 'drop': {
|
||||
this.drop(log.x);
|
||||
break;
|
||||
}
|
||||
case 'hold': {
|
||||
this.hold();
|
||||
break;
|
||||
}
|
||||
case 'surrender': {
|
||||
this.surrender();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
for (let i = 0; i < this.replayPlaybackRate; i++) {
|
||||
this.frame++;
|
||||
if (this.latestFusionedAt < this.frame - this.COMBO_INTERVAL) {
|
||||
this.combo = 0;
|
||||
}
|
||||
}
|
||||
this.tickCallbackQueue = this.tickCallbackQueue.filter(x => {
|
||||
if (x.frame === this.frame) {
|
||||
x.callback();
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
const log = logs.find(x => x.frame === this.frame - 1);
|
||||
if (log) {
|
||||
switch (log.operation) {
|
||||
case 'drop': {
|
||||
this.drop(log.x);
|
||||
break;
|
||||
}
|
||||
case 'hold': {
|
||||
this.hold();
|
||||
break;
|
||||
}
|
||||
case 'surrender': {
|
||||
this.surrender();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
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.TICK_DELTA);
|
||||
Matter.Engine.update(this.engine, this.TICK_DELTA);
|
||||
}
|
||||
|
||||
if (!this.isGameOver) {
|
||||
this.tickRaf = window.requestAnimationFrame(playTick);
|
||||
@@ -446,6 +446,9 @@ export class DropAndFusionGame extends EventEmitter<{
|
||||
|
||||
private tick() {
|
||||
this.frame++;
|
||||
if (this.latestFusionedAt < this.frame - this.COMBO_INTERVAL) {
|
||||
this.combo = 0;
|
||||
}
|
||||
this.tickCallbackQueue = this.tickCallbackQueue.filter(x => {
|
||||
if (x.frame === this.frame) {
|
||||
x.callback();
|
||||
|
Reference in New Issue
Block a user