mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-03 23:14:13 +00:00 
			
		
		
		
	enhance(drop-and-fusion): リプレイの倍速再生対応
This commit is contained in:
		
							parent
							
								
									138a248a6c
								
							
						
					
					
						commit
						3d9e42efca
					
				
					 2 changed files with 52 additions and 39 deletions
				
			
		| 
						 | 
				
			
			@ -103,7 +103,11 @@ SPDX-License-Identifier: AGPL-3.0-only
 | 
			
		|||
			<div v-if="replaying" style="display: flex;">
 | 
			
		||||
				<div :class="$style.frame" style="flex: 1; margin-right: 10px;">
 | 
			
		||||
					<div :class="$style.frameInner">
 | 
			
		||||
						<MkButton @click="endReplay"><i class="ti ti-player-stop"></i> END REPLAY</MkButton>
 | 
			
		||||
						<div class="_buttonsCenter">
 | 
			
		||||
							<MkButton @click="endReplay"><i class="ti ti-player-stop"></i> END REPLAY</MkButton>
 | 
			
		||||
							<MkButton :primary="replayPlaybackRate === 2" @click="replayPlaybackRate = replayPlaybackRate === 2 ? 1 : 2"><i class="ti ti-player-track-next"></i> x2</MkButton>
 | 
			
		||||
							<MkButton :primary="replayPlaybackRate === 4" @click="replayPlaybackRate = replayPlaybackRate === 4 ? 1 : 4"><i class="ti ti-player-track-next"></i> x4</MkButton>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
			</div>
 | 
			
		||||
| 
						 | 
				
			
			@ -437,10 +441,15 @@ const gameStarted = ref(false);
 | 
			
		|||
const highScore = ref<number | null>(null);
 | 
			
		||||
const showConfig = ref(false);
 | 
			
		||||
const replaying = ref(false);
 | 
			
		||||
const replayPlaybackRate = ref(1);
 | 
			
		||||
const mute = ref(false);
 | 
			
		||||
const bgmVolume = ref(defaultStore.state.dropAndFusion.bgmVolume);
 | 
			
		||||
const sfxVolume = ref(defaultStore.state.dropAndFusion.sfxVolume);
 | 
			
		||||
 | 
			
		||||
watch(replayPlaybackRate, (newValue) => {
 | 
			
		||||
	game.replayPlaybackRate = newValue;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function onClick(ev: MouseEvent) {
 | 
			
		||||
	if (!containerElRect) return;
 | 
			
		||||
	if (replaying.value) return;
 | 
			
		||||
| 
						 | 
				
			
			@ -493,6 +502,7 @@ function end() {
 | 
			
		|||
	game.dispose();
 | 
			
		||||
	isGameOver.value = false;
 | 
			
		||||
	replaying.value = false;
 | 
			
		||||
	replayPlaybackRate.value = 1;
 | 
			
		||||
	currentPick.value = null;
 | 
			
		||||
	dropReady.value = true;
 | 
			
		||||
	stock.value = [];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue