|
|
@ -7,6 +7,7 @@ import { Container, Graphics, Text, TextStyle, type Ticker } from "pixi.js"; |
|
|
|
|
|
|
|
|
const NODE_RADIUS = 18; |
|
|
const NODE_RADIUS = 18; |
|
|
const NODE_GAP = 58; |
|
|
const NODE_GAP = 58; |
|
|
|
|
|
const END_ACTION_COOLDOWN_MS = 250; |
|
|
|
|
|
|
|
|
type ChaseModelLike = Pick< |
|
|
type ChaseModelLike = Pick< |
|
|
ChaseGameModel, |
|
|
ChaseGameModel, |
|
|
@ -52,6 +53,7 @@ export default class ChaseScene extends BaseScene { |
|
|
private inputAttached = false; |
|
|
private inputAttached = false; |
|
|
private unsubscribeStageChange?: () => void; |
|
|
private unsubscribeStageChange?: () => void; |
|
|
private endActionLocked = false; |
|
|
private endActionLocked = false; |
|
|
|
|
|
private lastEndActionAt = 0; |
|
|
|
|
|
|
|
|
constructor(options: ChaseSceneOptions = {}) { |
|
|
constructor(options: ChaseSceneOptions = {}) { |
|
|
super("chase", SceneType.Normal); |
|
|
super("chase", SceneType.Normal); |
|
|
@ -223,30 +225,42 @@ export default class ChaseScene extends BaseScene { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private handleRetryClick(): void { |
|
|
private handleRetryClick(): void { |
|
|
if (!this.model || this.endActionLocked) { |
|
|
if (!this.model || this.endActionLocked || !this.canRunEndAction()) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
this.endActionLocked = true; |
|
|
this.endActionLocked = true; |
|
|
this.model.retryRound(); |
|
|
try { |
|
|
this.refreshView(); |
|
|
this.model.retryRound(); |
|
|
|
|
|
this.refreshView(); |
|
|
|
|
|
} finally { |
|
|
|
|
|
this.endActionLocked = false; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private handleNewGameClick(): void { |
|
|
private handleNewGameClick(): void { |
|
|
if (!this.model || this.endActionLocked) { |
|
|
if (!this.model || this.endActionLocked || !this.canRunEndAction()) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
this.endActionLocked = true; |
|
|
this.endActionLocked = true; |
|
|
this.resetSetup(); |
|
|
try { |
|
|
this.startGame(); |
|
|
this.resetSetup(); |
|
|
|
|
|
this.startGame(); |
|
|
|
|
|
} finally { |
|
|
|
|
|
this.endActionLocked = false; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private handleRestartClick(): void { |
|
|
private handleRestartClick(): void { |
|
|
if (!this.model || this.endActionLocked) { |
|
|
if (!this.model || this.endActionLocked || !this.canRunEndAction()) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
this.endActionLocked = true; |
|
|
this.endActionLocked = true; |
|
|
this.resetSetup(); |
|
|
try { |
|
|
this.startGame(); |
|
|
this.resetSetup(); |
|
|
|
|
|
this.startGame(); |
|
|
|
|
|
} finally { |
|
|
|
|
|
this.endActionLocked = false; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
private buildSetupControls(): void { |
|
|
private buildSetupControls(): void { |
|
|
@ -457,4 +471,13 @@ export default class ChaseScene extends BaseScene { |
|
|
this.retryButton.visible = true; |
|
|
this.retryButton.visible = true; |
|
|
this.newGameButton.visible = true; |
|
|
this.newGameButton.visible = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private canRunEndAction(): boolean { |
|
|
|
|
|
const now = Date.now(); |
|
|
|
|
|
if (now - this.lastEndActionAt < END_ACTION_COOLDOWN_MS) { |
|
|
|
|
|
return false; |
|
|
|
|
|
} |
|
|
|
|
|
this.lastEndActionAt = now; |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|