From 4b56d70b2220ed90edaea5e08d37e7e227b5db22 Mon Sep 17 00:00:00 2001 From: congsh <2452821485@qq.com> Date: Wed, 13 May 2026 04:27:27 +0000 Subject: [PATCH] feat: rewrite main.js with config-driven initialization --- src/main.js | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/main.js diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..fa5e55a --- /dev/null +++ b/src/main.js @@ -0,0 +1,128 @@ +// ==================== 游戏入口 ==================== + +import { createInitialState, resetForRebirth } from './engine/state.js'; +import { setCareerConfig } from './engine/careerEngine.js'; +import { setEventConfig } from './engine/eventEngine.js'; +import { setShopConfig } from './engine/shopEngine.js'; +import { startGameLoop, stopGameLoop, setSpeed } from './engine/tickLoop.js'; +import { applyEffect } from './engine/effectApplier.js'; +import { processDeath } from './engine/deathEngine.js'; +import { evaluateCondition } from './engine/conditionEvaluator.js'; +import { initRenderer, renderAll, showDeathScreen, hideChoiceEvent } from './ui/renderer.js'; + +const state = createInitialState(); + +// ==================== 配置加载 ==================== + +async function loadConfigs() { + const [careers, events, shop, identities, talents] = await Promise.all([ + fetch('./src/config/careers.json').then(r => r.json()), + fetch('./src/config/events.json').then(r => r.json()), + fetch('./src/config/shop.json').then(r => r.json()), + fetch('./src/config/identities.json').then(r => r.json()), + fetch('./src/config/talents.json').then(r => r.json()), + ]); + setCareerConfig(careers); + setEventConfig(events); + setShopConfig(shop); + return { careers, events, shop, identities, talents }; +} + +// ==================== 新游戏 ==================== + +function startNewGame(configs) { + resetForRebirth(state); + + // 随机选择可用身份 + const available = configs.identities.identities.filter(id => { + if (!id.unlockConditions || id.unlockConditions.length === 0) return true; + return id.unlockConditions.every(c => evaluateCondition(c, state)); + }); + const identity = available[Math.floor(Math.random() * available.length)]; + state.identity = identity.id; + + if (identity.startingStats) Object.assign(state.stats, identity.startingStats); + if (identity.startingItems) { + for (const itemId of identity.startingItems) { + applyEffect({ type: 'addItem', itemId }, state); + } + } + + // 从已解锁词条池抽取(简化:先不实现) + + startGameLoop(state, configs.careers, configs.events, configs.shop, () => { + renderAll(state, configs.careers, configs.shop); + }); +} + +// ==================== 选择事件处理 ==================== + +function handleChoice(choiceIndex) { + if (!state.currentEvent) return; + const choice = state.currentEvent.choices[choiceIndex]; + if (!choice) return; + if (choice.effects) { + for (const effect of choice.effects) applyEffect(effect, state); + } + state.paused = false; + state.currentEvent = null; + hideChoiceEvent(); +} + +// ==================== UI事件绑定 ==================== + +function bindUIEvents() { + // 速度按钮 + document.querySelectorAll('.speed-btn').forEach(btn => { + btn.addEventListener('click', () => { + const level = parseInt(btn.dataset.speed, 10); + setSpeed(state, level); + }); + }); + + // 暂停按钮 + const pauseBtn = document.getElementById('pause-btn'); + if (pauseBtn) { + pauseBtn.addEventListener('click', () => { + state.paused = !state.paused; + }); + } + + // 选择按钮委托 + const eventChoices = document.getElementById('event-choices'); + if (eventChoices) { + eventChoices.addEventListener('click', (e) => { + const btn = e.target.closest('[data-index]'); + if (!btn) return; + const idx = parseInt(btn.dataset.index, 10); + if (!isNaN(idx)) { + handleChoice(idx); + } + }); + } + + // 重生按钮(死亡界面) + document.addEventListener('click', (e) => { + if (e.target.id === 'rebirth-btn') { + location.reload(); + } + }); +} + +// ==================== 主流程 ==================== + +async function init() { + const configs = await loadConfigs(); + initRenderer(); + bindUIEvents(); + startNewGame(configs); + setInterval(() => { + if (!state.alive && state.deathReason) { + stopGameLoop(); + processDeath(state, configs.careers, configs.talents); + showDeathScreen(state, configs.careers); + } + }, 500); +} + +init().catch(console.error);