From 9704881fd808f558bbb617554adc281dc2ae825e Mon Sep 17 00:00:00 2001 From: Cloud Bot Date: Sat, 21 Mar 2026 09:45:37 +0000 Subject: [PATCH] =?UTF-8?q?feat(app):=20=E4=B8=BB=E9=A1=B5=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E9=9A=BE=E5=BA=A6=E9=80=89=E6=8B=A9UI=EF=BC=8C?= =?UTF-8?q?=E6=B8=B8=E6=88=8F=E9=A1=B5=E8=AF=BB=E5=8F=96localStorage?= =?UTF-8?q?=E9=9A=BE=E5=BA=A6=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/game/page.tsx | 22 ++++++---- app/page.tsx | 107 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 113 insertions(+), 16 deletions(-) diff --git a/app/game/page.tsx b/app/game/page.tsx index b066c46..3352715 100644 --- a/app/game/page.tsx +++ b/app/game/page.tsx @@ -16,14 +16,12 @@ export default function GamePage() { const [hc, setHc] = useState(200) const [selectedTower, setSelectedTower] = useState(null) const [gameReady, setGameReady] = useState(false) - // expose setter to game scene via window const selectedTowerRef = useRef(null) const handleSelectTower = useCallback((type: TowerType) => { const next = selectedTowerRef.current === type ? null : type selectedTowerRef.current = next setSelectedTower(next) - // notify scene if (typeof window !== 'undefined') { (window as any).__gameSelectTower?.(next) } @@ -39,6 +37,16 @@ export default function GamePage() { if (!mounted) return + // 从 localStorage 读取难度,通过 window 变量传给场景 + if (typeof window !== 'undefined') { + const storedDifficulty = localStorage.getItem('game-difficulty') + if (storedDifficulty === 'easy' || storedDifficulty === 'normal' || storedDifficulty === 'hard') { + ;(window as any).__gameDifficulty = storedDifficulty + } else { + ;(window as any).__gameDifficulty = 'normal' + } + } + const GameScene = createGameScene(Phaser) const config = createGameConfig('game-canvas-container') config.scene = [GameScene] @@ -49,7 +57,6 @@ export default function GamePage() { } config.type = Phaser.AUTO - // expose HC update to React if (typeof window !== 'undefined') { (window as any).__gameOnHCChange = (val: number) => { if (mounted) setHc(val) @@ -79,6 +86,7 @@ export default function GamePage() { delete (window as any).__gameOnTowerDeselect delete (window as any).__gameSelectTower delete (window as any).__gameReady + delete (window as any).__gameDifficulty } } }, []) @@ -88,14 +96,14 @@ export default function GamePage() { className="w-full h-screen flex flex-col overflow-hidden" style={{ backgroundColor: '#0A1628' }} > - {/* Phaser canvas 区域,flex-1 填满剩余高度 */} + {/* Phaser canvas 区域 */}
- {/* 底部塔选择面板 — 纯 React DOM,不被 Canvas 遮挡 */} + {/* 底部塔选择面板 */}
- {/* 角色图片 */}
{/* eslint-disable-next-line @next/next/no-img-element */}
- {/* 名称 */} {meta.name} - {/* 费用 */} {meta.cost} HC - {/* 描述 */} {meta.desc} diff --git a/app/page.tsx b/app/page.tsx index bd63cf8..ffa0585 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,6 +1,7 @@ 'use client' -import Link from 'next/link' +import { useState } from 'react' +import { useRouter } from 'next/navigation' // 背景装饰黑话词条 const BUZZ_WORDS = [ @@ -11,7 +12,53 @@ const BUZZ_WORDS = [ '向上管理', '自驱力', '全链路', '数据驱动', '业务增长', ] +type DifficultyLevel = 'easy' | 'normal' | 'hard' + +const DIFFICULTY_OPTIONS: { + key: DifficultyLevel + label: string + desc: string + color: string + borderColor: string + glowColor: string +}[] = [ + { + key: 'easy', + label: '简单', + desc: '带薪摸鱼,准点下班', + color: '#22C55E', + borderColor: '#16a34a', + glowColor: 'rgba(34,197,94,0.35)', + }, + { + key: 'normal', + label: '普通', + desc: '常规打工,偶有加班', + color: '#3B82F6', + borderColor: '#2563eb', + glowColor: 'rgba(59,130,246,0.35)', + }, + { + key: 'hard', + label: '困难', + desc: '地狱模式,007全开', + color: '#EF4444', + borderColor: '#dc2626', + glowColor: 'rgba(239,68,68,0.35)', + }, +] + export default function GameCover() { + const [selectedDifficulty, setSelectedDifficulty] = useState('normal') + const router = useRouter() + + const handleStart = () => { + if (typeof window !== 'undefined') { + localStorage.setItem('game-difficulty', selectedDifficulty) + } + router.push('/game') + } + return (
- {/* 深色叠加层,确保文字可读 */} + {/* 深色叠加层 */}
{/* CRT 流动扫描线 */} @@ -108,9 +155,54 @@ export default function GameCover() { 部署打工人防线,捍卫最后的 HC

+ {/* 难度选择 */} +
+

+ 选择难度 +

+
+ {DIFFICULTY_OPTIONS.map(opt => { + const isSelected = selectedDifficulty === opt.key + return ( + + ) + })} +
+
+ {/* 开始游戏按钮 */} - { - const el = e.currentTarget as HTMLAnchorElement + const el = e.currentTarget as HTMLButtonElement el.style.opacity = '0.9' el.style.transform = 'translateY(-2px)' el.style.boxShadow = '0 0 30px rgba(244, 63, 94, 0.6)' }} onMouseLeave={e => { - const el = e.currentTarget as HTMLAnchorElement + const el = e.currentTarget as HTMLButtonElement el.style.opacity = '1' el.style.transform = 'translateY(0)' el.style.boxShadow = '0 0 20px rgba(244, 63, 94, 0.4)' }} > 开始游戏 - + {/* 提示文字 */}