# Task 1A+1B: 游戏基础框架搭建 ## 任务概要 在现有 Next.js 项目中,安装 Phaser.js,改造主页(封面),创建游戏页面,实现 Phaser 游戏框架挂载 + S型地图渲染。 ## 执行步骤 ### Step 1: 安装 Phaser.js ```bash pnpm add phaser ``` ### Step 2: 改造 `app/page.tsx`(主页/游戏封面) 完全重写主页,展示游戏封面。注意:**必须覆盖模板原有 UI,不保留任何模板样式**。 设计要求(参考 `design-system/大厂保卫战/MASTER.md`): - 背景色:`#0F0F23`(深夜宇宙蓝) - 标题字体:Press Start 2P(像素字体),颜色 `#A78BFA`(霓虹紫) - 副标题:VT323 字体 - 主色 CTA 按钮(进入游戏):`#F43F5E` 红色 - 效果:CRT 扫描线叠加层(`::before` 伪元素,repeating-linear-gradient 细黑线) - 霓虹发光效果:标题 `text-shadow` 双层发光 - 装饰性文字:背景中随机排列大厂黑话(低透明度) 主页内容结构: ``` [全屏黑色背景] [CRT扫描线叠加层] [装饰黑话背景文字] [中央卡片] 标题:大厂保卫战 副标题:最后的打工人 英文副标:THE LAST GRINDER 描述:保住KPI,战胜空降VP [开始游戏] 按钮 → 跳转 /game [底部版权:像素风格] ``` ### Step 3: 创建 `app/game/page.tsx`(游戏页面) ```typescript 'use client' import { useEffect, useRef } from 'react' export default function GamePage() { const gameRef = useRef(null) useEffect(() => { let game: any = null const initGame = async () => { const Phaser = (await import('phaser')).default const { createGameConfig } = await import('@/game/config') if (gameRef.current && !game) { game = new Phaser.Game(createGameConfig('game-container')) } } initGame() return () => { game?.destroy(true) } }, []) return (
) } ``` ### Step 4: 创建游戏核心文件 **`game/constants.ts`**(游戏常量): ```typescript export const MAP_COLS = 16 export const MAP_ROWS = 12 export const TILE_SIZE = 80 // 每格80px,总计 1280x960,Phaser会缩放 export const GAME_WIDTH = 1280 export const GAME_HEIGHT = 720 // S型路径格子坐标 export const PATH_WAYPOINTS = [ { x: 0, y: 2 }, { x: 11, y: 2 }, { x: 11, y: 9 }, { x: 15, y: 9 }, ] // 游戏初始数值 export const INITIAL_HC = 200 export const INITIAL_KPI = 100 export const STAMINA_MAX = 100 export const STAMINA_REGEN = 5 // 每秒恢复量 export const COFFEE_COST = 10 // 瑞幸咖啡 HC 成本 // 颜色常量 export const COLOR_PATH = 0x3d2b1f export const COLOR_BUILDABLE = 0x1e3a5f export const COLOR_HOVER = 0x2d5a8e export const COLOR_BORDER = 0x0a1628 ``` **`game/config.ts`**(Phaser 配置): ```typescript import Phaser from 'phaser' import { GAME_WIDTH, GAME_HEIGHT } from './constants' export function createGameConfig(containerId: string): Phaser.Types.Core.GameConfig { return { type: Phaser.AUTO, width: GAME_WIDTH, height: GAME_HEIGHT, parent: containerId, backgroundColor: '#0a1628', scale: { mode: Phaser.Scale.FIT, autoCenter: Phaser.Scale.CENTER_BOTH, }, scene: [], // 在 GameScene 中动态加载 physics: { default: 'arcade', arcade: { debug: false } } } } ``` **`game/GameScene.ts`**(主游戏场景): 核心地图渲染逻辑: - 创建 16x12 格子网格 - 根据 PATH_WAYPOINTS 计算路径格子集合(路径上的每个格子都是路径格) - 路径格子:深褐色(`0x3d2b1f`) - 可建塔格子:深蓝色(`0x1e3a5f`) - 格子间有1px间距 - 鼠标悬停非路径格子时高亮 - 点击非路径格子:触发建塔逻辑(Phase 1先只做UI提示) - 添加地图装饰性文字("面试间"、"财务室") - 场景中显示:顶部 HUD 区域(KPI进度条 + HC数值) 地图路径计算方式(不能只用 4 个坐标点,需要填充中间格子): ```typescript // 将折线坐标展开为完整路径格子集合 function buildPathTiles(waypoints): Set { const tiles = new Set() for (let i = 0; i < waypoints.length - 1; i++) { const from = waypoints[i] const to = waypoints[i + 1] // 水平或垂直连线 if (from.x === to.x) { for (let y = Math.min(from.y, to.y); y <= Math.max(from.y, to.y); y++) { tiles.add(`${from.x},${y}`) } } else { for (let x = Math.min(from.x, to.x); x <= Math.max(from.x, to.x); x++) { tiles.add(`${x},${from.y}`) } } } return tiles } ``` HUD 设计(Phaser Text/Graphics 实现,而非 HTML 层): - 顶部黑色半透明条(全宽,高度60px) - 左:游戏标题 "大厂保卫战" (Press Start 2P,小字号) - 中:KPI 进度条(宽300px,绿→黄→红渐变) - 右:HC 数值 "HC: 200" **`game/GameManager.ts`**(游戏状态管理器): ```typescript export class GameManager { private static instance: GameManager public hc: number = INITIAL_HC public kpi: number = INITIAL_KPI public currentWave: number = 0 public gameState: 'idle' | 'playing' | 'paused' | 'victory' | 'defeat' = 'idle' static getInstance(): GameManager { ... } spendHC(amount: number): boolean { ... } // 扣除HC,不足返回false addHC(amount: number): void { ... } reduceKPI(amount: number): void { ... } // 减少KPI,归零触发失败 // 事件系统(用于 Scene 与 UI 通信) onHCChange: ((hc: number) => void)[] = [] onKPIChange: ((kpi: number) => void)[] = [] onGameOver: (() => void)[] = [] onVictory: (() => void)[] = [] } ``` ### Step 5: 更新 `app/layout.tsx` 在 layout 中引入 Google Fonts(Press Start 2P + VT323): ```tsx // 在 中添加 ``` ### Step 6: 更新 `app/globals.css` 添加游戏全局样式: - CSS 变量(颜色 token) - CRT 扫描线效果(供主页使用) - 霓虹发光 keyframes 动画 - 像素字体 class ## 验收标准 1. `pnpm dev` 启动成功,无编译错误 2. 访问 `/`:显示游戏封面,有进入游戏按钮,霓虹效果正常 3. 点击进入游戏跳转至 `/game` 4. 访问 `/game`:渲染 16x12 格子地图,S型路径可见(深褐色路径,深蓝色可建区域) 5. 鼠标悬停可建塔格子时高亮 6. 顶部 HUD 显示 KPI 进度条和 HC 数值 ## 相关上下文 - 设计系统:`design-system/大厂保卫战/MASTER.md` - PRD:`.docs/prd-tower-defense-game.md` - 计划文档:`.docs/plans/2026-03-21-tower-defense-game.md` - 开发规范:`@rules/dev-best-practices.md`(**必须先阅读**) 完成开发后,按 `@rules/atomic-commit.md` 规范,将变更按逻辑模块分组提交(禁止 `git add .`),确保所有文件均已 commit 后再结束任务。