(globalThis.TURBOPACK || (globalThis.TURBOPACK = [])).push([typeof document === "object" ? document.currentScript : undefined, "[project]/src/lib/game/cruise.ts [app-client] (ecmascript)", ((__turbopack_context__) => { "use strict"; // 回响星核 / Echo Nexus — 深空巡航(v0.8 Canvas 2D 实时玩法) // 一个自包含的"实时操作"玩法模块:操控飞船穿越陨石带、虚空风暴, // 收集晶体碎片/洞见光球/信标,最终抵达星门通关。奖励同步到主游戏。 // v0.8 新增:BOSS 战(每 5 关)/ 飞船射击 / 道具掉落 / 事件选择节点。 // 独立 localStorage(echo-nexus-cruise-v1),不污染 GameState schema。 // ============================================================ // 类型定义 // ============================================================ /** 游戏阶段 */ __turbopack_context__.s([ "CRUISE_CONFIG", ()=>CRUISE_CONFIG, "UPGRADE_POOL", ()=>UPGRADE_POOL, "applyUpgradeCard", ()=>applyUpgradeCard, "burstParticles", ()=>burstParticles, "computeRewards", ()=>computeRewards, "cruiseSeed", ()=>cruiseSeed, "defaultUpgrades", ()=>defaultUpgrades, "generateLevel", ()=>generateLevel, "loadCruiseStats", ()=>loadCruiseStats, "recordRun", ()=>recordRun, "resetCruiseStats", ()=>resetCruiseStats, "rollUpgradeChoices", ()=>rollUpgradeChoices, "saveCruiseStats", ()=>saveCruiseStats, "shootShip", ()=>shootShip, "updateCruise", ()=>updateCruise ]); const CRUISE_CONFIG = { /** 飞船最大速度(px/s) */ shipMaxSpeed: 280, /** 飞船加速度(px/s²) */ shipAccel: 900, /** 飞船摩擦系数(每秒衰减比例) */ shipFriction: 0.88, /** 飞船半径 */ shipRadius: 14, /** 护盾上限 */ shieldMax: 100, /** 护盾恢复速率(/s,仅在未受击时) */ shieldRegen: 2, /** 能量上限 */ energyMax: 100, /** 能量恢复速率(/s) */ energyRegen: 8, /** 收集物吸引半径 */ attractRadius: 90, /** 收集物吸入半径(实际收集) */ collectRadius: 22, /** 陨石基础伤害 */ asteroidBaseDamage: 18, /** 风暴持续伤害(/s) */ stormDps: 12, /** 受击后无敌时间(ms) */ invulnMs: 600, /** 屏幕震动时长(ms) */ shakeMs: 280, /** 屏幕震动强度 */ shakeIntensity: 14, /** 粒子上限 */ maxParticles: 200, /** 子弹粒子上限 */ maxBullets: 80, /** 道具上限 */ maxPowerups: 12, /** 离屏剔除余量(px) */ cullMargin: 100, /** 基础关卡时长(秒) */ baseDuration: 60, /** 每关增加时长(秒) */ durationPerLevel: 3, /** 关卡时长上限(秒) */ maxDuration: 90, /** BOSS 关卡时长(秒,更长) */ bossDuration: 120, /** 视差星空层数 */ parallaxLayers: 3, /** 最大关卡(用于 stats 显示) */ maxLevel: 99, // ---- 射击 ---- /** 子弹速度(px/s) */ bulletSpeed: 540, /** 子弹伤害(飞船) */ bulletDamage: 8, /** 每发消耗能量 */ bulletEnergyCost: 5, /** 射击冷却(ms) */ shootCooldownMs: 150, /** 子弹生命(秒) */ bulletLife: 1.4, /** 子弹半径 */ bulletRadius: 4, // ---- BOSS ---- /** BOSS 基础 HP */ bossBaseHp: 100, /** 每关 HP 增量 */ bossHpPerLevel: 20, /** BOSS 半径 */ bossRadius: 70, /** BOSS 子弹伤害 */ bossBulletDamage: 14, /** BOSS 直射间隔(秒) */ bossDirectInterval: 1.5, /** BOSS 散射间隔(秒) */ bossScatterInterval: 2.2, /** BOSS 追踪弹间隔(秒) */ bossHomingInterval: 2.0, /** BOSS 召唤间隔(秒) */ bossSummonInterval: 4.5, /** BOSS 漂移速度 */ bossDriftSpeed: 18, /** BOSS 接触伤害 */ bossContactDamage: 22, // ---- 道具 ---- /** 道具拾取半径 */ powerupPickupRadius: 26, /** 道具吸引半径(基础,受 magnet buff 加成) */ powerupAttractRadius: 120, /** BOSS 战掉落物寿命(秒) */ powerupLifeBoss: 18, /** 普通关卡掉落物寿命(秒) */ powerupLifeNormal: 10, // ---- Buff 时长(秒) ---- buffRapidDuration: 8, buffOverdriveDuration: 8, buffMagnetDuration: 6 }; const UPGRADE_POOL = [ { id: "speed", title: "速度 +12%", desc: "飞船最大速度提升", color: "#34d399", icon: "Wind" }, { id: "accel", title: "加速度 +15%", desc: "更灵活的转向响应", color: "#34d399", icon: "Gauge" }, { id: "friction", title: "摩擦优化 +5%", desc: "惯性更小,转向更利落", color: "#34d399", icon: "Feather" }, { id: "shield_max", title: "护盾上限 +25", desc: "最高护盾值提升", color: "#34d399", icon: "Shield" }, { id: "shield_regen", title: "护盾恢复 +50%", desc: "未受击时护盾回血更快", color: "#34d399", icon: "HeartPulse" }, { id: "energy_max", title: "能量上限 +25", desc: "更多射击储备", color: "#fbbf24", icon: "Battery" }, { id: "energy_regen", title: "能量恢复 +30%", desc: "能量回充加速", color: "#fbbf24", icon: "Zap" }, { id: "firepower", title: "火力 +25%", desc: "每发子弹伤害更高", color: "#fb7185", icon: "Flame" }, { id: "fire_rate", title: "射速 +20%", desc: "射击间隔更短", color: "#fb7185", icon: "Timer" }, { id: "double_shot", title: "双发", desc: "每次射击发射 2 发(仅一次)", color: "#e879f9", icon: "Split" }, { id: "attract_radius", title: "吸引半径 +40%", desc: "更远距离吸取收集物", color: "#e879f9", icon: "Magnet" }, { id: "collect_radius", title: "收集半径 +50%", desc: "更易拾取道具与晶体", color: "#e879f9", icon: "Circle" }, { id: "invuln_time", title: "无敌时间 +200ms", desc: "受击后更多喘息", color: "#34d399", icon: "ShieldCheck" }, { id: "damage_reduce", title: "受击伤害 -20%", desc: "减少承受的伤害", color: "#34d399", icon: "ShieldHalf" }, { id: "boss_bonus", title: "BOSS 战金币 +50%", desc: "击败 BOSS 奖励翻倍加成", color: "#fbbf24", icon: "Crown" }, { id: "normal_score", title: "普通关卡分数 +30%", desc: "通关得分提升", color: "#fbbf24", icon: "Star" }, { id: "start_shield", title: "起始护盾 +20", desc: "每局开局更高护盾", color: "#34d399", icon: "ShieldPlus" }, { id: "start_energy", title: "起始能量 +20", desc: "每局开局更多能量", color: "#fbbf24", icon: "BatteryCharging" } ]; function defaultUpgrades() { return { speedMult: 1, accelMult: 1, frictionBonus: 0, shieldMaxBonus: 0, shieldRegenMult: 1, energyMaxBonus: 0, energyRegenMult: 1, firepowerMult: 1, fireRateMult: 1, doubleShot: false, attractRadiusMult: 1, collectRadiusMult: 1, invulnBonusMs: 0, damageReduceMult: 1, bossBonusMult: 1, normalScoreMult: 1, startShieldBonus: 0, startEnergyBonus: 0 }; } function applyUpgradeCard(upgrades, card) { switch(card.id){ case "speed": upgrades.speedMult *= 1.12; break; case "accel": upgrades.accelMult *= 1.15; break; case "friction": // 摩擦优化 = 减少 friction 衰减,用正值表示优化程度 upgrades.frictionBonus = Math.min(0.2, upgrades.frictionBonus + 0.05); break; case "shield_max": upgrades.shieldMaxBonus += 25; break; case "shield_regen": upgrades.shieldRegenMult *= 1.5; break; case "energy_max": upgrades.energyMaxBonus += 25; break; case "energy_regen": upgrades.energyRegenMult *= 1.3; break; case "firepower": upgrades.firepowerMult *= 1.25; break; case "fire_rate": upgrades.fireRateMult *= 0.8; // 间隔更短 = 更快 break; case "double_shot": upgrades.doubleShot = true; break; case "attract_radius": upgrades.attractRadiusMult *= 1.4; break; case "collect_radius": upgrades.collectRadiusMult *= 1.5; break; case "invuln_time": upgrades.invulnBonusMs += 200; break; case "damage_reduce": upgrades.damageReduceMult *= 0.8; break; case "boss_bonus": upgrades.bossBonusMult *= 1.5; break; case "normal_score": upgrades.normalScoreMult *= 1.3; break; case "start_shield": upgrades.startShieldBonus += 20; break; case "start_energy": upgrades.startEnergyBonus += 20; break; } } function rollUpgradeChoices(count = 3, exclude = []) { const pool = UPGRADE_POOL.filter((c)=>!exclude.includes(c.id)); const shuffled = [ ...pool ].sort(()=>Math.random() - 0.5); return shuffled.slice(0, Math.min(count, shuffled.length)); } // ============================================================ // 随机数(mulberry32,与 beacon 模块风格一致) // ============================================================ function mulberry32(seed) { let a = seed >>> 0; return function() { a |= 0; a = a + 0x6d2b79f5 | 0; let t = a; t = Math.imul(t ^ t >>> 15, t | 1); t ^= t + Math.imul(t ^ t >>> 7, t | 61); return ((t ^ t >>> 14) >>> 0) / 4294967296; }; } /** FNV-1a 哈希(用于种子生成) */ function fnv1a(str) { let hash = 0x811c9dc5; for(let i = 0; i < str.length; i++){ hash ^= str.charCodeAt(i); hash = Math.imul(hash, 0x01000193); } return hash >>> 0; } function cruiseSeed(level, salt = Date.now()) { return fnv1a(`cruise-l${level}-s${salt}`); } // ============================================================ // 工具:根据 upgrades 计算实时数值 // ============================================================ function effectiveShieldMax(state) { return CRUISE_CONFIG.shieldMax + state.upgrades.shieldMaxBonus; } function effectiveEnergyMax(state) { return CRUISE_CONFIG.energyMax + state.upgrades.energyMaxBonus; } function effectiveShipMaxSpeed(state) { let mult = state.upgrades.speedMult; // overdrive buff 期间 ×1.5 if (state.activeBuffs.some((b)=>b.type === "overdrive")) mult *= 1.5; return CRUISE_CONFIG.shipMaxSpeed * mult; } function effectiveShipAccel(state) { return CRUISE_CONFIG.shipAccel * state.upgrades.accelMult; } function effectiveFriction(state) { // 摩擦优化让 friction 衰减更慢(更接近 1) return Math.min(0.98, CRUISE_CONFIG.shipFriction + state.upgrades.frictionBonus); } function effectiveAttractRadius(state) { let mult = state.upgrades.attractRadiusMult; // magnet buff 期间 ×3 if (state.activeBuffs.some((b)=>b.type === "magnet")) mult *= 3; return CRUISE_CONFIG.attractRadius * mult; } function effectiveCollectRadius(state) { return CRUISE_CONFIG.collectRadius * state.upgrades.collectRadiusMult; } function effectiveShootCooldownMs(state) { let mult = state.upgrades.fireRateMult; // rapid buff 期间 ×0.5 if (state.activeBuffs.some((b)=>b.type === "rapid")) mult *= 0.5; return CRUISE_CONFIG.shootCooldownMs * mult; } function effectiveBulletDamage(state) { return CRUISE_CONFIG.bulletDamage * state.upgrades.firepowerMult; } function effectiveInvulnMs(state) { return CRUISE_CONFIG.invulnMs + state.upgrades.invulnBonusMs; } function generateLevel(level, seed, worldWidth, worldHeight, upgrades = defaultUpgrades(), appliedUpgrades = []) { const rng = mulberry32(seed); const W = worldWidth; const H = worldHeight; let nextId = 1; const isBossLevel = level > 0 && level % 5 === 0; // 飞船:底部中央,起始护盾/能量受 upgrades 加成 const startShield = Math.min(CRUISE_CONFIG.shieldMax + upgrades.shieldMaxBonus, CRUISE_CONFIG.shieldMax + upgrades.shieldMaxBonus + upgrades.startShieldBonus); const startEnergy = Math.min(CRUISE_CONFIG.energyMax + upgrades.energyMaxBonus, CRUISE_CONFIG.energyMax + upgrades.energyMaxBonus + upgrades.startEnergyBonus); const ship = { id: nextId++, type: "ship", x: W / 2, y: H - 80, vx: 0, vy: 0, heading: -Math.PI / 2, shield: startShield, energy: startEnergy, radius: CRUISE_CONFIG.shipRadius, thrust: 0 }; const entities = []; let boss = null; let crystalCount = 0; let insightCount = 0; let beaconCount = 0; let durationSec; if (isBossLevel) { // ---- BOSS 关卡:只生成 BOSS + 少量环境装饰(无星门) ---- const bossHp = CRUISE_CONFIG.bossBaseHp + level * CRUISE_CONFIG.bossHpPerLevel; boss = { id: nextId++, type: "boss", x: W / 2, y: H * 0.3, vx: 0, vy: 0, hp: bossHp, maxHp: bossHp, radius: CRUISE_CONFIG.bossRadius, rotation: 0, rotationSpeed: 0.3, pulsePhase: 0, attackPhase: 1, directTimer: 1.5, homingTimer: 2, summonTimer: 4, driftAngle: 0, dropStage: 0, breathPhase: 0, tentaclePhase: 0 }; durationSec = CRUISE_CONFIG.bossDuration; // 少量装饰性小陨石(缓慢飘动,增加视觉层次) const decorAsteroids = 4; for(let i = 0; i < decorAsteroids; i++){ const radius = 14 + rng() * 16; const x = 60 + rng() * (W - 120); const y = 60 + rng() * (H - 120); const speed = 20 + rng() * 30; const angle = rng() * Math.PI * 2; const vertCount = 7 + Math.floor(rng() * 4); const vertices = []; for(let v = 0; v < vertCount; v++)vertices.push(0.75 + rng() * 0.4); entities.push({ id: nextId++, type: "asteroid", x, y, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed, radius, rotation: rng() * Math.PI * 2, rotationSpeed: (rng() - 0.5) * 1.2, vertices, damage: CRUISE_CONFIG.asteroidBaseDamage + level * 1.5 }); } // 几枚晶体作为补给 crystalCount = 4; for(let i = 0; i < crystalCount; i++){ const x = 80 + rng() * (W - 160); const y = 120 + rng() * (H - 240); entities.push({ id: nextId++, type: "crystal", x, y, vx: 0, vy: 0, radius: 12, rotation: rng() * Math.PI * 2, rotationSpeed: (rng() - 0.5) * 2, pulsePhase: rng() * Math.PI * 2, collected: false }); } } else { // ---- 普通关卡:星门 + 陨石带 + 风暴 + 收集物 ---- // 星门:顶部中央 const stargate = { id: nextId++, type: "stargate", x: W / 2, y: 70, vx: 0, vy: 0, radius: 42, rotation: 0, rotationSpeed: 0.6, pulsePhase: 0, active: false }; entities.push(stargate); // 陨石带:数量随关卡递增 const asteroidCount = Math.min(8 + level * 2, 32); for(let i = 0; i < asteroidCount; i++){ const radius = 16 + rng() * 28; let x = 0, y = 0, tries = 0; do { x = 40 + rng() * (W - 80); y = 140 + rng() * (H - 260); tries++; }while (tries < 20 && (Math.hypot(x - ship.x, y - ship.y) < 120 || Math.hypot(x - stargate.x, y - stargate.y) < 100)) const speed = 30 + rng() * 60 + level * 4; const angle = rng() * Math.PI * 2; const vertCount = 7 + Math.floor(rng() * 4); const vertices = []; for(let v = 0; v < vertCount; v++){ vertices.push(0.75 + rng() * 0.4); } entities.push({ id: nextId++, type: "asteroid", x, y, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed, radius, rotation: rng() * Math.PI * 2, rotationSpeed: (rng() - 0.5) * 1.2, vertices, damage: CRUISE_CONFIG.asteroidBaseDamage + level * 1.5 }); } // 虚空风暴:随关卡递增(最多 5 个) const stormCount = Math.min(1 + Math.floor(level / 2), 5); for(let i = 0; i < stormCount; i++){ const radius = 60 + rng() * 50; let x = 0, y = 0, tries = 0; do { x = 100 + rng() * (W - 200); y = 180 + rng() * (H - 320); tries++; }while (tries < 20 && (Math.hypot(x - ship.x, y - ship.y) < 180 || Math.hypot(x - stargate.x, y - stargate.y) < 150)) const speed = 12 + rng() * 18; const angle = rng() * Math.PI * 2; entities.push({ id: nextId++, type: "storm", x, y, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed, radius, rotation: rng() * Math.PI * 2, rotationSpeed: (rng() - 0.5) * 0.4, lightningTimer: rng() * 0.5, cloudSeed: Math.floor(rng() * 10000) }); } // 晶体碎片:5 + level crystalCount = 5 + level; for(let i = 0; i < crystalCount; i++){ let x = 0, y = 0, tries = 0; do { x = 50 + rng() * (W - 100); y = 120 + rng() * (H - 220); tries++; }while (tries < 20 && Math.hypot(x - ship.x, y - ship.y) < 90) entities.push({ id: nextId++, type: "crystal", x, y, vx: 0, vy: 0, radius: 12, rotation: rng() * Math.PI * 2, rotationSpeed: (rng() - 0.5) * 2, pulsePhase: rng() * Math.PI * 2, collected: false }); } // 洞见光球:2 + floor(level/3) insightCount = 2 + Math.floor(level / 3); for(let i = 0; i < insightCount; i++){ let x = 0, y = 0, tries = 0; do { x = 60 + rng() * (W - 120); y = 140 + rng() * (H - 240); tries++; }while (tries < 20 && Math.hypot(x - ship.x, y - ship.y) < 100) entities.push({ id: nextId++, type: "insight", x, y, vx: 0, vy: 0, radius: 14, pulsePhase: rng() * Math.PI * 2, swirlAngle: rng() * Math.PI * 2, collected: false }); } // 信标:1 + floor(level/4) beaconCount = 1 + Math.floor(level / 4); for(let i = 0; i < beaconCount; i++){ let x = 0, y = 0, tries = 0; do { x = 80 + rng() * (W - 160); y = 160 + rng() * (H - 280); tries++; }while (tries < 20 && Math.hypot(x - ship.x, y - ship.y) < 110) entities.push({ id: nextId++, type: "beacon", x, y, vx: 0, vy: 0, radius: 16, rotation: rng() * Math.PI * 2, rotationSpeed: (rng() - 0.5) * 1.5, pulsePhase: rng() * Math.PI * 2, collected: false }); } durationSec = Math.min(CRUISE_CONFIG.baseDuration + (level - 1) * CRUISE_CONFIG.durationPerLevel, CRUISE_CONFIG.maxDuration); } return { phase: "ready", level, seed, ship, entities, particles: [], bullets: [], powerups: [], boss, isBossLevel, score: 0, timeSec: 0, durationSec, collectedCrystals: 0, collectedInsights: 0, collectedBeacons: 0, totalCrystals: crystalCount, totalInsights: insightCount, totalBeacons: beaconCount, shakeAmount: 0, shakeTimer: 0, flashLowShield: false, pickupFlash: null, worldWidth: W, worldHeight: H, nextEntityId: nextId, invulnTimer: 0, shootCooldown: 0, endedAt: null, upgrades, appliedUpgrades, pendingUpgradeChoice: [], activeBuffs: [], bossDefeated: false }; } /** 计算 upgrades 在无 state 时的 shield 上限(用于 generateLevel 初始化) */ function effectiveShieldMaxRaw(upgrades) { return CRUISE_CONFIG.shieldMax + upgrades.shieldMaxBonus + upgrades.startShieldBonus; } function effectiveEnergyMaxRaw(upgrades) { return CRUISE_CONFIG.energyMax + upgrades.energyMaxBonus + upgrades.startEnergyBonus; } // ============================================================ // 物理与碰撞更新 // ============================================================ /** 触发屏幕震动 */ function triggerShake(state, intensity) { state.shakeAmount = intensity ?? CRUISE_CONFIG.shakeIntensity; state.shakeTimer = CRUISE_CONFIG.shakeMs; } /** 添加粒子(自动限制数量) */ function addParticle(state, p) { state.particles.push({ id: state.nextEntityId++, type: "particle", ...p }); // 超出上限移除最老的 while(state.particles.length > CRUISE_CONFIG.maxParticles){ state.particles.shift(); } } function burstParticles(state, x, y, color, count, speed = 180, life = 0.6, size = 3) { for(let i = 0; i < count; i++){ const angle = i / count * Math.PI * 2 + Math.random() * 0.4; const sp = speed * (0.4 + Math.random() * 0.8); addParticle(state, { x, y, vx: Math.cos(angle) * sp, vy: Math.sin(angle) * sp, life: life * (0.7 + Math.random() * 0.6), maxLife: life, size: size * (0.6 + Math.random() * 0.8), color, shrink: true }); } } /** 飞船尾焰粒子 */ function emitThrustParticle(state, ship) { const back = ship.heading + Math.PI; const spread = (Math.random() - 0.5) * 0.6; const ang = back + spread; const sp = 80 + Math.random() * 60; // 颜色:emerald → amber 随推力变化 const t = Math.min(1, ship.thrust); const r = Math.round(52 + t * (251 - 52)); const g = Math.round(211 + t * (191 - 211)); const b = Math.round(153 + t * (36 - 153)); const color = `rgba(${r},${g},${b},0.9)`; addParticle(state, { x: ship.x + Math.cos(back) * ship.radius, y: ship.y + Math.sin(back) * ship.radius, vx: Math.cos(ang) * sp + ship.vx * 0.3, vy: Math.sin(ang) * sp + ship.vy * 0.3, life: 0.35 + Math.random() * 0.25, maxLife: 0.6, size: 2.5 + Math.random() * 2, color, shrink: true }); } /** 添加子弹(自动限制数量) */ function addBullet(state, b) { if (state.bullets.length >= CRUISE_CONFIG.maxBullets) { state.bullets.shift(); } state.bullets.push({ id: state.nextEntityId++, type: "bullet", ...b }); } /** 添加道具 */ function addPowerup(state, p) { if (state.powerups.length >= CRUISE_CONFIG.maxPowerups) { state.powerups.shift(); } state.powerups.push({ id: state.nextEntityId++, type: "powerup", ...p }); } function shootShip(state) { if (state.phase !== "playing") return; if (state.shootCooldown > 0) return; const ship = state.ship; const energyCost = CRUISE_CONFIG.bulletEnergyCost; if (ship.energy < energyCost) return; ship.energy -= energyCost; state.shootCooldown = effectiveShootCooldownMs(state); const dmg = effectiveBulletDamage(state); const ang = ship.heading; const muzzleX = ship.x + Math.cos(ang) * (ship.radius + 4); const muzzleY = ship.y + Math.sin(ang) * (ship.radius + 4); const v = CRUISE_CONFIG.bulletSpeed; // 主弹 addBullet(state, { x: muzzleX, y: muzzleY, vx: Math.cos(ang) * v, vy: Math.sin(ang) * v, owner: "ship", radius: CRUISE_CONFIG.bulletRadius, damage: dmg, life: CRUISE_CONFIG.bulletLife, homing: false, homingTime: 0, color: "#34d399" }); // 双发:上下偏移 8° if (state.upgrades.doubleShot) { for (const offset of [ 0.14, -0.14 ]){ const a2 = ang + offset; addBullet(state, { x: ship.x + Math.cos(a2) * (ship.radius + 4), y: ship.y + Math.sin(a2) * (ship.radius + 4), vx: Math.cos(a2) * v, vy: Math.sin(a2) * v, owner: "ship", radius: CRUISE_CONFIG.bulletRadius, damage: dmg, life: CRUISE_CONFIG.bulletLife, homing: false, homingTime: 0, color: "#34d399" }); } } // 枪口闪光粒子 burstParticles(state, muzzleX, muzzleY, "#a7f3d0", 4, 120, 0.25, 2); } // ============================================================ // BOSS AI // ============================================================ /** BOSS 攻击模式更新 */ function updateBoss(state, dt) { const boss = state.boss; if (!boss) return; const ship = state.ship; // 阶段切换(HP 比例) const hpPct = boss.hp / boss.maxHp; if (hpPct > 0.66) boss.attackPhase = 1; else if (hpPct > 0.33) boss.attackPhase = 2; else boss.attackPhase = 3; // 视觉相位 boss.rotation += boss.rotationSpeed * dt; boss.pulsePhase += dt * 2; boss.breathPhase += dt * 1.4; boss.tentaclePhase += dt * 0.8; // 漂浮:以画布中心区域为目标,缓慢游走 boss.driftAngle += dt * 0.4; const cx = state.worldWidth / 2 + Math.cos(boss.driftAngle) * (state.worldWidth * 0.25); const cy = state.worldHeight * 0.32 + Math.sin(boss.driftAngle * 1.3) * 40; const dx = cx - boss.x; const dy = cy - boss.y; const dist = Math.hypot(dx, dy) || 1; const driftSpeed = CRUISE_CONFIG.bossDriftSpeed; boss.vx = dx / dist * driftSpeed; boss.vy = dy / dist * driftSpeed; boss.x += boss.vx * dt; boss.y += boss.vy * dt; // 边界 boss.x = Math.max(boss.radius + 20, Math.min(state.worldWidth - boss.radius - 20, boss.x)); boss.y = Math.max(boss.radius + 20, Math.min(state.worldHeight * 0.55, boss.y)); // ---- 攻击 ---- // 阶段1:直射 if (boss.attackPhase >= 1) { boss.directTimer -= dt; if (boss.directTimer <= 0) { boss.directTimer = boss.attackPhase === 1 ? CRUISE_CONFIG.bossDirectInterval : CRUISE_CONFIG.bossScatterInterval; if (boss.attackPhase === 1) { // 直射一发,朝飞船方向 const a = Math.atan2(ship.y - boss.y, ship.x - boss.x); const v = 260; addBullet(state, { x: boss.x + Math.cos(a) * boss.radius, y: boss.y + Math.sin(a) * boss.radius, vx: Math.cos(a) * v, vy: Math.sin(a) * v, owner: "boss", radius: 6, damage: CRUISE_CONFIG.bossBulletDamage, life: 4, homing: false, homingTime: 0, color: "#fb7185" }); } else { // 阶段2+:散射 5 发扇形 const baseA = Math.atan2(ship.y - boss.y, ship.x - boss.x); const v = 240; for(let i = -2; i <= 2; i++){ const a = baseA + i * 0.18; addBullet(state, { x: boss.x + Math.cos(a) * boss.radius, y: boss.y + Math.sin(a) * boss.radius, vx: Math.cos(a) * v, vy: Math.sin(a) * v, owner: "boss", radius: 6, damage: CRUISE_CONFIG.bossBulletDamage, life: 4, homing: false, homingTime: 0, color: "#fb7185" }); } } } } // 阶段2+:召唤小陨石 if (boss.attackPhase >= 2) { boss.summonTimer -= dt; if (boss.summonTimer <= 0) { boss.summonTimer = CRUISE_CONFIG.bossSummonInterval; for(let i = 0; i < 2; i++){ const a = Math.random() * Math.PI * 2; const r = boss.radius + 10; const sx = boss.x + Math.cos(a) * r; const sy = boss.y + Math.sin(a) * r; const v = 100 + Math.random() * 60; const ang = Math.atan2(ship.y - sy, ship.x - sx) + (Math.random() - 0.5) * 0.8; const vertCount = 7; const vertices = []; for(let k = 0; k < vertCount; k++)vertices.push(0.75 + Math.random() * 0.4); state.entities.push({ id: state.nextEntityId++, type: "asteroid", x: sx, y: sy, vx: Math.cos(ang) * v, vy: Math.sin(ang) * v, radius: 14 + Math.random() * 8, rotation: Math.random() * Math.PI * 2, rotationSpeed: (Math.random() - 0.5) * 2, vertices, damage: CRUISE_CONFIG.asteroidBaseDamage, summoned: true }); } // 召唤特效 burstParticles(state, boss.x, boss.y, "#e879f9", 12, 200, 0.5, 3); } } // 阶段3:追踪弹 if (boss.attackPhase >= 3) { boss.homingTimer -= dt; if (boss.homingTimer <= 0) { boss.homingTimer = CRUISE_CONFIG.bossHomingInterval; const a = Math.atan2(ship.y - boss.y, ship.x - boss.x); const v = 200; addBullet(state, { x: boss.x + Math.cos(a) * boss.radius, y: boss.y + Math.sin(a) * boss.radius, vx: Math.cos(a) * v, vy: Math.sin(a) * v, owner: "boss", radius: 7, damage: CRUISE_CONFIG.bossBulletDamage, life: 5, homing: true, homingTime: 3, color: "#e879f9" }); } } // ---- 道具掉落:每损失 25% HP 掉 1 个 ---- const newDropStage = Math.min(3, Math.floor((1 - hpPct) / 0.25)); while(boss.dropStage < newDropStage){ boss.dropStage++; dropRandomPowerup(state, boss.x + (Math.random() - 0.5) * 80, boss.y + 40, "boss"); burstParticles(state, boss.x, boss.y, "#fbbf24", 16, 200, 0.6, 3); } } /** 掉落随机道具 */ function dropRandomPowerup(state, x, y, source) { const types = [ "shield", "energy", "rapid", "overdrive", "magnet" ]; const t = types[Math.floor(Math.random() * types.length)]; const life = source === "boss" ? CRUISE_CONFIG.powerupLifeBoss : CRUISE_CONFIG.powerupLifeNormal; addPowerup(state, { x, y, vx: (Math.random() - 0.5) * 30, vy: 20 + Math.random() * 20, powerupType: t, radius: 14, rotation: 0, rotationSpeed: (Math.random() - 0.5) * 2, pulsePhase: Math.random() * Math.PI * 2, life, maxLife: life, collected: false }); } // ============================================================ // 子弹更新 // ============================================================ function updateBullets(state, dt) { const ship = state.ship; for(let i = state.bullets.length - 1; i >= 0; i--){ const b = state.bullets[i]; b.life -= dt; if (b.life <= 0) { state.bullets.splice(i, 1); continue; } // 追踪弹 if (b.homing && b.homingTime > 0) { b.homingTime -= dt; const a = Math.atan2(ship.y - b.y, ship.x - b.x); const v = Math.hypot(b.vx, b.vy); // 平滑转向 const curA = Math.atan2(b.vy, b.vx); let diff = a - curA; while(diff > Math.PI)diff -= Math.PI * 2; while(diff < -Math.PI)diff += Math.PI * 2; const turn = Math.max(-2 * dt, Math.min(2 * dt, diff)); const newA = curA + turn; b.vx = Math.cos(newA) * v; b.vy = Math.sin(newA) * v; } b.x += b.vx * dt; b.y += b.vy * dt; // 离屏剔除 const m = 50; if (b.x < -m || b.x > state.worldWidth + m || b.y < -m || b.y > state.worldHeight + m) { state.bullets.splice(i, 1); continue; } // 尾焰粒子(少量) if (Math.random() < 0.4) { addParticle(state, { x: b.x, y: b.y, vx: -b.vx * 0.05, vy: -b.vy * 0.05, life: 0.2, maxLife: 0.3, size: 2, color: b.color, shrink: true }); } // ---- 碰撞 ---- if (b.owner === "ship") { // 飞船子弹 vs 陨石(小陨石/召唤陨石一击碎;大陨石伤害衰减) let consumed = false; for (const e of state.entities){ if (e.type !== "asteroid") continue; const d = Math.hypot(b.x - e.x, b.y - e.y); if (d < e.radius + b.radius) { if (e.summoned || e.radius < 22) { // 一击碎 burstParticles(state, e.x, e.y, "#fb7185", 14, 220, 0.5, 3); // 标记移除(后面统一过滤) e.damage = -999; // 标记删除 state.score += 30; } else { // 大陨石:只是擦伤 burstParticles(state, b.x, b.y, "#fbbf24", 6, 160, 0.3, 2); } consumed = true; break; } } // 飞船子弹 vs BOSS if (!consumed && state.boss) { const d = Math.hypot(b.x - state.boss.x, b.y - state.boss.y); if (d < state.boss.radius + b.radius) { state.boss.hp = Math.max(0, state.boss.hp - b.damage); burstParticles(state, b.x, b.y, "#fbbf24", 8, 180, 0.4, 2.5); // BOSS 受击闪光 burstParticles(state, b.x, b.y, "#fb7185", 4, 100, 0.2, 2); consumed = true; } } if (consumed) { state.bullets.splice(i, 1); continue; } } else { // BOSS 子弹 vs 飞船 if (state.invulnTimer <= 0) { const d = Math.hypot(b.x - ship.x, b.y - ship.y); if (d < ship.radius + b.radius) { // 受击 const overdrive = state.activeBuffs.some((bb)=>bb.type === "overdrive"); if (!overdrive) { const dmg = b.damage * state.upgrades.damageReduceMult; ship.shield = Math.max(0, ship.shield - dmg); burstParticles(state, ship.x, ship.y, "#fb7185", 10, 200, 0.4, 3); triggerShake(state, 10); state.invulnTimer = effectiveInvulnMs(state); } state.bullets.splice(i, 1); continue; } } } } // 移除被子弹击碎的陨石 state.entities = state.entities.filter((e)=>{ if (e.type === "asteroid" && e.damage <= -100) return false; return true; }); } // ============================================================ // 道具更新 + 拾取 // ============================================================ function updatePowerups(state, dt) { const ship = state.ship; for(let i = state.powerups.length - 1; i >= 0; i--){ const p = state.powerups[i]; if (p.collected) { state.powerups.splice(i, 1); continue; } p.life -= dt; if (p.life <= 0) { state.powerups.splice(i, 1); continue; } p.rotation += p.rotationSpeed * dt; p.pulsePhase += dt * 3; p.x += p.vx * dt; p.y += p.vy * dt; // 摩擦衰减 p.vx *= 0.96; p.vy *= 0.96; // 边界 p.x = Math.max(p.radius, Math.min(state.worldWidth - p.radius, p.x)); p.y = Math.max(p.radius, Math.min(state.worldHeight - p.radius, p.y)); const d = Math.hypot(ship.x - p.x, ship.y - p.y); // 吸引半径(受 magnet buff 影响) const attractR = CRUISE_CONFIG.powerupAttractRadius * (state.activeBuffs.some((b)=>b.type === "magnet") ? 3 : 1); if (d < attractR) { const a = Math.atan2(ship.y - p.y, ship.x - p.x); const pull = (1 - d / attractR) * 380; p.x += Math.cos(a) * pull * dt; p.y += Math.sin(a) * pull * dt; } // 拾取 if (d < CRUISE_CONFIG.powerupPickupRadius + ship.radius) { p.collected = true; applyPowerup(state, p.powerupType); state.powerups.splice(i, 1); } } } /** 应用道具效果 */ function applyPowerup(state, type) { const ship = state.ship; let color = "#34d399"; switch(type){ case "shield": ship.shield = Math.min(effectiveShieldMax(state), ship.shield + 30); color = "#34d399"; burstParticles(state, ship.x, ship.y, color, 18, 220, 0.6, 3); break; case "energy": ship.energy = Math.min(effectiveEnergyMax(state), ship.energy + 50); color = "#fbbf24"; burstParticles(state, ship.x, ship.y, color, 18, 220, 0.6, 3); break; case "rapid": state.activeBuffs.push({ type: "rapid", remaining: CRUISE_CONFIG.buffRapidDuration, total: CRUISE_CONFIG.buffRapidDuration }); color = "#e879f9"; break; case "overdrive": state.activeBuffs.push({ type: "overdrive", remaining: CRUISE_CONFIG.buffOverdriveDuration, total: CRUISE_CONFIG.buffOverdriveDuration }); color = "#fb7185"; break; case "magnet": state.activeBuffs.push({ type: "magnet", remaining: CRUISE_CONFIG.buffMagnetDuration, total: CRUISE_CONFIG.buffMagnetDuration }); color = "#a7f3d0"; break; } // 屏幕边缘闪光 state.pickupFlash = { color, timer: 400 }; state.score += 50; } // ============================================================ // Buff 计时 // ============================================================ function updateBuffs(state, dt) { for(let i = state.activeBuffs.length - 1; i >= 0; i--){ state.activeBuffs[i].remaining -= dt; if (state.activeBuffs[i].remaining <= 0) state.activeBuffs.splice(i, 1); } } function updateCruise(state, dtMs, input) { if (state.phase !== "playing") return null; const dt = Math.min(dtMs / 1000, 0.05); // 限制最大帧间隔,避免卡顿后大跳 state.timeSec += dt; // 震动衰减 if (state.shakeTimer > 0) { state.shakeTimer -= dtMs; if (state.shakeTimer <= 0) { state.shakeTimer = 0; state.shakeAmount = 0; } } // 拾取闪光衰减 if (state.pickupFlash) { state.pickupFlash.timer -= dtMs; if (state.pickupFlash.timer <= 0) state.pickupFlash = null; } // 无敌时间衰减 if (state.invulnTimer > 0) { state.invulnTimer = Math.max(0, state.invulnTimer - dtMs); } // 射击冷却衰减 if (state.shootCooldown > 0) { state.shootCooldown = Math.max(0, state.shootCooldown - dtMs); } // Buff 计时 updateBuffs(state, dt); const ship = state.ship; // ---- 飞船控制 ---- if (input.active && (input.dx !== 0 || input.dy !== 0)) { const mag = Math.hypot(input.dx, input.dy); const nx = input.dx / mag; const ny = input.dy / mag; ship.vx += nx * effectiveShipAccel(state) * dt; ship.vy += ny * effectiveShipAccel(state) * dt; ship.heading = Math.atan2(ny, nx); ship.thrust = Math.min(1, ship.thrust + dt * 4); // 尾焰粒子 if (Math.random() < 0.9) emitThrustParticle(state, ship); if (Math.random() < 0.5) emitThrustParticle(state, ship); } else { ship.thrust = Math.max(0, ship.thrust - dt * 3); } // 摩擦(指数衰减) const fric = Math.pow(effectiveFriction(state), dt * 60); ship.vx *= fric; ship.vy *= fric; // 限速 const sp = Math.hypot(ship.vx, ship.vy); const maxSp = effectiveShipMaxSpeed(state); if (sp > maxSp) { ship.vx = ship.vx / sp * maxSp; ship.vy = ship.vy / sp * maxSp; } // 位置更新 + 边界反弹 ship.x += ship.vx * dt; ship.y += ship.vy * dt; if (ship.x < ship.radius) { ship.x = ship.radius; ship.vx = Math.abs(ship.vx) * 0.4; } if (ship.x > state.worldWidth - ship.radius) { ship.x = state.worldWidth - ship.radius; ship.vx = -Math.abs(ship.vx) * 0.4; } if (ship.y < ship.radius) { ship.y = ship.radius; ship.vy = Math.abs(ship.vy) * 0.4; } if (ship.y > state.worldHeight - ship.radius) { ship.y = state.worldHeight - ship.radius; ship.vy = -Math.abs(ship.vy) * 0.4; } // ---- 射击输入 ---- if (input.shoot) shootShip(state); // 护盾恢复(未受击时) if (state.invulnTimer <= 0 && ship.shield < effectiveShieldMax(state)) { ship.shield = Math.min(effectiveShieldMax(state), ship.shield + CRUISE_CONFIG.shieldRegen * state.upgrades.shieldRegenMult * dt); } // 能量恢复 if (ship.energy < effectiveEnergyMax(state)) { ship.energy = Math.min(effectiveEnergyMax(state), ship.energy + CRUISE_CONFIG.energyRegen * state.upgrades.energyRegenMult * dt); } // 低护盾闪烁标记 state.flashLowShield = ship.shield < effectiveShieldMax(state) * 0.3; // ---- 实体更新 ---- for (const e of state.entities){ e.x += e.vx * dt; e.y += e.vy * dt; switch(e.type){ case "asteroid": { e.rotation += e.rotationSpeed * dt; // 离屏剔除 + 重生 const m = CRUISE_CONFIG.cullMargin; if (e.x < -m || e.x > state.worldWidth + m || e.y < -m || e.y > state.worldHeight + m) { // 召唤陨石离屏就消失(不重生) if (e.summoned) { e.damage = -999; break; } // 从随机边缘重生,朝场内运动 const edge = Math.floor(Math.random() * 4); if (edge === 0) { e.x = -e.radius; e.y = Math.random() * state.worldHeight; e.vx = Math.abs(e.vx); } else if (edge === 1) { e.x = state.worldWidth + e.radius; e.y = Math.random() * state.worldHeight; e.vx = -Math.abs(e.vx); } else if (edge === 2) { e.x = Math.random() * state.worldWidth; e.y = -e.radius; e.vy = Math.abs(e.vy); } else { e.x = Math.random() * state.worldWidth; e.y = state.worldHeight + e.radius; e.vy = -Math.abs(e.vy); } } break; } case "storm": { e.rotation += e.rotationSpeed * dt; e.lightningTimer -= dt; if (e.lightningTimer <= 0) { e.lightningTimer = 0.3 + Math.random() * 0.5; } // 风暴边界软反弹 if (e.x < e.radius || e.x > state.worldWidth - e.radius) e.vx *= -1; if (e.y < e.radius || e.y > state.worldHeight - e.radius) e.vy *= -1; break; } case "crystal": { e.rotation += e.rotationSpeed * dt; e.pulsePhase += dt * 3; break; } case "insight": { e.pulsePhase += dt * 2.5; e.swirlAngle += dt * 1.5; break; } case "beacon": { e.rotation += e.rotationSpeed * dt; e.pulsePhase += dt * 2; break; } case "stargate": { e.rotation += e.rotationSpeed * dt; e.pulsePhase += dt * 2; const dist = Math.hypot(ship.x - e.x, ship.y - e.y); e.active = dist < 200; break; } } } // 清理被击碎的陨石 state.entities = state.entities.filter((e)=>{ if (e.type === "asteroid" && e.damage <= -100) return false; return true; }); // ---- BOSS 更新 ---- if (state.boss) updateBoss(state, dt); // ---- 子弹更新 ---- updateBullets(state, dt); // ---- 道具更新 ---- updatePowerups(state, dt); // ---- 粒子更新 ---- for(let i = state.particles.length - 1; i >= 0; i--){ const p = state.particles[i]; p.life -= dt; if (p.life <= 0) { state.particles.splice(i, 1); continue; } p.x += p.vx * dt; p.y += p.vy * dt; p.vx *= 0.96; p.vy *= 0.96; } // ---- 碰撞检测 ---- // 飞船 vs 陨石 if (state.invulnTimer <= 0) { const overdrive = state.activeBuffs.some((b)=>b.type === "overdrive"); for (const e of state.entities){ if (e.type !== "asteroid") continue; const dist = Math.hypot(ship.x - e.x, ship.y - e.y); if (dist < ship.radius + e.radius) { if (!overdrive) { // 受击 const dmg = e.damage * state.upgrades.damageReduceMult; ship.shield = Math.max(0, ship.shield - dmg); } // 击退 const ang = Math.atan2(ship.y - e.y, ship.x - e.x); ship.vx += Math.cos(ang) * 200; ship.vy += Math.sin(ang) * 200; // 陨石反向 e.vx = -Math.cos(ang) * Math.abs(e.vx) * 0.5; e.vy = -Math.sin(ang) * Math.abs(e.vy) * 0.5; // 爆炸粒子 burstParticles(state, ship.x, ship.y, "#fb7185", 18, 260, 0.7, 3.5); burstParticles(state, ship.x, ship.y, "#fbbf24", 8, 180, 0.5, 2.5); triggerShake(state, CRUISE_CONFIG.shakeIntensity); state.invulnTimer = effectiveInvulnMs(state); break; } } } // 飞船 vs 风暴(持续伤害) if (state.invulnTimer <= 0) { const overdrive = state.activeBuffs.some((b)=>b.type === "overdrive"); for (const e of state.entities){ if (e.type !== "storm") continue; const dist = Math.hypot(ship.x - e.x, ship.y - e.y); if (dist < ship.radius + e.radius * 0.7) { if (!overdrive) { const dmg = CRUISE_CONFIG.stormDps * dt * state.upgrades.damageReduceMult; ship.shield = Math.max(0, ship.shield - dmg); } // 风暴边缘小粒子 if (Math.random() < 0.3) { burstParticles(state, ship.x, ship.y, "#e879f9", 2, 100, 0.4, 2); } } } } // 飞船 vs BOSS(接触伤害) if (state.invulnTimer <= 0 && state.boss) { const overdrive = state.activeBuffs.some((b)=>b.type === "overdrive"); const dist = Math.hypot(ship.x - state.boss.x, ship.y - state.boss.y); if (dist < ship.radius + state.boss.radius * 0.85) { if (!overdrive) { const dmg = CRUISE_CONFIG.bossContactDamage * state.upgrades.damageReduceMult; ship.shield = Math.max(0, ship.shield - dmg); } // 击退 const ang = Math.atan2(ship.y - state.boss.y, ship.x - state.boss.x); ship.vx += Math.cos(ang) * 280; ship.vy += Math.sin(ang) * 280; burstParticles(state, ship.x, ship.y, "#fb7185", 14, 240, 0.5, 3); triggerShake(state, 16); state.invulnTimer = effectiveInvulnMs(state); } } // 收集物:吸引 + 收集 const attractR = effectiveAttractRadius(state); const collectR = effectiveCollectRadius(state); for (const e of state.entities){ if (e.type === "crystal" || e.type === "insight" || e.type === "beacon") { if (e.collected) continue; const dist = Math.hypot(ship.x - e.x, ship.y - e.y); // 吸引 if (dist < attractR) { const ang = Math.atan2(ship.y - e.y, ship.x - e.x); const pull = (1 - dist / attractR) * 320; e.x += Math.cos(ang) * pull * dt; e.y += Math.sin(ang) * pull * dt; } // 收集 if (dist < collectR) { e.collected = true; if (e.type === "crystal") { state.collectedCrystals++; state.score += Math.round(100 * state.upgrades.normalScoreMult); burstParticles(state, e.x, e.y, "#34d399", 10, 200, 0.6, 3); } else if (e.type === "insight") { state.collectedInsights++; state.score += Math.round(250 * state.upgrades.normalScoreMult); burstParticles(state, e.x, e.y, "#e879f9", 10, 200, 0.6, 3); } else if (e.type === "beacon") { state.collectedBeacons++; state.score += Math.round(500 * state.upgrades.normalScoreMult); burstParticles(state, e.x, e.y, "#fbbf24", 12, 220, 0.7, 3.5); // 信标 5% 概率掉落道具 if (!e.powerupDropped && Math.random() < 0.05) { e.powerupDropped = true; dropRandomPowerup(state, e.x, e.y, "beacon"); } } } } } // ---- 关卡结束判定 ---- // BOSS 关:BOSS HP 归零 → 胜利 if (state.boss && state.boss.hp <= 0 && !state.bossDefeated) { state.bossDefeated = true; state.phase = "won"; state.endedAt = Date.now(); // 大爆炸(200+ 粒子) const bx = state.boss.x; const by = state.boss.y; const colors = [ "#fb7185", "#fbbf24", "#e879f9", "#34d399" ]; for(let k = 0; k < 8; k++){ const col = colors[k % colors.length]; burstParticles(state, bx + (Math.random() - 0.5) * 80, by + (Math.random() - 0.5) * 80, col, 28, 360, 1.0, 4); } triggerShake(state, 28); const result = computeRewards(state); return result; } // 普通关卡:星门到达判定 if (!state.isBossLevel) { for (const e of state.entities){ if (e.type !== "stargate") continue; const dist = Math.hypot(ship.x - e.x, ship.y - e.y); if (dist < ship.radius + e.radius * 0.6) { // 通关! state.phase = "won"; state.endedAt = Date.now(); // 烟花 for(let k = 0; k < 5; k++){ const cx = state.worldWidth * (0.2 + Math.random() * 0.6); const cy = state.worldHeight * (0.2 + Math.random() * 0.6); const colors = [ "#34d399", "#fb7185", "#fbbf24", "#e879f9" ]; const col = colors[k % colors.length]; burstParticles(state, cx, cy, col, 24, 320, 1.0, 4); } const result = computeRewards(state); return result; } } } // 护盾归零 → 失败 if (ship.shield <= 0) { state.phase = "lost"; state.endedAt = Date.now(); // 大爆炸 burstParticles(state, ship.x, ship.y, "#fb7185", 30, 360, 1.0, 4.5); burstParticles(state, ship.x, ship.y, "#fbbf24", 16, 240, 0.8, 3); triggerShake(state, 24); const result = computeRewards(state); return result; } // 时间耗尽 → 失败 if (state.timeSec >= state.durationSec) { state.phase = "lost"; state.endedAt = Date.now(); const result = computeRewards(state); return result; } return null; } function computeRewards(state) { const level = state.level; const baseCrystals = state.collectedCrystals * (8 + level * 2); const baseInsights = state.collectedInsights * (2 + level * 0.5); const baseContact = state.collectedBeacons * (1.5 + level * 0.3); let mult = 1; if (state.phase === "won") { mult = state.isBossLevel ? 3 : 1.5; if (state.isBossLevel) mult *= state.upgrades.bossBonusMult; } else if (state.phase === "lost") { mult = 0.5; } const rewards = { crystals: Math.round(baseCrystals * mult), insights: Math.round(baseInsights * mult * 10) / 10, contact: Math.round(baseContact * mult * 10) / 10 }; // 综合得分(用于排行榜/统计) const timeBonus = Math.max(0, 1000 - state.timeSec * 5); const shieldBonus = Math.round(state.ship.shield * 10); const winBonus = state.phase === "won" ? state.isBossLevel ? 5000 : 2000 : 0; const score = state.score + timeBonus + shieldBonus + winBonus + level * 500; return { level, phase: state.phase, isBossLevel: state.isBossLevel, durationSec: Math.round(state.timeSec * 10) / 10, collectedCrystals: state.collectedCrystals, collectedInsights: state.collectedInsights, collectedBeacons: state.collectedBeacons, remainingShield: Math.round(state.ship.shield), score: Math.round(score), rewards, timestamp: Date.now() }; } // ============================================================ // localStorage 持久化(独立 key,不污染 GameState) // ============================================================ const STORAGE_KEY = "echo-nexus-cruise-v1"; function emptyStats() { return { highScore: 0, totalRuns: 0, totalWins: 0, bestLevel: 0, totalCrystals: 0, totalInsights: 0, totalContact: 0, bossKills: 0, lastResult: null, recentResults: [] }; } function loadCruiseStats() { if ("TURBOPACK compile-time falsy", 0) //TURBOPACK unreachable ; try { const raw = window.localStorage.getItem(STORAGE_KEY); if (!raw) return emptyStats(); const parsed = JSON.parse(raw); return { ...emptyStats(), ...parsed, recentResults: Array.isArray(parsed.recentResults) ? parsed.recentResults.slice(0, 20) : [] }; } catch { return emptyStats(); } } function saveCruiseStats(stats) { if ("TURBOPACK compile-time falsy", 0) //TURBOPACK unreachable ; try { window.localStorage.setItem(STORAGE_KEY, JSON.stringify(stats)); } catch { // 忽略写入失败(隐私模式 / 配额满) } } function recordRun(result) { const stats = loadCruiseStats(); stats.totalRuns++; if (result.phase === "won") { stats.totalWins++; stats.bestLevel = Math.max(stats.bestLevel, result.level); if (result.isBossLevel) stats.bossKills++; } stats.highScore = Math.max(stats.highScore, result.score); stats.totalCrystals += result.rewards.crystals; stats.totalInsights += result.rewards.insights; stats.totalContact += result.rewards.contact; stats.lastResult = result; stats.recentResults = [ result, ...stats.recentResults ].slice(0, 20); saveCruiseStats(stats); return stats; } function resetCruiseStats() { const empty = emptyStats(); saveCruiseStats(empty); return empty; } if (typeof globalThis.$RefreshHelpers$ === 'object' && globalThis.$RefreshHelpers !== null) { __turbopack_context__.k.registerExports(__turbopack_context__.m, globalThis.$RefreshHelpers$); } }), "[project]/src/components/game/CruiseMode.tsx [app-client] (ecmascript) ", ((__turbopack_context__) => { "use strict"; __turbopack_context__.s([ "CruiseMode", ()=>CruiseMode ]); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/node_modules/next/dist/compiled/react/jsx-dev-runtime.js [app-client] (ecmascript)"); // 回响星核 / Echo Nexus — 深空巡航 Canvas 2D 实时玩法渲染层 (v0.8) // v0.8 新增:BOSS 战 / 飞船射击 / 道具掉落 / 事件选择节点 // 全屏 fixed 覆盖,rAF 驱动游戏循环,HTML HUD 叠层 + Canvas 实体绘制。 var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/node_modules/next/dist/compiled/react/index.js [app-client] (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/components/ui/button.tsx [app-client] (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$x$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__X$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/x.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$play$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Play$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/play.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$rotate$2d$ccw$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__RotateCcw$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/rotate-ccw.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$chevron$2d$right$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ChevronRight$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/chevron-right.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$pause$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Pause$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/pause.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$gem$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Gem$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/gem.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$brain$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Brain$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/brain.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$radio$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Radio$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/radio.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Shield$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/shield.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$zap$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Zap$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/zap.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$clock$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Clock$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/clock.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$trophy$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Trophy$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/trophy.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$crosshair$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Crosshair$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/crosshair.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$skull$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Skull$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/skull.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$sparkles$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Sparkles$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/sparkles.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$wind$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Wind$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/wind.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$gauge$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Gauge$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/gauge.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$feather$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Feather$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/feather.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$heart$2d$pulse$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__HeartPulse$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/heart-pulse.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$battery$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Battery$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/battery.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$timer$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Timer$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/timer.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$flame$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Flame$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/flame.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$split$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Split$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/split.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$magnet$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Magnet$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/magnet.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$circle$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Circle$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/circle.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2d$check$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ShieldCheck$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/shield-check.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2d$half$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ShieldHalf$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/shield-half.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$crown$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Crown$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/crown.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$star$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Star$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/star.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2d$plus$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ShieldPlus$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/shield-plus.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$battery$2d$charging$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__BatteryCharging$3e$__ = __turbopack_context__.i("[project]/node_modules/lucide-react/dist/esm/icons/battery-charging.js [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/game/cruise.ts [app-client] (ecmascript)"); var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$store$2f$gameStore$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$locals$3e$__ = __turbopack_context__.i("[project]/src/store/gameStore.ts [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$config$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/game/config.ts [app-client] (ecmascript)"); ; var _s = __turbopack_context__.k.signature(); "use client"; ; ; ; ; ; ; // ============================================================ // 颜色常量(避开蓝色/靛色,使用 emerald/rose/amber/fuchsia 四色全息色谱) // ============================================================ const C = { ship: "#34d399", shipCore: "#a7f3d0", asteroid: "#3a2a2a", asteroidStroke: "#7f1d1d", asteroidGlow: "#fb7185", storm: "#e879f9", stormCore: "#fdf4ff", crystal: "#34d399", crystalCore: "#d1fae5", insight: "#e879f9", insightCore: "#fae8ff", beacon: "#fbbf24", beaconCore: "#fef3c7", stargate: "#fb7185", stargateCore: "#ffe4e6", boss: "#fb7185", bossGlow: "#e879f9", bossCore: "#ffe4e6", shipBullet: "#34d399", bossBullet: "#fb7185", homingBullet: "#e879f9" }; // 道具颜色 const POWERUP_COLOR = { shield: "#34d399", energy: "#fbbf24", rapid: "#e879f9", overdrive: "#fb7185", magnet: "#a7f3d0" }; // 道具图标 key → lucide 组件 const POWERUP_ICON_KEY = { shield: "Shield", energy: "Zap", rapid: "Timer", overdrive: "Flame", magnet: "Magnet" }; // 升级卡图标 key → lucide const UPGRADE_ICON_MAP = { Wind: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$wind$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Wind$3e$__["Wind"], Gauge: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$gauge$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Gauge$3e$__["Gauge"], Feather: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$feather$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Feather$3e$__["Feather"], Shield: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Shield$3e$__["Shield"], HeartPulse: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$heart$2d$pulse$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__HeartPulse$3e$__["HeartPulse"], Battery: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$battery$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Battery$3e$__["Battery"], Zap: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$zap$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Zap$3e$__["Zap"], Flame: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$flame$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Flame$3e$__["Flame"], Timer: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$timer$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Timer$3e$__["Timer"], Split: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$split$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Split$3e$__["Split"], Magnet: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$magnet$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Magnet$3e$__["Magnet"], Circle: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$circle$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Circle$3e$__["Circle"], ShieldCheck: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2d$check$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ShieldCheck$3e$__["ShieldCheck"], ShieldHalf: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2d$half$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ShieldHalf$3e$__["ShieldHalf"], Crown: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$crown$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Crown$3e$__["Crown"], Star: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$star$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Star$3e$__["Star"], ShieldPlus: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2d$plus$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ShieldPlus$3e$__["ShieldPlus"], BatteryCharging: __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$battery$2d$charging$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__BatteryCharging$3e$__["BatteryCharging"] }; function generateStars(w, h) { const layers = [ { stars: [], speed: 8, parallax: 0.1 }, { stars: [], speed: 18, parallax: 0.25 }, { stars: [], speed: 36, parallax: 0.5 } ]; const counts = [ 100, 60, 30 ]; for(let li = 0; li < layers.length; li++){ const layer = layers[li]; for(let i = 0; i < counts[li]; i++){ layer.stars.push({ x: Math.random() * w, y: Math.random() * h, size: 0.5 + li * 0.6 + Math.random() * (0.5 + li * 0.5), brightness: 0.2 + li * 0.25 + Math.random() * 0.25, twinkle: Math.random() * Math.PI * 2, twinkleSpeed: 0.5 + Math.random() * 2 }); } } return layers; } function drawStars(ctx, layers, dt, w, h, shipVx, shipVy) { for (const layer of layers){ for (const s of layer.stars){ // 向下漂移 + 受飞船速度影响的视差 s.y += (layer.speed + shipVy * layer.parallax) * dt; s.x -= shipVx * layer.parallax * dt; // 环绕 if (s.y > h + 5) s.y = -5; if (s.y < -5) s.y = h + 5; if (s.x > w + 5) s.x = -5; if (s.x < -5) s.x = w + 5; s.twinkle += s.twinkleSpeed * dt; const tw = 0.6 + 0.4 * Math.sin(s.twinkle); const alpha = s.brightness * tw; ctx.fillStyle = `rgba(220,230,255,${alpha})`; ctx.beginPath(); ctx.arc(s.x, s.y, s.size, 0, Math.PI * 2); ctx.fill(); } } } // ============================================================ // 实体绘制函数 // ============================================================ function drawShip(ctx, ship, invuln, buffs) { ctx.save(); ctx.translate(ship.x, ship.y); // buff 光环(在飞船下层) if (buffs.length > 0) { for (const buff of buffs){ const color = POWERUP_COLOR[buff.type]; const pct = buff.remaining / buff.total; const r = ship.radius * (1.6 + 0.2 * Math.sin(Date.now() / 200)); ctx.beginPath(); ctx.arc(0, 0, r, 0, Math.PI * 2); ctx.strokeStyle = `${color}${Math.round(pct * 200).toString(16).padStart(2, "0")}`; ctx.lineWidth = 2; ctx.stroke(); // 进度弧 ctx.beginPath(); ctx.arc(0, 0, r + 3, -Math.PI / 2, -Math.PI / 2 + Math.PI * 2 * pct); ctx.strokeStyle = color; ctx.lineWidth = 1.5; ctx.stroke(); } } ctx.rotate(ship.heading); // 受击闪烁 const blink = invuln && Math.floor(Date.now() / 80) % 2 === 0; // 尾焰(在飞船后方) if (ship.thrust > 0.1) { const flameLen = ship.radius * (1.5 + ship.thrust * 1.5); const grad = ctx.createLinearGradient(-ship.radius * 0.4, 0, -flameLen, 0); grad.addColorStop(0, `rgba(251,191,36,${0.8 * ship.thrust})`); grad.addColorStop(0.5, `rgba(232,121,249,${0.4 * ship.thrust})`); grad.addColorStop(1, "rgba(232,121,249,0)"); ctx.fillStyle = grad; ctx.beginPath(); ctx.moveTo(-ship.radius * 0.4, ship.radius * 0.4); ctx.lineTo(-flameLen, 0); ctx.lineTo(-ship.radius * 0.4, -ship.radius * 0.4); ctx.closePath(); ctx.fill(); } // 飞船辉光 ctx.shadowBlur = 22; ctx.shadowColor = C.ship; // 飞船主体(三角形) const r = ship.radius; ctx.beginPath(); ctx.moveTo(r, 0); ctx.lineTo(-r * 0.7, r * 0.75); ctx.lineTo(-r * 0.35, 0); ctx.lineTo(-r * 0.7, -r * 0.75); ctx.closePath(); const bodyGrad = ctx.createLinearGradient(-r, 0, r, 0); bodyGrad.addColorStop(0, blink ? "#fb7185" : "#065f46"); bodyGrad.addColorStop(0.5, blink ? "#fda4af" : C.ship); bodyGrad.addColorStop(1, blink ? "#fecdd3" : C.shipCore); ctx.fillStyle = bodyGrad; ctx.fill(); ctx.shadowBlur = 0; ctx.lineWidth = 1.5; ctx.strokeStyle = blink ? "#ffe4e6" : "#d1fae5"; ctx.stroke(); // 驾驶舱 ctx.beginPath(); ctx.arc(r * 0.15, 0, r * 0.22, 0, Math.PI * 2); ctx.fillStyle = "rgba(255,255,255,0.85)"; ctx.fill(); ctx.restore(); } function drawAsteroid(ctx, a) { ctx.save(); ctx.translate(a.x, a.y); ctx.rotate(a.rotation); ctx.shadowBlur = 14; ctx.shadowColor = C.asteroidGlow; ctx.beginPath(); const n = a.vertices.length; for(let i = 0; i < n; i++){ const ang = i / n * Math.PI * 2; const rad = a.radius * a.vertices[i]; const x = Math.cos(ang) * rad; const y = Math.sin(ang) * rad; if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.closePath(); const grad = ctx.createRadialGradient(0, 0, a.radius * 0.2, 0, 0, a.radius); grad.addColorStop(0, "#5a3a3a"); grad.addColorStop(0.7, C.asteroid); grad.addColorStop(1, "#1a0808"); ctx.fillStyle = grad; ctx.fill(); ctx.shadowBlur = 0; ctx.lineWidth = 1.2; ctx.strokeStyle = C.asteroidStroke; ctx.stroke(); // 内部裂纹 ctx.beginPath(); ctx.moveTo(-a.radius * 0.3, -a.radius * 0.2); ctx.lineTo(a.radius * 0.2, a.radius * 0.3); ctx.strokeStyle = "rgba(127,29,29,0.5)"; ctx.lineWidth = 1; ctx.stroke(); ctx.restore(); } function drawStorm(ctx, s) { ctx.save(); ctx.translate(s.x, s.y); ctx.shadowBlur = 30; ctx.shadowColor = C.storm; // 多层云团 const cloudCount = 5; for(let i = 0; i < cloudCount; i++){ const ang = i / cloudCount * Math.PI * 2 + s.rotation; const dist = s.radius * 0.4 * (0.5 + 0.5 * Math.sin(s.cloudSeed + i)); const cx = Math.cos(ang) * dist; const cy = Math.sin(ang) * dist; const cr = s.radius * (0.5 + 0.2 * Math.sin(s.cloudSeed * 0.7 + i * 2)); const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, cr); grad.addColorStop(0, "rgba(232,121,249,0.55)"); grad.addColorStop(0.6, "rgba(168,85,247,0.3)"); grad.addColorStop(1, "rgba(88,28,135,0)"); ctx.fillStyle = grad; ctx.beginPath(); ctx.arc(cx, cy, cr, 0, Math.PI * 2); ctx.fill(); } // 核心 ctx.shadowBlur = 0; const coreGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, s.radius * 0.3); coreGrad.addColorStop(0, "rgba(253,244,255,0.8)"); coreGrad.addColorStop(1, "rgba(232,121,249,0)"); ctx.fillStyle = coreGrad; ctx.beginPath(); ctx.arc(0, 0, s.radius * 0.3, 0, Math.PI * 2); ctx.fill(); // 闪电 if (s.lightningTimer < 0.12) { ctx.strokeStyle = "rgba(253,244,255,0.9)"; ctx.lineWidth = 2; ctx.shadowBlur = 12; ctx.shadowColor = C.stormCore; ctx.beginPath(); let lx = 0, ly = 0; ctx.moveTo(lx, ly); for(let i = 0; i < 4; i++){ lx += (Math.random() - 0.5) * s.radius * 0.5; ly += (Math.random() - 0.5) * s.radius * 0.5; ctx.lineTo(lx, ly); } ctx.stroke(); } ctx.restore(); } function drawCrystal(ctx, c) { if (c.collected) return; ctx.save(); ctx.translate(c.x, c.y); // 脉冲光环 const pulse = 0.5 + 0.5 * Math.sin(c.pulsePhase); ctx.shadowBlur = 20; ctx.shadowColor = C.crystal; ctx.beginPath(); ctx.arc(0, 0, c.radius * (1.4 + pulse * 0.4), 0, Math.PI * 2); ctx.strokeStyle = `rgba(52,211,153,${0.15 + pulse * 0.2})`; ctx.lineWidth = 2; ctx.stroke(); // 菱形 ctx.rotate(c.rotation); ctx.beginPath(); ctx.moveTo(0, -c.radius); ctx.lineTo(c.radius * 0.7, 0); ctx.lineTo(0, c.radius); ctx.lineTo(-c.radius * 0.7, 0); ctx.closePath(); const grad = ctx.createLinearGradient(-c.radius, -c.radius, c.radius, c.radius); grad.addColorStop(0, "#065f46"); grad.addColorStop(0.5, C.crystal); grad.addColorStop(1, C.crystalCore); ctx.fillStyle = grad; ctx.fill(); ctx.shadowBlur = 0; ctx.lineWidth = 1.2; ctx.strokeStyle = C.crystalCore; ctx.stroke(); // 高光 ctx.beginPath(); ctx.moveTo(0, -c.radius * 0.7); ctx.lineTo(c.radius * 0.3, -c.radius * 0.2); ctx.strokeStyle = "rgba(255,255,255,0.6)"; ctx.lineWidth = 1; ctx.stroke(); ctx.restore(); } function drawInsight(ctx, i) { if (i.collected) return; ctx.save(); ctx.translate(i.x, i.y); const pulse = 0.5 + 0.5 * Math.sin(i.pulsePhase); ctx.shadowBlur = 22; ctx.shadowColor = C.insight; // 外光环 ctx.beginPath(); ctx.arc(0, 0, i.radius * (1.3 + pulse * 0.3), 0, Math.PI * 2); ctx.strokeStyle = `rgba(232,121,249,${0.2 + pulse * 0.2})`; ctx.lineWidth = 2; ctx.stroke(); // 球体 const grad = ctx.createRadialGradient(-i.radius * 0.3, -i.radius * 0.3, 0, 0, 0, i.radius); grad.addColorStop(0, C.insightCore); grad.addColorStop(0.5, C.insight); grad.addColorStop(1, "#86198f"); ctx.fillStyle = grad; ctx.beginPath(); ctx.arc(0, 0, i.radius, 0, Math.PI * 2); ctx.fill(); // 内部漩涡 ctx.shadowBlur = 0; ctx.rotate(i.swirlAngle); ctx.strokeStyle = "rgba(253,244,255,0.7)"; ctx.lineWidth = 1.5; ctx.beginPath(); for(let t = 0; t < Math.PI * 2; t += 0.3){ const r = t / (Math.PI * 2) * i.radius * 0.8; const x = Math.cos(t * 2) * r; const y = Math.sin(t * 2) * r; if (t === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.stroke(); ctx.restore(); } function drawBeacon(ctx, b) { if (b.collected) return; ctx.save(); ctx.translate(b.x, b.y); const pulse = 0.5 + 0.5 * Math.sin(b.pulsePhase); ctx.shadowBlur = 25; ctx.shadowColor = C.beacon; // 立柱光束(向上) const beamGrad = ctx.createLinearGradient(0, -b.radius * 4, 0, b.radius); beamGrad.addColorStop(0, "rgba(251,191,36,0)"); beamGrad.addColorStop(0.5, `rgba(251,191,36,${0.3 + pulse * 0.2})`); beamGrad.addColorStop(1, `rgba(251,191,36,${0.5 + pulse * 0.3})`); ctx.fillStyle = beamGrad; ctx.beginPath(); ctx.moveTo(-b.radius * 0.5, 0); ctx.lineTo(-b.radius * 0.2, -b.radius * 4); ctx.lineTo(b.radius * 0.2, -b.radius * 4); ctx.lineTo(b.radius * 0.5, 0); ctx.closePath(); ctx.fill(); // 旋转光环 ctx.rotate(b.rotation); ctx.beginPath(); ctx.ellipse(0, 0, b.radius * (1.2 + pulse * 0.2), b.radius * 0.4, 0, 0, Math.PI * 2); ctx.strokeStyle = `rgba(251,191,36,${0.5 + pulse * 0.3})`; ctx.lineWidth = 2; ctx.stroke(); // 核心 ctx.shadowBlur = 0; const coreGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, b.radius * 0.6); coreGrad.addColorStop(0, C.beaconCore); coreGrad.addColorStop(0.7, C.beacon); coreGrad.addColorStop(1, "#92400e"); ctx.fillStyle = coreGrad; ctx.beginPath(); ctx.arc(0, 0, b.radius * 0.6, 0, Math.PI * 2); ctx.fill(); ctx.restore(); } function drawStargate(ctx, g, ship) { ctx.save(); ctx.translate(g.x, g.y); const dist = Math.hypot(ship.x - g.x, ship.y - g.y); const proximity = Math.max(0, 1 - dist / 300); const pulse = 0.5 + 0.5 * Math.sin(g.pulsePhase); ctx.shadowBlur = 25 + proximity * 30; ctx.shadowColor = C.stargate; // 外旋涡(多层旋转弧) for(let i = 0; i < 4; i++){ ctx.save(); ctx.rotate(g.rotation * (i % 2 === 0 ? 1 : -1) * (1 + i * 0.3)); ctx.beginPath(); const ringR = g.radius * (1 + i * 0.25); ctx.arc(0, 0, ringR, 0, Math.PI * 1.5); ctx.strokeStyle = `rgba(251,113,133,${(0.3 + pulse * 0.2) * (1 - i * 0.15)})`; ctx.lineWidth = 3 - i * 0.5; ctx.stroke(); ctx.restore(); } // 核心旋涡 const coreGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, g.radius); coreGrad.addColorStop(0, C.stargateCore); coreGrad.addColorStop(0.4, C.stargate); coreGrad.addColorStop(0.8, "#9f1239"); coreGrad.addColorStop(1, "rgba(159,18,57,0)"); ctx.fillStyle = coreGrad; ctx.beginPath(); ctx.arc(0, 0, g.radius * (0.9 + pulse * 0.1), 0, Math.PI * 2); ctx.fill(); // 吸入粒子(接近时) ctx.shadowBlur = 0; if (proximity > 0.1) { for(let i = 0; i < 8; i++){ const ang = g.rotation * 2 + i / 8 * Math.PI * 2; const r = g.radius * (0.8 + 0.6 * Math.sin(g.pulsePhase + i)); const px = Math.cos(ang) * r; const py = Math.sin(ang) * r; ctx.fillStyle = `rgba(254,205,211,${proximity * 0.8})`; ctx.beginPath(); ctx.arc(px, py, 2, 0, Math.PI * 2); ctx.fill(); } } // 提示光环(接近时) if (proximity > 0.3) { ctx.beginPath(); ctx.arc(0, 0, g.radius * 1.6, 0, Math.PI * 2); ctx.strokeStyle = `rgba(251,113,133,${proximity * 0.4})`; ctx.lineWidth = 2; ctx.setLineDash([ 8, 8 ]); ctx.stroke(); ctx.setLineDash([]); } ctx.restore(); } function drawParticle(ctx, p) { const alpha = Math.max(0, p.life / p.maxLife); const size = p.shrink ? p.size * alpha : p.size; if (size < 0.3) return; ctx.globalAlpha = alpha; ctx.fillStyle = p.color; ctx.beginPath(); ctx.arc(p.x, p.y, size, 0, Math.PI * 2); ctx.fill(); ctx.globalAlpha = 1; } // ============================================================ // BOSS 绘制 // ============================================================ function drawBoss(ctx, b) { ctx.save(); ctx.translate(b.x, b.y); const breath = 1 + 0.06 * Math.sin(b.breathPhase); const pulse = 0.5 + 0.5 * Math.sin(b.pulsePhase); // 阶段颜色(rose 主色 + fuchsia 辉光) const phaseColor = b.attackPhase === 1 ? "#fb7185" : b.attackPhase === 2 ? "#f43f5e" : "#e879f9"; ctx.shadowBlur = 40; ctx.shadowColor = C.bossGlow; // 外层旋转环(多层) for(let i = 0; i < 3; i++){ ctx.save(); ctx.rotate(b.rotation * (i % 2 === 0 ? 1 : -1) * (1 + i * 0.4)); ctx.beginPath(); const ringR = b.radius * (1.15 + i * 0.18) * breath; const segs = 24; for(let s = 0; s < segs; s++){ const a = s / segs * Math.PI * 2; const r = ringR + Math.sin(b.pulsePhase * 2 + s * 0.6) * 4; const x = Math.cos(a) * r; const y = Math.sin(a) * r; if (s === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.closePath(); ctx.strokeStyle = `${phaseColor}${i === 0 ? "cc" : "66"}`; ctx.lineWidth = 3 - i * 0.6; ctx.stroke(); ctx.restore(); } // 触手 / 光环(旋转的光带) ctx.save(); ctx.rotate(b.tentaclePhase); for(let i = 0; i < 6; i++){ ctx.save(); ctx.rotate(i / 6 * Math.PI * 2); ctx.beginPath(); const tlen = b.radius * 1.4; ctx.moveTo(b.radius * 0.6, 0); ctx.quadraticCurveTo(b.radius * 1.1 + Math.sin(b.tentaclePhase * 2 + i) * 10, Math.cos(b.pulsePhase + i) * 8, tlen, 0); ctx.strokeStyle = `rgba(232,121,249,${0.5 + 0.3 * pulse})`; ctx.lineWidth = 2.5; ctx.stroke(); // 触手尖端光点 ctx.fillStyle = "#fda4af"; ctx.beginPath(); ctx.arc(tlen, 0, 3, 0, Math.PI * 2); ctx.fill(); ctx.restore(); } ctx.restore(); // 内核(径向渐变) ctx.shadowBlur = 30; ctx.shadowColor = phaseColor; const coreGrad = ctx.createRadialGradient(0, 0, 0, 0, 0, b.radius * 0.85); coreGrad.addColorStop(0, "#ffffff"); coreGrad.addColorStop(0.2, C.bossCore); coreGrad.addColorStop(0.6, phaseColor); coreGrad.addColorStop(1, "#9f1239"); ctx.fillStyle = coreGrad; ctx.beginPath(); ctx.arc(0, 0, b.radius * 0.85 * breath, 0, Math.PI * 2); ctx.fill(); // 内部六边形纹理(旋转) ctx.shadowBlur = 0; ctx.save(); ctx.rotate(-b.rotation * 2); ctx.beginPath(); for(let i = 0; i < 6; i++){ const a = i / 6 * Math.PI * 2; const r = b.radius * 0.55; const x = Math.cos(a) * r; const y = Math.sin(a) * r; if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.closePath(); ctx.strokeStyle = `rgba(254,205,211,${0.6 + 0.2 * pulse})`; ctx.lineWidth = 2; ctx.stroke(); ctx.restore(); // 阶段标记(小圆点) ctx.save(); ctx.rotate(-b.rotation * 1.5); for(let i = 0; i < 3; i++){ const a = i / 3 * Math.PI * 2 - Math.PI / 2; const r = b.radius * 0.7; const x = Math.cos(a) * r; const y = Math.sin(a) * r; ctx.fillStyle = i < b.attackPhase ? "#fbbf24" : "rgba(255,255,255,0.2)"; ctx.beginPath(); ctx.arc(x, y, 3, 0, Math.PI * 2); ctx.fill(); } ctx.restore(); ctx.restore(); } // ============================================================ // 子弹绘制 // ============================================================ function drawBullet(ctx, b) { ctx.save(); ctx.translate(b.x, b.y); const ang = Math.atan2(b.vy, b.vx); ctx.rotate(ang); ctx.shadowBlur = 14; ctx.shadowColor = b.color; if (b.owner === "ship") { // 飞船子弹:emerald 椭圆 + 尾焰 const grad = ctx.createLinearGradient(-b.radius * 3, 0, b.radius, 0); grad.addColorStop(0, "rgba(52,211,153,0)"); grad.addColorStop(0.5, "rgba(52,211,153,0.6)"); grad.addColorStop(1, "#a7f3d0"); ctx.fillStyle = grad; ctx.beginPath(); ctx.ellipse(0, 0, b.radius * 1.8, b.radius * 0.8, 0, 0, Math.PI * 2); ctx.fill(); // 核心亮点 ctx.fillStyle = "#ffffff"; ctx.beginPath(); ctx.arc(b.radius * 0.6, 0, b.radius * 0.4, 0, Math.PI * 2); ctx.fill(); } else { // BOSS 子弹:rose / fuchsia 圆球 + 拖尾 const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, b.radius); if (b.homing) { grad.addColorStop(0, "#fdf4ff"); grad.addColorStop(0.6, "#e879f9"); grad.addColorStop(1, "#86198f"); } else { grad.addColorStop(0, "#ffe4e6"); grad.addColorStop(0.6, "#fb7185"); grad.addColorStop(1, "#9f1239"); } ctx.fillStyle = grad; ctx.beginPath(); ctx.arc(0, 0, b.radius, 0, Math.PI * 2); ctx.fill(); // 拖尾 ctx.shadowBlur = 0; ctx.fillStyle = `${b.color}55`; ctx.beginPath(); ctx.ellipse(-b.radius * 2, 0, b.radius * 2, b.radius * 0.5, 0, 0, Math.PI * 2); ctx.fill(); // 追踪弹旋转标记 if (b.homing) { ctx.rotate(Date.now() / 100); ctx.strokeStyle = "#fdf4ff"; ctx.lineWidth = 1; ctx.beginPath(); ctx.arc(0, 0, b.radius * 1.3, 0, Math.PI * 1.5); ctx.stroke(); } } ctx.restore(); } // ============================================================ // 道具绘制 // ============================================================ function drawPowerup(ctx, p) { if (p.collected) return; ctx.save(); ctx.translate(p.x, p.y); const pulse = 0.5 + 0.5 * Math.sin(p.pulsePhase); // 即将消失闪烁 const blink = p.life < 3 && Math.floor(Date.now() / 150) % 2 === 0; if (blink) ctx.globalAlpha = 0.5; const color = POWERUP_COLOR[p.powerupType]; ctx.shadowBlur = 22; ctx.shadowColor = color; // 外发光环 ctx.beginPath(); ctx.arc(0, 0, p.radius * (1.5 + pulse * 0.3), 0, Math.PI * 2); ctx.strokeStyle = `${color}40`; ctx.lineWidth = 2; ctx.stroke(); // 旋转六边形 ctx.rotate(p.rotation); ctx.beginPath(); for(let i = 0; i < 6; i++){ const a = i / 6 * Math.PI * 2; const r = p.radius; const x = Math.cos(a) * r; const y = Math.sin(a) * r; if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y); } ctx.closePath(); const grad = ctx.createRadialGradient(0, 0, 0, 0, 0, p.radius); grad.addColorStop(0, "#ffffff"); grad.addColorStop(0.5, color); grad.addColorStop(1, `${color}80`); ctx.fillStyle = grad; ctx.fill(); ctx.lineWidth = 1.5; ctx.strokeStyle = "#ffffffaa"; ctx.stroke(); // 内部图标(用文字符号代替 lucide,避免 React-Canvas 桥接) ctx.shadowBlur = 0; ctx.rotate(-p.rotation); ctx.fillStyle = "#ffffff"; ctx.font = "bold 12px sans-serif"; ctx.textAlign = "center"; ctx.textBaseline = "middle"; const sym = p.powerupType === "shield" ? "S" : p.powerupType === "energy" ? "E" : p.powerupType === "rapid" ? "R" : p.powerupType === "overdrive" ? "O" : "M"; ctx.fillText(sym, 0, 1); ctx.globalAlpha = 1; ctx.restore(); } function CruiseMode({ onClose }) { _s(); const canvasRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(null); const stateRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(null); const upgradesRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])((0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["defaultUpgrades"])()); const appliedUpgradesRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])([]); const rafRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(0); const lastTimeRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(0); const starsRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])([]); const keysRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(new Set()); const joystickRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])({ active: false, baseX: 0, baseY: 0, knobX: 0, knobY: 0, touchId: null }); const shootHeldRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(false); const rewardGrantedRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(false); const pausedRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(false); const phaseRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])("ready"); const lastResultRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(null); const hudRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])({ shield: 100, shieldMax: 100, energy: 100, energyMax: 100, score: 0, time: 0, duration: 60, crystals: 0, totalCrystals: 0, insights: 0, totalInsights: 0, beacons: 0, totalBeacons: 0, lowShield: false, isBossLevel: false, bossHp: 0, bossMaxHp: 0, bossPhase: 1, buffs: [], appliedUpgrades: [], pickupFlashColor: null }); const lastHudUpdateRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])(0); const sizeRef = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useRef"])({ w: 0, h: 0 }); const [phase, setPhase] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])("ready"); const [level, setLevel] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])(1); const [result, setResult] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])(null); const [stats, setStats] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])({ "CruiseMode.useState": ()=>("TURBOPACK compile-time truthy", 1) ? (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["loadCruiseStats"])() : "TURBOPACK unreachable" }["CruiseMode.useState"]); const [paused, setPaused] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])(false); const [isTouch] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])({ "CruiseMode.useState": ()=>("TURBOPACK compile-time value", "object") !== "undefined" && ("ontouchstart" in window || navigator.maxTouchPoints > 0) }["CruiseMode.useState"]); const [joystickVisual, setJoystickVisual] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])({ baseX: 0, baseY: 0, knobX: 0, knobY: 0, active: false }); const [pendingChoices, setPendingChoices] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])([]); const [selectedChoice, setSelectedChoice] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])(null); // 镜像 appliedUpgradesRef 用于渲染(ref 不能在 render 中读取) const [appliedUpgradesList, setAppliedUpgradesList] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])([]); const [hud, setHud] = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useState"])({ shield: 100, shieldMax: 100, energy: 100, energyMax: 100, score: 0, time: 0, duration: 60, crystals: 0, totalCrystals: 0, insights: 0, totalInsights: 0, beacons: 0, totalBeacons: 0, lowShield: false, isBossLevel: false, bossHp: 0, bossMaxHp: 0, bossPhase: 1, buffs: [], appliedUpgrades: [], pickupFlashColor: null }); // ---- 启动一局 ---- const startGame = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useCallback"])({ "CruiseMode.useCallback[startGame]": (lvl)=>{ const { w, h } = sizeRef.current; if (w === 0 || h === 0) return; const seed = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["cruiseSeed"])(lvl); const state = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["generateLevel"])(lvl, seed, w, h, upgradesRef.current, appliedUpgradesRef.current); state.phase = "playing"; stateRef.current = state; rewardGrantedRef.current = false; lastResultRef.current = null; setResult(null); setLevel(lvl); setPhase("playing"); phaseRef.current = "playing"; setPaused(false); pausedRef.current = false; setSelectedChoice(null); // 重置 HUD hudRef.current = { shield: state.ship.shield, shieldMax: __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["CRUISE_CONFIG"].shieldMax + state.upgrades.shieldMaxBonus, energy: state.ship.energy, energyMax: __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["CRUISE_CONFIG"].energyMax + state.upgrades.energyMaxBonus, score: 0, time: 0, duration: state.durationSec, crystals: 0, totalCrystals: state.totalCrystals, insights: 0, totalInsights: state.totalInsights, beacons: 0, totalBeacons: state.totalBeacons, lowShield: false, isBossLevel: state.isBossLevel, bossHp: state.boss?.hp ?? 0, bossMaxHp: state.boss?.maxHp ?? 0, bossPhase: state.boss?.attackPhase ?? 1, buffs: [], appliedUpgrades: state.appliedUpgrades, pickupFlashColor: null }; setHud({ ...hudRef.current }); } }["CruiseMode.useCallback[startGame]"], []); // ---- 加载统计(已用 useState initializer 初始化,无需 effect)---- // ---- 检测触摸设备(用 useState initializer 避免 effect 内 setState)---- // 已在 useState 初始化时检测,此处无需 effect // ---- Canvas 初始化 + Resize ---- (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useEffect"])({ "CruiseMode.useEffect": ()=>{ const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const resize = { "CruiseMode.useEffect.resize": ()=>{ const dpr = Math.min(window.devicePixelRatio || 1, 2); const w = window.innerWidth; const h = window.innerHeight; canvas.width = Math.floor(w * dpr); canvas.height = Math.floor(h * dpr); canvas.style.width = w + "px"; canvas.style.height = h + "px"; ctx.setTransform(dpr, 0, 0, dpr, 0, 0); sizeRef.current = { w, h }; starsRef.current = generateStars(w, h); if (stateRef.current) { stateRef.current.worldWidth = w; stateRef.current.worldHeight = h; } } }["CruiseMode.useEffect.resize"]; resize(); window.addEventListener("resize", resize); return ({ "CruiseMode.useEffect": ()=>window.removeEventListener("resize", resize) })["CruiseMode.useEffect"]; } }["CruiseMode.useEffect"], []); // ---- 键盘控制 ---- (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useEffect"])({ "CruiseMode.useEffect": ()=>{ const down = { "CruiseMode.useEffect.down": (e)=>{ const k = e.key.toLowerCase(); if ([ "w", "a", "s", "d", "arrowup", "arrowdown", "arrowleft", "arrowright" ].includes(k)) { keysRef.current.add(k); e.preventDefault(); } else if (k === " " || k === "spacebar") { // 空格射击 shootHeldRef.current = true; e.preventDefault(); } else if (k === "p") { if (phaseRef.current === "playing") { const np = !pausedRef.current; pausedRef.current = np; setPaused(np); } } else if (k === "escape") { onClose(); } } }["CruiseMode.useEffect.down"]; const up = { "CruiseMode.useEffect.up": (e)=>{ const k = e.key.toLowerCase(); if ([ "w", "a", "s", "d", "arrowup", "arrowdown", "arrowleft", "arrowright" ].includes(k)) { keysRef.current.delete(k); } else if (k === " " || k === "spacebar") { shootHeldRef.current = false; } } }["CruiseMode.useEffect.up"]; window.addEventListener("keydown", down); window.addEventListener("keyup", up); return ({ "CruiseMode.useEffect": ()=>{ window.removeEventListener("keydown", down); window.removeEventListener("keyup", up); } })["CruiseMode.useEffect"]; } }["CruiseMode.useEffect"], [ onClose ]); // ---- 失焦自动暂停 ---- (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useEffect"])({ "CruiseMode.useEffect": ()=>{ const onBlur = { "CruiseMode.useEffect.onBlur": ()=>{ shootHeldRef.current = false; if (phaseRef.current === "playing") { pausedRef.current = true; setPaused(true); } } }["CruiseMode.useEffect.onBlur"]; window.addEventListener("blur", onBlur); document.addEventListener("visibilitychange", onBlur); return ({ "CruiseMode.useEffect": ()=>{ window.removeEventListener("blur", onBlur); document.removeEventListener("visibilitychange", onBlur); } })["CruiseMode.useEffect"]; } }["CruiseMode.useEffect"], []); // ---- 触摸摇杆 + 射击按钮 ---- (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useEffect"])({ "CruiseMode.useEffect": ()=>{ const onStart = { "CruiseMode.useEffect.onStart": (e)=>{ if (phaseRef.current !== "playing" || pausedRef.current) return; for(let i = 0; i < e.changedTouches.length; i++){ const t = e.changedTouches[i]; // 右下区域:射击按钮 if (t.clientX > window.innerWidth * 0.65 && t.clientY > window.innerHeight * 0.55) { shootHeldRef.current = true; e.preventDefault(); continue; } // 左下区域激活摇杆 if (t.clientX < window.innerWidth * 0.5 && t.clientY > window.innerHeight * 0.35) { if (joystickRef.current.active) continue; joystickRef.current = { active: true, baseX: t.clientX, baseY: t.clientY, knobX: 0, knobY: 0, touchId: t.identifier }; setJoystickVisual({ baseX: t.clientX, baseY: t.clientY, knobX: 0, knobY: 0, active: true }); e.preventDefault(); return; } } } }["CruiseMode.useEffect.onStart"]; const onMove = { "CruiseMode.useEffect.onMove": (e)=>{ if (!joystickRef.current.active) return; for(let i = 0; i < e.changedTouches.length; i++){ const t = e.changedTouches[i]; if (t.identifier !== joystickRef.current.touchId) continue; const dx = t.clientX - joystickRef.current.baseX; const dy = t.clientY - joystickRef.current.baseY; const maxR = 55; const mag = Math.hypot(dx, dy); const clampedMag = Math.min(mag, maxR); const nx = mag > 0 ? dx / mag * clampedMag : 0; const ny = mag > 0 ? dy / mag * clampedMag : 0; joystickRef.current.knobX = nx / maxR; // -1 ~ 1 joystickRef.current.knobY = ny / maxR; setJoystickVisual({ baseX: joystickRef.current.baseX, baseY: joystickRef.current.baseY, knobX: nx, knobY: ny, active: true }); e.preventDefault(); return; } } }["CruiseMode.useEffect.onMove"]; const onEnd = { "CruiseMode.useEffect.onEnd": (e)=>{ for(let i = 0; i < e.changedTouches.length; i++){ const t = e.changedTouches[i]; if (t.identifier === joystickRef.current.touchId) { joystickRef.current = { active: false, baseX: 0, baseY: 0, knobX: 0, knobY: 0, touchId: null }; setJoystickVisual({ baseX: 0, baseY: 0, knobX: 0, knobY: 0, active: false }); } // 右下区域松开 → 停止射击 if (t.clientX > window.innerWidth * 0.65 && t.clientY > window.innerHeight * 0.55) { shootHeldRef.current = false; } } e.preventDefault(); } }["CruiseMode.useEffect.onEnd"]; window.addEventListener("touchstart", onStart, { passive: false }); window.addEventListener("touchmove", onMove, { passive: false }); window.addEventListener("touchend", onEnd, { passive: false }); window.addEventListener("touchcancel", onEnd, { passive: false }); return ({ "CruiseMode.useEffect": ()=>{ window.removeEventListener("touchstart", onStart); window.removeEventListener("touchmove", onMove); window.removeEventListener("touchend", onEnd); window.removeEventListener("touchcancel", onEnd); } })["CruiseMode.useEffect"]; } }["CruiseMode.useEffect"], []); // ---- 游戏主循环 ---- (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useEffect"])({ "CruiseMode.useEffect": ()=>{ const canvas = canvasRef.current; if (!canvas) return; const ctx = canvas.getContext("2d"); if (!ctx) return; const loop = { "CruiseMode.useEffect.loop": (time)=>{ rafRef.current = requestAnimationFrame(loop); const dt = lastTimeRef.current === 0 ? 16 : time - lastTimeRef.current; lastTimeRef.current = time; const dtSec = Math.min(dt / 1000, 0.05); const { w, h } = sizeRef.current; if (w === 0 || h === 0) return; const state = stateRef.current; const playing = state && state.phase === "playing" && !pausedRef.current; // ---- 更新 ---- if (playing && state) { // 计算输入 let dx = 0; let dy = 0; const keys = keysRef.current; if (keys.has("w") || keys.has("arrowup")) dy -= 1; if (keys.has("s") || keys.has("arrowdown")) dy += 1; if (keys.has("a") || keys.has("arrowleft")) dx -= 1; if (keys.has("d") || keys.has("arrowright")) dx += 1; // 摇杆覆盖 if (joystickRef.current.active) { dx = joystickRef.current.knobX; dy = joystickRef.current.knobY; } const input = { dx, dy, active: Math.abs(dx) > 0.05 || Math.abs(dy) > 0.05, shoot: shootHeldRef.current }; const res = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["updateCruise"])(state, dt, input); if (res) { // 结算 lastResultRef.current = res; setResult(res); setPhase(res.phase); phaseRef.current = res.phase; if (!rewardGrantedRef.current) { rewardGrantedRef.current = true; __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$store$2f$gameStore$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$locals$3e$__["useGameStore"].getState().grantCruiseReward(res.rewards); const newStats = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["recordRun"])(res); setStats(newStats); } } // 更新 HUD ref hudRef.current = { shield: state.ship.shield, shieldMax: __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["CRUISE_CONFIG"].shieldMax + state.upgrades.shieldMaxBonus, energy: state.ship.energy, energyMax: __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["CRUISE_CONFIG"].energyMax + state.upgrades.energyMaxBonus, score: state.score, time: state.timeSec, duration: state.durationSec, crystals: state.collectedCrystals, totalCrystals: state.totalCrystals, insights: state.collectedInsights, totalInsights: state.totalInsights, beacons: state.collectedBeacons, totalBeacons: state.totalBeacons, lowShield: state.flashLowShield, isBossLevel: state.isBossLevel, bossHp: state.boss?.hp ?? 0, bossMaxHp: state.boss?.maxHp ?? 0, bossPhase: state.boss?.attackPhase ?? 1, buffs: [ ...state.activeBuffs ], appliedUpgrades: state.appliedUpgrades, pickupFlashColor: state.pickupFlash?.color ?? null }; // 节流更新 React HUD(~12fps) if (time - lastHudUpdateRef.current > 80) { lastHudUpdateRef.current = time; setHud({ ...hudRef.current }); } } // ---- 渲染 ---- // 背景 ctx.fillStyle = "#050410"; ctx.fillRect(0, 0, w, h); // 屏幕震动偏移 let shakeX = 0; let shakeY = 0; if (state && state.shakeTimer > 0) { const intensity = state.shakeAmount * (state.shakeTimer / __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["CRUISE_CONFIG"].shakeMs); shakeX = (Math.random() - 0.5) * intensity; shakeY = (Math.random() - 0.5) * intensity; } ctx.save(); ctx.translate(shakeX, shakeY); // 视差星空 const shipVx = state ? state.ship.vx : 0; const shipVy = state ? state.ship.vy : 0; drawStars(ctx, starsRef.current, dtSec, w, h, shipVx, shipVy); // 实体 if (state) { // 星门优先(在底层) for (const e of state.entities){ if (e.type === "stargate") drawStargate(ctx, e, state.ship); } // 风暴 for (const e of state.entities){ if (e.type === "storm") drawStorm(ctx, e); } // 陨石 for (const e of state.entities){ if (e.type === "asteroid") drawAsteroid(ctx, e); } // 道具 for (const p of state.powerups)drawPowerup(ctx, p); // 收集物 for (const e of state.entities){ if (e.type === "crystal") drawCrystal(ctx, e); else if (e.type === "insight") drawInsight(ctx, e); else if (e.type === "beacon") drawBeacon(ctx, e); } // 粒子 for (const p of state.particles)drawParticle(ctx, p); // 子弹 for (const b of state.bullets)drawBullet(ctx, b); // BOSS(在飞船之下绘制) if (state.boss) drawBoss(ctx, state.boss); // 飞船(最上层) if (state.phase === "playing" || state.phase === "won") { drawShip(ctx, state.ship, state.invulnTimer > 0, state.activeBuffs); } } ctx.restore(); // 低护盾红色边框(不受震动影响) if (state && state.flashLowShield && state.phase === "playing") { const pulse = 0.3 + 0.3 * Math.sin(time / 150); ctx.strokeStyle = `rgba(251,113,133,${pulse})`; ctx.lineWidth = 6; ctx.strokeRect(3, 3, w - 6, h - 6); } // 道具拾取屏幕闪光(边缘渐变) if (state && state.pickupFlash && state.phase === "playing") { const alpha = state.pickupFlash.timer / 400; const c = state.pickupFlash.color; const grad = ctx.createRadialGradient(w / 2, h / 2, Math.min(w, h) * 0.3, w / 2, h / 2, Math.max(w, h) * 0.7); grad.addColorStop(0, "rgba(0,0,0,0)"); grad.addColorStop(1, `${c}${Math.round(alpha * 100).toString(16).padStart(2, "0")}`); ctx.fillStyle = grad; ctx.fillRect(0, 0, w, h); } } }["CruiseMode.useEffect.loop"]; rafRef.current = requestAnimationFrame(loop); return ({ "CruiseMode.useEffect": ()=>cancelAnimationFrame(rafRef.current) })["CruiseMode.useEffect"]; } }["CruiseMode.useEffect"], []); // ---- 暂停切换 ---- const togglePause = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useCallback"])({ "CruiseMode.useCallback[togglePause]": ()=>{ if (phaseRef.current !== "playing") return; const np = !pausedRef.current; pausedRef.current = np; setPaused(np); } }["CruiseMode.useCallback[togglePause]"], []); // ---- 退出 ---- const handleExit = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useCallback"])({ "CruiseMode.useCallback[handleExit]": ()=>{ onClose(); } }["CruiseMode.useCallback[handleExit]"], [ onClose ]); // ---- 进入升级选择阶段(won → choosing) ---- const goToChoosing = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useCallback"])({ "CruiseMode.useCallback[goToChoosing]": ()=>{ if (!lastResultRef.current) return; // 失败不进入选择 if (lastResultRef.current.phase !== "won") return; const choices = (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["rollUpgradeChoices"])(3, appliedUpgradesRef.current.map({ "CruiseMode.useCallback[goToChoosing].choices": (c)=>c.id }["CruiseMode.useCallback[goToChoosing].choices"])); setPendingChoices(choices); setSelectedChoice(null); setPhase("choosing"); phaseRef.current = "choosing"; } }["CruiseMode.useCallback[goToChoosing]"], []); // ---- 选择一张升级卡 ---- const handlePickUpgrade = (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$index$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["useCallback"])({ "CruiseMode.useCallback[handlePickUpgrade]": (idx)=>{ const card = pendingChoices[idx]; if (!card) return; setSelectedChoice(idx); // 应用升级 (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["applyUpgradeCard"])(upgradesRef.current, card); appliedUpgradesRef.current = [ ...appliedUpgradesRef.current, card ]; setAppliedUpgradesList(appliedUpgradesRef.current); // 延迟跳转到下一关(让动画播放) setTimeout({ "CruiseMode.useCallback[handlePickUpgrade]": ()=>{ if (lastResultRef.current) { startGame(lastResultRef.current.level + 1); } } }["CruiseMode.useCallback[handlePickUpgrade]"], 700); } }["CruiseMode.useCallback[handlePickUpgrade]"], [ pendingChoices, startGame ]); // ============================================================ // 渲染 // ============================================================ const shieldPct = hud.shieldMax > 0 ? Math.max(0, Math.min(100, hud.shield / hud.shieldMax * 100)) : 0; const shieldColor = shieldPct > 60 ? "#34d399" : shieldPct > 30 ? "#fbbf24" : "#fb7185"; const energyPct = hud.energyMax > 0 ? Math.max(0, Math.min(100, hud.energy / hud.energyMax * 100)) : 0; const timeLeft = Math.max(0, hud.duration - hud.time); const bossHpPct = hud.bossMaxHp > 0 ? hud.bossHp / hud.bossMaxHp * 100 : 0; return /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "fixed inset-0 z-50 bg-[#050410] overflow-hidden select-none", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("canvas", { ref: canvasRef, className: "absolute inset-0 w-full h-full touch-none" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1409, columnNumber: 7 }, this), phase === "playing" && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Fragment"], { children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute top-3 left-3 flex flex-col gap-2 min-w-[180px]", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-xl p-2.5 border-white/10", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2 mb-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Shield$3e$__["Shield"], { className: "h-3.5 w-3.5", style: { color: shieldColor } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1421, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-[10px] text-muted-foreground uppercase tracking-wider", children: "护盾" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1422, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "ml-auto font-mono text-xs font-bold", style: { color: shieldColor }, children: Math.round(hud.shield) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1423, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1420, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-2 rounded-full bg-black/50 overflow-hidden border border-white/5", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-full rounded-full transition-all duration-150", style: { width: `${shieldPct}%`, background: `linear-gradient(90deg, ${shieldColor}, ${shieldColor}dd)`, boxShadow: `0 0 8px ${shieldColor}aa` } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1428, columnNumber: 17 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1427, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2 mt-2 mb-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$zap$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Zap$3e$__["Zap"], { className: "h-3.5 w-3.5 text-fuchsia-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1438, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-[10px] text-muted-foreground uppercase tracking-wider", children: "能量" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1439, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "ml-auto font-mono text-xs font-bold text-fuchsia-200", children: Math.round(hud.energy) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1440, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1437, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-2 rounded-full bg-black/50 overflow-hidden border border-white/5", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-full rounded-full transition-all duration-150", style: { width: `${energyPct}%`, background: "linear-gradient(90deg, #e879f9, #c026d3)", boxShadow: "0 0 8px rgba(232,121,249,0.6)" } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1445, columnNumber: 17 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1444, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1419, columnNumber: 13 }, this), hud.buffs.length > 0 && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-xl p-2 border-white/10 flex flex-col gap-1", children: hud.buffs.map((buff, i)=>{ const color = POWERUP_COLOR[buff.type]; const pct = Math.max(0, buff.remaining / buff.total * 100); const label = buff.type === "shield" ? "护盾" : buff.type === "energy" ? "能量" : buff.type === "rapid" ? "急速" : buff.type === "overdrive" ? "过载" : "磁吸"; return /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-2 w-2 rounded-full", style: { background: color, boxShadow: `0 0 6px ${color}` } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1469, columnNumber: 23 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-[10px] text-white/80", style: { color }, children: label }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1470, columnNumber: 23 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex-1 h-1 rounded-full bg-black/40 overflow-hidden", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-full rounded-full", style: { width: `${pct}%`, background: color } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1472, columnNumber: 25 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1471, columnNumber: 23 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-[9px] text-muted-foreground w-6 text-right", children: [ Math.ceil(buff.remaining), "s" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1474, columnNumber: 23 }, this) ] }, i, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1468, columnNumber: 21 }, this); }) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1457, columnNumber: 15 }, this), hud.appliedUpgrades.length > 0 && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-xl p-1.5 border-white/10 flex flex-wrap gap-1 max-w-[200px]", children: hud.appliedUpgrades.map((u, i)=>/*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-5 w-5 rounded-md flex items-center justify-center border", style: { borderColor: `${u.color}80`, background: `${u.color}20` }, title: u.title, children: (()=>{ const Icon = UPGRADE_ICON_MAP[u.icon] ?? __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$sparkles$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Sparkles$3e$__["Sparkles"]; return /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(Icon, { className: "h-3 w-3", style: { color: u.color } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1492, columnNumber: 30 }, this); })() }, i, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1484, columnNumber: 19 }, this)) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1482, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1418, columnNumber: 11 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute top-3 left-1/2 -translate-x-1/2 flex flex-col items-center gap-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-xl px-4 py-2 border-white/10 flex items-center gap-4", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-center", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground uppercase tracking-wider", children: "关卡" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1504, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-sm font-bold text-amber-200", children: [ "L", level, hud.isBossLevel && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$skull$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Skull$3e$__["Skull"], { className: "inline h-3 w-3 ml-0.5 text-rose-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1506, columnNumber: 47 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1505, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1503, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "w-px h-7 bg-white/10" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1509, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-center", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground uppercase tracking-wider", children: "分数" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1511, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-sm font-bold text-emerald-200", children: (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$config$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["formatNum"])(hud.score) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1512, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1510, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "w-px h-7 bg-white/10" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1514, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-center min-w-[52px]", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground uppercase tracking-wider flex items-center justify-center gap-0.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$clock$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Clock$3e$__["Clock"], { className: "h-2.5 w-2.5" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1517, columnNumber: 19 }, this), "用时" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1516, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-sm font-bold text-rose-200", children: [ Math.floor(timeLeft / 60), ":", String(Math.floor(timeLeft % 60)).padStart(2, "0") ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1519, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1515, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1502, columnNumber: 13 }, this), hud.isBossLevel && hud.bossMaxHp > 0 && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg px-3 py-1.5 border-rose-400/30 min-w-[260px] sm:min-w-[320px]", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center justify-between mb-0.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$skull$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Skull$3e$__["Skull"], { className: "h-3 w-3 text-rose-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1529, columnNumber: 21 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-[10px] text-rose-200 font-bold tracking-wider", children: "BOSS" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1530, columnNumber: 21 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1528, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-1", children: [ 1, 2, 3 ].map((p)=>/*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: `h-1.5 w-1.5 rounded-full ${p <= hud.bossPhase ? "bg-rose-400" : "bg-white/15"}` }, p, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1534, columnNumber: 23 }, this)) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1532, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1527, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-2.5 rounded-full bg-black/60 overflow-hidden border border-rose-400/20", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-full rounded-full transition-all duration-200", style: { width: `${bossHpPct}%`, background: "linear-gradient(90deg, #fb7185, #e879f9)", boxShadow: "0 0 12px rgba(232,121,249,0.7)" } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1542, columnNumber: 19 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1541, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1526, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1501, columnNumber: 11 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute top-3 right-3 flex items-start gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-xl p-2 border-white/10 flex flex-col gap-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$gem$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Gem$3e$__["Gem"], { className: "h-3 w-3 text-emerald-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1559, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-xs font-bold text-emerald-200", children: [ hud.crystals, /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground/60", children: [ "/", hud.totalCrystals ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1561, columnNumber: 33 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1560, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1558, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$brain$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Brain$3e$__["Brain"], { className: "h-3 w-3 text-fuchsia-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1565, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-xs font-bold text-fuchsia-200", children: [ hud.insights, /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground/60", children: [ "/", hud.totalInsights ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1567, columnNumber: 33 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1566, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1564, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$radio$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Radio$3e$__["Radio"], { className: "h-3 w-3 text-amber-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1571, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-xs font-bold text-amber-200", children: [ hud.beacons, /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground/60", children: [ "/", hud.totalBeacons ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1573, columnNumber: 32 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1572, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1570, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1557, columnNumber: 13 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { size: "icon", variant: "ghost", onClick: togglePause, className: "h-8 w-8 glass border-white/10 hover:bg-white/10 text-white/80", "aria-label": "暂停", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$pause$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Pause$3e$__["Pause"], { className: "h-4 w-4" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1584, columnNumber: 15 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1577, columnNumber: 13 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { size: "icon", variant: "ghost", onClick: handleExit, className: "h-8 w-8 glass border-rose-400/30 hover:bg-rose-500/20 text-rose-200", "aria-label": "退出", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$x$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__X$3e$__["X"], { className: "h-4 w-4" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1593, columnNumber: 15 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1586, columnNumber: 13 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1556, columnNumber: 11 }, this), !isTouch && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 glass rounded-full px-4 py-1.5 border-white/10 text-[11px] text-muted-foreground", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-white/80", children: "WASD" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1600, columnNumber: 15 }, this), " / ", /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-white/80", children: "方向键" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1600, columnNumber: 71 }, this), " 移动 · ", /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-emerald-300", children: "空格" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1600, columnNumber: 129 }, this), " 射击 · ", /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-white/80", children: "P" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1600, columnNumber: 189 }, this), " 暂停 · ", /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-white/80", children: "Esc" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1600, columnNumber: 245 }, this), " 退出" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1599, columnNumber: 13 }, this), isTouch && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute bottom-4 left-1/2 -translate-x-1/2 glass rounded-full px-3 py-1 border-white/10 text-[10px] text-muted-foreground pointer-events-none", children: "左下摇杆 · 右下射击" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1604, columnNumber: 13 }, this), isTouch && joystickVisual.active && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute pointer-events-none", style: { left: joystickVisual.baseX, top: joystickVisual.baseY, transform: "translate(-50%, -50%)" }, children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "relative h-28 w-28 rounded-full border-2 border-amber-400/40 bg-amber-500/5 backdrop-blur-sm", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute h-12 w-12 rounded-full border-2 border-amber-300 bg-amber-400/30 backdrop-blur", style: { left: "50%", top: "50%", transform: `translate(calc(-50% + ${joystickVisual.knobX}px), calc(-50% + ${joystickVisual.knobY}px))`, boxShadow: "0 0 16px rgba(251,191,36,0.6)" } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1613, columnNumber: 17 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1612, columnNumber: 15 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1611, columnNumber: 13 }, this), isTouch && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("button", { "aria-label": "射击", className: "absolute bottom-20 right-6 h-20 w-20 rounded-full border-2 border-emerald-400/50 bg-emerald-500/15 backdrop-blur-md flex items-center justify-center pointer-events-none", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$crosshair$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Crosshair$3e$__["Crosshair"], { className: "h-9 w-9 text-emerald-300", style: { filter: "drop-shadow(0 0 8px rgba(52,211,153,0.8))" } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1632, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute inset-0 rounded-full border-2 border-emerald-400/30 animate-ping", style: { animationDuration: "2s" } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1633, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1628, columnNumber: 13 }, this), paused && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-10", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-2xl p-8 border-white/15 text-center max-w-xs", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$pause$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Pause$3e$__["Pause"], { className: "h-10 w-10 mx-auto mb-3 text-amber-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1641, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("h3", { className: "text-lg font-bold text-white mb-1", children: "已暂停" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1642, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("p", { className: "text-xs text-muted-foreground mb-5", children: "深空时间已凝固" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1643, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex flex-col gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { onClick: togglePause, className: "bg-amber-500/20 border border-amber-400/50 text-amber-100 hover:bg-amber-500/30", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$play$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Play$3e$__["Play"], { className: "h-4 w-4 mr-1.5" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1649, columnNumber: 21 }, this), "继续" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1645, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { variant: "ghost", onClick: handleExit, className: "text-rose-200 hover:bg-rose-500/10", children: "退出巡航" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1652, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1644, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1640, columnNumber: 15 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1639, columnNumber: 13 }, this) ] }, void 0, true), phase === "ready" && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute inset-0 flex items-center justify-center p-4 bg-gradient-to-b from-black/40 via-transparent to-black/60", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-2xl p-6 sm:p-8 border-amber-400/30 max-w-md w-full text-center relative overflow-hidden", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "pointer-events-none absolute -top-20 -left-20 h-40 w-40 rounded-full bg-amber-500/20 blur-3xl" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1670, columnNumber: 13 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "pointer-events-none absolute -bottom-20 -right-20 h-40 w-40 rounded-full bg-rose-500/20 blur-3xl" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1671, columnNumber: 13 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "relative", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] tracking-[0.3em] text-amber-300/70 mb-1", children: "DEEP SPACE CRUISE · v0.8" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1673, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("h2", { className: "text-3xl sm:text-4xl font-bold text-gradient mb-1", children: "深空巡航" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1674, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("p", { className: "text-xs text-muted-foreground mb-5", children: "操控飞船穿越陨石带,抵达星门 / 击败 BOSS" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1675, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "grid grid-cols-2 gap-2 mb-5 text-left", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2.5 border-white/10", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] text-muted-foreground", children: "起始关卡" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1679, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-lg font-bold text-amber-200", children: [ "L", level ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1680, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1678, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2.5 border-white/10", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] text-muted-foreground", children: "历史最高分" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1683, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-lg font-bold text-emerald-200", children: stats ? (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$config$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["formatNum"])(stats.highScore) : "—" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1684, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1682, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2.5 border-white/10", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] text-muted-foreground", children: "通关次数" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1689, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-lg font-bold text-fuchsia-200", children: stats ? stats.totalWins : 0 }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1690, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1688, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2.5 border-white/10", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] text-muted-foreground", children: "BOSS 击杀" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1695, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-lg font-bold text-rose-200", children: stats ? stats.bossKills : 0 }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1696, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1694, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1677, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-3 border-white/10 mb-5 text-left text-[11px] space-y-1", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$gem$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Gem$3e$__["Gem"], { className: "h-3 w-3 text-emerald-300 shrink-0" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1704, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground", children: "收集晶体碎片 → 晶体奖励" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1705, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1703, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$brain$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Brain$3e$__["Brain"], { className: "h-3 w-3 text-fuchsia-300 shrink-0" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1708, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground", children: "收集洞见光球 → 洞见奖励" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1709, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1707, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$radio$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Radio$3e$__["Radio"], { className: "h-3 w-3 text-amber-300 shrink-0" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1712, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground", children: "收集信标 → 接触进度" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1713, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1711, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$trophy$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Trophy$3e$__["Trophy"], { className: "h-3 w-3 text-rose-300 shrink-0" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1716, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground", children: "抵达星门通关 → +50% 奖励" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1717, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1715, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$skull$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Skull$3e$__["Skull"], { className: "h-3 w-3 text-rose-300 shrink-0" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1720, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground", children: "每 5 关 BOSS 战:击败 ×3 奖励" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1721, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1719, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$crosshair$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Crosshair$3e$__["Crosshair"], { className: "h-3 w-3 text-emerald-300 shrink-0" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1724, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground", children: "空格 / 右下角射击按钮 → 发射能量弹" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1725, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1723, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$sparkles$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Sparkles$3e$__["Sparkles"], { className: "h-3 w-3 text-fuchsia-300 shrink-0" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1728, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground", children: "通关后 3 选 1 强化卡牌(每局重置)" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1729, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1727, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1702, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { onClick: ()=>startGame(level), className: "flex-1 bg-amber-500/20 border border-amber-400/50 text-amber-100 hover:bg-amber-500/30 h-11", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$play$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Play$3e$__["Play"], { className: "h-4 w-4 mr-1.5" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1738, columnNumber: 19 }, this), "启动巡航" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1734, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { variant: "ghost", onClick: handleExit, className: "border border-white/10 text-white/70 hover:bg-white/10 h-11", children: "返回" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1741, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1733, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] text-muted-foreground/60 mt-3", children: isTouch ? "左下摇杆移动 · 右下射击" : "WASD / 方向键移动 · 空格射击 · P 暂停 · Esc 退出" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1749, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1672, columnNumber: 13 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1669, columnNumber: 11 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1668, columnNumber: 9 }, this), (phase === "won" || phase === "lost") && result && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute inset-0 flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: `glass rounded-2xl p-6 sm:p-8 max-w-md w-full relative overflow-hidden ${phase === "won" ? result.isBossLevel ? "border-fuchsia-400/50" : "border-emerald-400/40" : "border-rose-400/40"}`, children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: `pointer-events-none absolute -top-20 -left-20 h-40 w-40 rounded-full blur-3xl ${phase === "won" ? result.isBossLevel ? "bg-fuchsia-500/25" : "bg-emerald-500/20" : "bg-rose-500/20"}` }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1765, columnNumber: 13 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "relative", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: `text-[10px] tracking-[0.3em] mb-1 ${phase === "won" ? result.isBossLevel ? "text-fuchsia-300/70" : "text-emerald-300/70" : "text-rose-300/70"}`, children: phase === "won" ? result.isBossLevel ? "BOSS DEFEATED" : "MISSION COMPLETE" : "MISSION FAILED" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1771, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("h2", { className: `text-3xl font-bold mb-1 ${phase === "won" ? result.isBossLevel ? "text-fuchsia-300" : "text-emerald-300" : "text-rose-300"}`, style: { textShadow: `0 0 20px ${phase === "won" ? result.isBossLevel ? "rgba(232,121,249,0.5)" : "rgba(52,211,153,0.5)" : "rgba(251,113,133,0.5)"}` }, children: phase === "won" ? result.isBossLevel ? "BOSS 击破" : "巡航成功" : "巡航失败" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1778, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("p", { className: "text-xs text-muted-foreground mb-5", children: [ "关卡 L", result.level, " · 用时 ", Math.floor(result.durationSec / 60), ":", String(Math.floor(result.durationSec % 60)).padStart(2, "0") ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1786, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "grid grid-cols-3 gap-2 mb-4", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2 border-emerald-400/20 text-center", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$gem$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Gem$3e$__["Gem"], { className: "h-4 w-4 mx-auto text-emerald-300 mb-0.5" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1794, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-lg font-bold text-emerald-200", children: result.collectedCrystals }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1795, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground", children: "晶体碎片" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1798, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1793, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2 border-fuchsia-400/20 text-center", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$brain$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Brain$3e$__["Brain"], { className: "h-4 w-4 mx-auto text-fuchsia-300 mb-0.5" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1801, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-lg font-bold text-fuchsia-200", children: result.collectedInsights }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1802, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground", children: "洞见光球" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1805, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1800, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2 border-amber-400/20 text-center", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$radio$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Radio$3e$__["Radio"], { className: "h-4 w-4 mx-auto text-amber-300 mb-0.5" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1808, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-lg font-bold text-amber-200", children: result.collectedBeacons }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1809, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground", children: "信标" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1812, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1807, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1792, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "grid grid-cols-2 gap-2 mb-4", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2 border-white/10 flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$shield$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Shield$3e$__["Shield"], { className: "h-4 w-4 text-rose-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1819, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground", children: "剩余护盾" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1821, columnNumber: 21 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-sm font-bold text-rose-200", children: result.remainingShield }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1822, columnNumber: 21 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1820, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1818, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-2 border-white/10 flex items-center gap-2", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$trophy$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Trophy$3e$__["Trophy"], { className: "h-4 w-4 text-amber-300" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1828, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground", children: "得分" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1830, columnNumber: 21 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "font-mono text-sm font-bold text-amber-200", children: (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$config$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["formatNum"])(result.score) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1831, columnNumber: 21 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1829, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1827, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1817, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "glass rounded-lg p-3 border-emerald-400/20 mb-5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] text-muted-foreground uppercase tracking-wider mb-2", children: phase === "won" ? result.isBossLevel ? "BOSS 击败奖励 (×3)" : "通关奖励 (+50%)" : "残骸回收 (×50%)" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1840, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "space-y-1.5", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center justify-between", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "flex items-center gap-1.5 text-xs text-emerald-200", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$gem$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Gem$3e$__["Gem"], { className: "h-3 w-3" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1848, columnNumber: 23 }, this), " 晶体" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1847, columnNumber: 21 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-sm font-bold text-emerald-200", children: [ "+", (0, __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$config$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["formatNum"])(result.rewards.crystals) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1850, columnNumber: 21 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1846, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center justify-between", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "flex items-center gap-1.5 text-xs text-fuchsia-200", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$brain$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Brain$3e$__["Brain"], { className: "h-3 w-3" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1856, columnNumber: 23 }, this), " 洞见" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1855, columnNumber: 21 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-sm font-bold text-fuchsia-200", children: [ "+", result.rewards.insights.toFixed(1) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1858, columnNumber: 21 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1854, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center justify-between", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "flex items-center gap-1.5 text-xs text-amber-200", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$radio$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Radio$3e$__["Radio"], { className: "h-3 w-3" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1864, columnNumber: 23 }, this), " 接触" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1863, columnNumber: 21 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "font-mono text-sm font-bold text-amber-200", children: [ "+", result.rewards.contact.toFixed(1), "%" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1866, columnNumber: 21 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1862, columnNumber: 19 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1845, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[9px] text-muted-foreground/70 mt-2 pt-2 border-t border-white/5", children: "奖励已同步至主游戏" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1871, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1839, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex gap-2", children: [ phase === "won" && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { onClick: goToChoosing, className: "flex-1 bg-fuchsia-500/20 border border-fuchsia-400/50 text-fuchsia-100 hover:bg-fuchsia-500/30 h-10", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$sparkles$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Sparkles$3e$__["Sparkles"], { className: "h-4 w-4 mr-1" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1883, columnNumber: 21 }, this), "选择强化" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1879, columnNumber: 19 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { onClick: ()=>startGame(result.level), variant: phase === "won" ? "ghost" : "default", className: `${phase === "lost" ? "flex-1 bg-rose-500/20 border border-rose-400/50 text-rose-100 hover:bg-rose-500/30" : "border border-white/10 text-white/80 hover:bg-white/10"} h-10`, children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$rotate$2d$ccw$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__RotateCcw$3e$__["RotateCcw"], { className: "h-4 w-4 mr-1" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1896, columnNumber: 19 }, this), "重试" ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1887, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { variant: "ghost", onClick: handleExit, className: "border border-white/10 text-white/70 hover:bg-white/10 h-10", children: "返回" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1899, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1877, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1770, columnNumber: 13 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1760, columnNumber: 11 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1759, columnNumber: 9 }, this), phase === "choosing" && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute inset-0 flex items-center justify-center p-4 bg-black/70 backdrop-blur-md", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "w-full max-w-3xl", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-center mb-6", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] tracking-[0.4em] text-fuchsia-300/70 mb-1", children: "REINFORCEMENT PROTOCOL" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1917, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("h2", { className: "text-2xl sm:text-3xl font-bold text-gradient mb-1", children: "选择强化" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1918, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("p", { className: "text-xs text-muted-foreground", children: "星门共鸣释放能量,3 选 1 永久强化(本局有效)" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1919, columnNumber: 15 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1916, columnNumber: 13 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "grid grid-cols-1 sm:grid-cols-3 gap-3", children: pendingChoices.map((card, idx)=>{ const Icon = UPGRADE_ICON_MAP[card.icon] ?? __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$sparkles$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Sparkles$3e$__["Sparkles"]; const isSelected = selectedChoice === idx; const isFaded = selectedChoice !== null && !isSelected; return /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("button", { onClick: ()=>selectedChoice === null && handlePickUpgrade(idx), disabled: selectedChoice !== null, className: `group relative glass rounded-2xl p-5 border-2 transition-all duration-500 text-left overflow-hidden ${isSelected ? "scale-105 border-fuchsia-400 shadow-[0_0_30px_rgba(232,121,249,0.5)]" : isFaded ? "opacity-40 border-white/10" : "border-white/15 hover:border-white/30 hover:scale-[1.02] cursor-pointer"}`, style: { minHeight: "220px" }, children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "pointer-events-none absolute -top-10 -left-10 h-32 w-32 rounded-full blur-3xl opacity-40 transition-opacity group-hover:opacity-70", style: { background: card.color } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1941, columnNumber: 21 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "relative flex flex-col h-full", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "h-12 w-12 rounded-xl flex items-center justify-center mb-3 border", style: { background: `${card.color}20`, borderColor: `${card.color}80`, boxShadow: `0 0 16px ${card.color}40` }, children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(Icon, { className: "h-6 w-6", style: { color: card.color } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1954, columnNumber: 25 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1946, columnNumber: 23 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] font-mono uppercase tracking-wider mb-1", style: { color: card.color }, children: [ "强化 ", String(idx + 1).padStart(2, "0") ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1956, columnNumber: 23 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("h3", { className: "text-lg font-bold text-white mb-1.5", children: card.title }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1959, columnNumber: 23 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("p", { className: "text-xs text-muted-foreground mb-3", children: card.desc }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1960, columnNumber: 23 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "mt-auto pt-2 border-t border-white/5", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center justify-between text-[10px]", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-muted-foreground/70", children: "点击选择" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1963, columnNumber: 27 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$chevron$2d$right$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__ChevronRight$3e$__["ChevronRight"], { className: "h-3 w-3", style: { color: card.color } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1964, columnNumber: 27 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1962, columnNumber: 25 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1961, columnNumber: 23 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1945, columnNumber: 21 }, this), isSelected && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "absolute inset-0 flex items-center justify-center bg-fuchsia-500/10 backdrop-blur-[1px]", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-center", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$sparkles$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Sparkles$3e$__["Sparkles"], { className: "h-10 w-10 mx-auto text-fuchsia-300 animate-pulse", style: { filter: "drop-shadow(0 0 12px rgba(232,121,249,0.8))" } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1971, columnNumber: 27 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "mt-2 text-xs font-bold text-fuchsia-200 tracking-wider", children: "已激活" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1972, columnNumber: 27 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1970, columnNumber: 25 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1969, columnNumber: 23 }, this) ] }, card.id, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1927, columnNumber: 19 }, this); }) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1921, columnNumber: 13 }, this), appliedUpgradesList.length > 0 && /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "mt-5 glass rounded-xl p-3 border-white/10", children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-[10px] text-muted-foreground uppercase tracking-wider mb-2", children: "本局已激活强化" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1983, columnNumber: 17 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex flex-wrap gap-2", children: appliedUpgradesList.map((u, i)=>{ const Icon = UPGRADE_ICON_MAP[u.icon] ?? __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$lucide$2d$react$2f$dist$2f$esm$2f$icons$2f$sparkles$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$export__default__as__Sparkles$3e$__["Sparkles"]; return /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "flex items-center gap-1.5 rounded-md px-2 py-1 border", style: { borderColor: `${u.color}50`, background: `${u.color}15` }, children: [ /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(Icon, { className: "h-3 w-3", style: { color: u.color } }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1993, columnNumber: 25 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("span", { className: "text-[11px] text-white/85", children: u.title }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1994, columnNumber: 25 }, this) ] }, i, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1988, columnNumber: 23 }, this); }) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1984, columnNumber: 17 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1982, columnNumber: 15 }, this), /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])("div", { className: "text-center mt-4", children: /*#__PURE__*/ (0, __TURBOPACK__imported__module__$5b$project$5d2f$node_modules$2f$next$2f$dist$2f$compiled$2f$react$2f$jsx$2d$dev$2d$runtime$2e$js__$5b$app$2d$client$5d$__$28$ecmascript$29$__["jsxDEV"])(__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$ui$2f$button$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__["Button"], { variant: "ghost", onClick: handleExit, className: "border border-white/10 text-white/60 hover:bg-white/10 h-9", children: "退出巡航" }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 2002, columnNumber: 15 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 2001, columnNumber: 13 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1915, columnNumber: 11 }, this) }, void 0, false, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1914, columnNumber: 9 }, this) ] }, void 0, true, { fileName: "[project]/src/components/game/CruiseMode.tsx", lineNumber: 1408, columnNumber: 5 }, this); } _s(CruiseMode, "dRh+2G1Wc+HWMpPPcXFQlMrG/TA="); _c = CruiseMode; ; var _c; __turbopack_context__.k.register(_c, "CruiseMode"); if (typeof globalThis.$RefreshHelpers$ === 'object' && globalThis.$RefreshHelpers !== null) { __turbopack_context__.k.registerExports(__turbopack_context__.m, globalThis.$RefreshHelpers$); } }), "[project]/src/components/game/CruiseMode.tsx [app-client] (ecmascript)", ((__turbopack_context__) => { "use strict"; __turbopack_context__.s([ "CruiseMode", ()=>__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$game$2f$CruiseMode$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$locals$3e$__["CruiseMode"], "UPGRADE_POOL", ()=>__TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__["UPGRADE_POOL"] ]); var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$components$2f$game$2f$CruiseMode$2e$tsx__$5b$app$2d$client$5d$__$28$ecmascript$29$__$3c$locals$3e$__ = __turbopack_context__.i("[project]/src/components/game/CruiseMode.tsx [app-client] (ecmascript) "); var __TURBOPACK__imported__module__$5b$project$5d2f$src$2f$lib$2f$game$2f$cruise$2e$ts__$5b$app$2d$client$5d$__$28$ecmascript$29$__ = __turbopack_context__.i("[project]/src/lib/game/cruise.ts [app-client] (ecmascript)"); }), "[project]/src/components/game/CruiseMode.tsx [app-client] (ecmascript, next/dynamic entry)", ((__turbopack_context__) => { __turbopack_context__.n(__turbopack_context__.i("[project]/src/components/game/CruiseMode.tsx [app-client] (ecmascript)")); }), ]); //# sourceMappingURL=src_fe091346._.js.map