feat: P1 core - seamless video switching, conditional branches, save/load

- VideoManager: A/B dual-buffered video with crossfade transitions and candidate preloading
- Engine: condition-based choice filtering, ChoiceSystem timer, resumeScene for save/load
- SceneManager: getCandidateUrls for preloading next scenes
- SaveSystem: Dexie.js IndexedDB multi-slot save/load
- ChoiceSystem: timed choices with countdown and auto-default on timeout
- GamePlayer: dual video elements with crossfade CSS
- ChoicePanel: timer progress bar and countdown text
- SaveLoadMenu: save/load UI component
- App.vue: menu trigger, dual video refs, save/load integration
- gameStore: timer state, saves list
- demo.json: conditional choice example (secret ending, requires trust >= 80)
- ROADMAP: mark P1 as completed
This commit is contained in:
2026-06-07 16:48:52 +08:00
parent 42181fe185
commit 937e45c203
16 changed files with 763 additions and 71 deletions

View File

@@ -2,10 +2,19 @@ import { defineStore } from 'pinia'
import { ref, shallowRef } from 'vue'
import type { SceneNode, Choice } from '@engine/types'
export interface SlotInfo {
slot: number
timestamp: number
sceneLabel: string
}
export const useGameStore = defineStore('game', () => {
const currentScene = shallowRef<SceneNode | null>(null)
const choices = ref<Choice[]>([])
const gameEnded = ref(false)
const timerTotal = ref(0)
const timerRemaining = ref(0)
const saves = ref<SlotInfo[]>([])
function setScene(scene: SceneNode) {
currentScene.value = scene
@@ -23,5 +32,23 @@ export const useGameStore = defineStore('game', () => {
gameEnded.value = val
}
return { currentScene, choices, gameEnded, setScene, setChoices, clearChoices, setGameEnded }
function setTimer(total: number, remaining: number) {
timerTotal.value = total
timerRemaining.value = remaining
}
function clearTimer() {
timerTotal.value = 0
timerRemaining.value = 0
}
function setSaves(list: SlotInfo[]) {
saves.value = list
}
return {
currentScene, choices, gameEnded, timerTotal, timerRemaining, saves,
setScene, setChoices, clearChoices, setGameEnded,
setTimer, clearTimer, setSaves,
}
})