v0.7: CrystalOrb Canvas 粒子系统升级 + 角色属性系统(四维)
CrystalOrb 升级(P0 视觉震撼): - 从 CSS 动画重写为 Canvas 2D 粒子系统 - 环绕能量粒子(3层32个,emerald/fuchsia/rose,带拖尾) - 环境星尘(40个,闪烁漂移) - 点击爆发粒子 + 冲击波环(连击解锁更多层) - 晶核辉光呼吸 + 3层六边形纹理 + 鼠标视差 - VLM 视觉评分 8/10 角色属性系统(P1 RPG 深度): - 新增 attributes.ts 逻辑层 + AttributesPanel UI - 四维属性:探索力/智慧/勇气/灵感(emerald/fuchsia/amber/rose) - 两区加成公式(0-50线性,50-100递减) - 飞升获得属性点(ascensions×2+1),手动分配 - 完成活动获得属性经验,自动升级 - 接入 pulse/clickNode/resolveCurrentNode/grantCruiseReward/tickTide - 旧存档兼容(migrateAttributes) - 新增 2 项成就 + 第 8 个标签页「角色」 - VLM 视觉评分 7-8/10 lint 零错误;HTTP 200
This commit is contained in:
+21
-3
@@ -19,6 +19,7 @@ import { BeaconPanel } from "@/components/game/BeaconPanel";
|
||||
import { TutorialOverlay } from "@/components/game/TutorialOverlay";
|
||||
import { OfflineReportDialog } from "@/components/game/OfflineReportDialog";
|
||||
import { CruiseMode } from "@/components/game/CruiseMode";
|
||||
import { AttributesPanel } from "@/components/game/AttributesPanel";
|
||||
import {
|
||||
StarTideNotifier,
|
||||
StarTideIndicator,
|
||||
@@ -42,6 +43,7 @@ import {
|
||||
Star,
|
||||
Radio,
|
||||
Navigation,
|
||||
User,
|
||||
} from "lucide-react";
|
||||
import { TECH_TREE, FRAGMENTS, formatNum } from "@/lib/game/config";
|
||||
import { ACHIEVEMENTS } from "@/lib/game/achievements";
|
||||
@@ -74,6 +76,7 @@ export default function Page() {
|
||||
const energy = useGameStore((s) => s.energy);
|
||||
const hasActiveExpedition = useGameStore((s) => !!s.activeExpedition && !s.activeExpedition.finished);
|
||||
const chronicleCount = useGameStore((s) => s.chronicle?.length ?? 0);
|
||||
const pendingAttrPoints = useGameStore((s) => s.pendingAttrPoints ?? 0);
|
||||
|
||||
// 深空信标:检测是否有可领取的奖励(独立 localStorage)
|
||||
const [beaconClaimable, setBeaconClaimable] = useState(false);
|
||||
@@ -169,7 +172,7 @@ export default function Page() {
|
||||
<div className="leading-tight">
|
||||
<h1 className="text-base sm:text-lg font-bold text-gradient">回响星核</h1>
|
||||
<p className="text-[9px] sm:text-[10px] text-muted-foreground/70 -mt-0.5 tracking-wider">
|
||||
ECHO NEXUS · v0.6
|
||||
ECHO NEXUS · v0.7
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -257,10 +260,10 @@ export default function Page() {
|
||||
<div data-tut="decode-panel" className="glass rounded-2xl p-4 flex-1 min-h-[300px] sm:min-h-[360px] max-h-[560px]">
|
||||
<DecodePanel />
|
||||
</div>
|
||||
{/* 标签面板:探险 / 技术 / 星图 / 图谱 / 成就 / 信标 / 统计 */}
|
||||
{/* 标签面板:探险 / 技术 / 星图 / 图谱 / 成就 / 信标 / 统计 / 角色 */}
|
||||
<div className="glass rounded-2xl p-3 min-h-[280px] sm:min-h-[320px] max-h-[440px] flex flex-col">
|
||||
<Tabs defaultValue={hasActiveExpedition ? "expedition" : hasPendingPerk ? "constellation" : "tech"} className="h-full flex flex-col">
|
||||
<TabsList className="grid grid-cols-7 h-9 bg-black/30 gap-0.5 p-1">
|
||||
<TabsList className="grid grid-cols-8 h-9 bg-black/30 gap-0.5 p-1">
|
||||
<TabsTrigger value="expedition" data-tut="tab-expedition" className="text-[11px] gap-1 relative px-0.5 flex-col h-7 data-[state=active]:bg-amber-500/15 data-[state=active]:shadow-[0_0_12px_rgba(251,191,36,0.3)] transition-all">
|
||||
<Rocket className="h-3.5 w-3.5" />
|
||||
<span className="leading-none">探险</span>
|
||||
@@ -304,6 +307,13 @@ export default function Page() {
|
||||
<BarChart3 className="h-3.5 w-3.5" />
|
||||
<span className="leading-none">统计</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="attributes" className="text-[11px] gap-1 relative px-0.5 flex-col h-7 data-[state=active]:bg-gradient-to-br data-[state=active]:from-emerald-500/15 data-[state=active]:via-fuchsia-500/15 data-[state=active]:to-rose-500/15 data-[state=active]:shadow-[0_0_12px_rgba(232,121,249,0.3)] transition-all">
|
||||
<User className="h-3.5 w-3.5" />
|
||||
<span className="leading-none">角色</span>
|
||||
{pendingAttrPoints > 0 && (
|
||||
<span className="absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-rose-400 animate-pulse ring-1 ring-black/50" />
|
||||
)}
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="expedition" className="flex-1 mt-2 min-h-0 data-[state=active]:flex data-[state=active]:flex-col">
|
||||
<ExpeditionPanel />
|
||||
@@ -326,6 +336,9 @@ export default function Page() {
|
||||
<TabsContent value="stats" className="flex-1 mt-2 min-h-0">
|
||||
<StatsPanel />
|
||||
</TabsContent>
|
||||
<TabsContent value="attributes" className="flex-1 mt-2 min-h-0 data-[state=active]:flex data-[state=active]:flex-col">
|
||||
<AttributesPanel />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</section>
|
||||
@@ -424,6 +437,11 @@ function StatsPanel() {
|
||||
{ label: "编年史条目", value: `${(s.chronicle ?? []).length} 纪元` },
|
||||
{ label: "探险能量", value: `${Math.floor(s.energy)} / ${s.energyMax}` },
|
||||
{ label: "信标最高分", value: beaconBest !== null ? formatNum(beaconBest) : "—" },
|
||||
{ label: "探索力", value: `${s.attributes?.exploration ?? 0} / 100` },
|
||||
{ label: "智慧", value: `${s.attributes?.wisdom ?? 0} / 100` },
|
||||
{ label: "勇气", value: `${s.attributes?.courage ?? 0} / 100` },
|
||||
{ label: "灵感", value: `${s.attributes?.inspiration ?? 0} / 100` },
|
||||
{ label: "待分配属性点", value: `${s.pendingAttrPoints ?? 0}` },
|
||||
];
|
||||
return (
|
||||
<div className="grid grid-cols-2 gap-1.5 text-xs">
|
||||
|
||||
Reference in New Issue
Block a user