4988 lines
316 KiB
JavaScript
4988 lines
316 KiB
JavaScript
(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) <locals>", ((__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) <export default as X>");
|
||
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) <export default as Play>");
|
||
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) <export default as RotateCcw>");
|
||
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) <export default as ChevronRight>");
|
||
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) <export default as Pause>");
|
||
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) <export default as Gem>");
|
||
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) <export default as Brain>");
|
||
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) <export default as Radio>");
|
||
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) <export default as Shield>");
|
||
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) <export default as Zap>");
|
||
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) <export default as Clock>");
|
||
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) <export default as Trophy>");
|
||
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) <export default as Crosshair>");
|
||
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) <export default as Skull>");
|
||
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) <export default as Sparkles>");
|
||
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) <export default as Wind>");
|
||
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) <export default as Gauge>");
|
||
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) <export default as Feather>");
|
||
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) <export default as HeartPulse>");
|
||
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) <export default as Battery>");
|
||
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) <export default as Timer>");
|
||
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) <export default as Flame>");
|
||
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) <export default as Split>");
|
||
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) <export default as Magnet>");
|
||
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) <export default as Circle>");
|
||
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) <export default as ShieldCheck>");
|
||
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) <export default as ShieldHalf>");
|
||
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) <export default as Crown>");
|
||
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) <export default as Star>");
|
||
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) <export default as ShieldPlus>");
|
||
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) <export default as BatteryCharging>");
|
||
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) <locals>");
|
||
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) <locals>");
|
||
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
|