refactor: inline event registration at setup level, remove registerEvents duplication across entry points
This commit is contained in:
@@ -15,105 +15,112 @@ export function useGameEngine(videoEls: () => [HTMLVideoElement | null, HTMLVide
|
||||
;(window as any).__store = store
|
||||
}
|
||||
|
||||
engine.setChapterUnlockHandler(async (chapterId) => {
|
||||
await saveSystem.unlockChapter(chapterId)
|
||||
store.addUnlockedChapter(chapterId)
|
||||
})
|
||||
|
||||
engine.on('sceneChange', (scene) => {
|
||||
store.setScene(scene)
|
||||
store.clearChoices()
|
||||
store.clearTimer()
|
||||
store.clearHotspots()
|
||||
store.setIsImageScene(scene.type === 'image')
|
||||
saveGame(0)
|
||||
})
|
||||
|
||||
engine.on('choiceRequest', (choiceList) => {
|
||||
store.setChoices(choiceList)
|
||||
})
|
||||
|
||||
engine.on('choiceTimer', (timerState) => {
|
||||
store.setTimer(timerState.total, timerState.remaining)
|
||||
})
|
||||
|
||||
engine.on('choiceTimeout', () => {
|
||||
store.clearChoices()
|
||||
store.clearTimer()
|
||||
})
|
||||
|
||||
engine.on('hotspotRequest', (list) => {
|
||||
store.setHotspots(list)
|
||||
})
|
||||
|
||||
engine.on('hotspotUpdate', (list) => {
|
||||
store.setHotspots(list)
|
||||
})
|
||||
|
||||
engine.on('videoEnd', () => {
|
||||
try {
|
||||
const video = engine.videoManager.getActiveVideoElement()
|
||||
if (video && video.readyState >= 2) {
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = 320
|
||||
canvas.height = 180
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (ctx) {
|
||||
ctx.drawImage(video, 0, 0, 320, 180)
|
||||
lastThumbnail = canvas.toDataURL('image/jpeg', 0.6)
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
})
|
||||
|
||||
engine.on('gameEnd', () => {
|
||||
store.setGameEnded(true)
|
||||
engine.choiceSystem.stop()
|
||||
})
|
||||
|
||||
engine.on('qteTrigger', (qte) => {
|
||||
store.showQTE(qte)
|
||||
})
|
||||
|
||||
engine.on('qteTimer', ({ remaining }) => {
|
||||
store.updateQTE(remaining)
|
||||
})
|
||||
|
||||
engine.on('qteResult', ({ success }) => {
|
||||
store.resolveQTE(success)
|
||||
})
|
||||
|
||||
engine.videoManager.onTimeUpdate((t: number) => {
|
||||
store.setVideoTime(t)
|
||||
})
|
||||
|
||||
async function loadGame(dataUrl: string) {
|
||||
const resp = await fetch(dataUrl)
|
||||
const data: GameData = await resp.json()
|
||||
engine.sceneManager.load(data)
|
||||
engine.stateManager.init(data.variables)
|
||||
store.setChapters(data.chapters || [])
|
||||
|
||||
const unlocked = await saveSystem.getUnlockedChapters()
|
||||
store.setUnlockedChapters(unlocked)
|
||||
}
|
||||
|
||||
function registerEvents() {
|
||||
engine.setChapterUnlockHandler(async (chapterId) => {
|
||||
await saveSystem.unlockChapter(chapterId)
|
||||
store.addUnlockedChapter(chapterId)
|
||||
})
|
||||
|
||||
engine.on('sceneChange', (scene) => {
|
||||
store.setScene(scene)
|
||||
store.clearChoices()
|
||||
store.clearTimer()
|
||||
store.clearHotspots()
|
||||
store.setIsImageScene(scene.type === 'image')
|
||||
saveGame(0)
|
||||
})
|
||||
|
||||
engine.on('choiceRequest', (choiceList) => {
|
||||
store.setChoices(choiceList)
|
||||
})
|
||||
|
||||
engine.on('choiceTimer', (timerState) => {
|
||||
store.setTimer(timerState.total, timerState.remaining)
|
||||
})
|
||||
|
||||
engine.on('choiceTimeout', () => {
|
||||
store.clearChoices()
|
||||
store.clearTimer()
|
||||
})
|
||||
|
||||
engine.on('hotspotRequest', (list) => {
|
||||
store.setHotspots(list)
|
||||
})
|
||||
|
||||
engine.on('hotspotUpdate', (list) => {
|
||||
store.setHotspots(list)
|
||||
})
|
||||
|
||||
engine.on('videoEnd', () => {
|
||||
try {
|
||||
const video = engine.videoManager.getActiveVideoElement()
|
||||
if (video && video.readyState >= 2) {
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = 320
|
||||
canvas.height = 180
|
||||
const ctx = canvas.getContext('2d')
|
||||
if (ctx) {
|
||||
ctx.drawImage(video, 0, 0, 320, 180)
|
||||
lastThumbnail = canvas.toDataURL('image/jpeg', 0.6)
|
||||
}
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
})
|
||||
|
||||
engine.on('gameEnd', () => {
|
||||
store.setGameEnded(true)
|
||||
engine.choiceSystem.stop()
|
||||
})
|
||||
|
||||
engine.on('qteTrigger', (qte) => {
|
||||
store.showQTE(qte)
|
||||
})
|
||||
|
||||
engine.on('qteTimer', ({ remaining }) => {
|
||||
store.updateQTE(remaining)
|
||||
})
|
||||
|
||||
engine.on('qteResult', ({ success }) => {
|
||||
store.resolveQTE(success)
|
||||
})
|
||||
|
||||
engine.videoManager.onTimeUpdate((t: number) => {
|
||||
store.setVideoTime(t)
|
||||
})
|
||||
function ensureVideo() {
|
||||
const [elA, elB] = videoEls()
|
||||
if (elA && elB) engine.videoManager.attach(elA, elB)
|
||||
}
|
||||
|
||||
function start() {
|
||||
const [elA, elB] = videoEls()
|
||||
if (elA && elB) engine.videoManager.attach(elA, elB)
|
||||
registerEvents()
|
||||
ensureVideo()
|
||||
engine.start()
|
||||
}
|
||||
|
||||
async function resumeAutoSave(): Promise<boolean> {
|
||||
const [elA, elB] = videoEls()
|
||||
if (elA && elB) engine.videoManager.attach(elA, elB)
|
||||
registerEvents()
|
||||
ensureVideo()
|
||||
store.setGameEnded(false)
|
||||
return await loadGameFromSlot(0)
|
||||
}
|
||||
|
||||
function startChapter(chapterId: string) {
|
||||
ensureVideo()
|
||||
store.setGameEnded(false)
|
||||
engine.startChapter(chapterId)
|
||||
}
|
||||
|
||||
function makeChoice(index: number) {
|
||||
const scene = store.currentScene
|
||||
if (!scene?.choices) return
|
||||
@@ -131,17 +138,9 @@ export function useGameEngine(videoEls: () => [HTMLVideoElement | null, HTMLVide
|
||||
}
|
||||
}
|
||||
|
||||
function startChapter(chapterId: string) {
|
||||
const [elA, elB] = videoEls()
|
||||
if (elA && elB) engine.videoManager.attach(elA, elB)
|
||||
store.setGameEnded(false)
|
||||
engine.startChapter(chapterId)
|
||||
}
|
||||
|
||||
async function saveGame(slot: number) {
|
||||
const state = engine.stateManager
|
||||
const currentScene = store.currentScene
|
||||
|
||||
await saveSystem.save(slot, {
|
||||
timestamp: Date.now(),
|
||||
currentScene: currentScene?.id ?? '',
|
||||
@@ -156,7 +155,6 @@ export function useGameEngine(videoEls: () => [HTMLVideoElement | null, HTMLVide
|
||||
async function loadGameFromSlot(slot: number): Promise<boolean> {
|
||||
const data = await saveSystem.load(slot)
|
||||
if (!data) return false
|
||||
|
||||
store.setGameEnded(false)
|
||||
engine.resumeScene(data.currentScene, {
|
||||
variables: data.variables,
|
||||
@@ -179,6 +177,17 @@ export function useGameEngine(videoEls: () => [HTMLVideoElement | null, HTMLVide
|
||||
destroy()
|
||||
})
|
||||
|
||||
return { loadGame, start, resumeAutoSave, makeChoice, clickHotspot, startChapter,
|
||||
saveGame, loadGameFromSlot, refreshSaves, engine, saveSystem }
|
||||
return {
|
||||
loadGame,
|
||||
start,
|
||||
resumeAutoSave,
|
||||
makeChoice,
|
||||
clickHotspot,
|
||||
startChapter,
|
||||
saveGame,
|
||||
loadGameFromSlot,
|
||||
refreshSaves,
|
||||
engine,
|
||||
saveSystem,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user