【Cocos Creator】幽灵射手项目讲义 - 第一章:项目概述

🎯 幽灵射手系列 · 全目录

文章目录

      • [🎯 幽灵射手系列 · 全目录](#🎯 幽灵射手系列 · 全目录)
    • 概述
    • [1.1 项目简介](#1.1 项目简介)
    • [1.2 游戏特色](#1.2 游戏特色)
    • [1.3 项目目录结构](#1.3 项目目录结构)
    • [1.4 核心技术栈](#1.4 核心技术栈)
    • [1.5 关键设计模式](#1.5 关键设计模式)
    • [1.6 项目启动流程](#1.6 项目启动流程)
      • [1.6.1 场景加载流程](#1.6.1 场景加载流程)
      • [1.6.2 入口脚本分析](#1.6.2 入口脚本分析)
        • [1.6.2.1 login.ts(登录场景入口)](#1.6.2.1 login.ts(登录场景入口))
        • [1.6.2.2 main.ts(战斗场景入口)](#1.6.2.2 main.ts(战斗场景入口))
      • [1.6.3 启动流程图](#1.6.3 启动流程图)
    • [1.7 框架层核心模块](#1.7 框架层核心模块)
      • [1.7.1 Constant(常量定义)](#1.7.1 Constant(常量定义))
      • [1.7.2 ClientEvent(事件系统)](#1.7.2 ClientEvent(事件系统))
      • [1.7.3 PlayerData(玩家数据管理)](#1.7.3 PlayerData(玩家数据管理))
      • [1.7.4 UIManager(界面管理)](#1.7.4 UIManager(界面管理))
      • [1.7.5 ResourceUtil(资源管理)](#1.7.5 ResourceUtil(资源管理))
      • [1.7.6 AudioManager(音频管理)](#1.7.6 AudioManager(音频管理))
    • [1.8 战斗系统核心模块](#1.8 战斗系统核心模块)
      • [1.8.1 GameManager(游戏管理)](#1.8.1 GameManager(游戏管理))
      • [1.8.2 Player(玩家控制)](#1.8.2 Player(玩家控制))
      • [1.8.3 Monster(怪物控制)](#1.8.3 Monster(怪物控制))
      • [1.8.4 MapManager(地图管理)](#1.8.4 MapManager(地图管理))
      • [1.8.5 Arrow(箭矢控制)](#1.8.5 Arrow(箭矢控制))
    • [1.9 技能系统](#1.9 技能系统)
      • [1.9.1 技能分类体系](#1.9.1 技能分类体系)
      • [1.9.2 玩家技能详解](#1.9.2 玩家技能详解)
        • [1.9.2.1 形态技能](#1.9.2.1 形态技能)
        • [1.9.2.2 数值技能](#1.9.2.2 数值技能)
        • [1.9.2.3 Buff技能](#1.9.2.3 Buff技能)
        • [1.9.2.4 触发技能](#1.9.2.4 触发技能)
      • [1.9.3 怪物技能详解](#1.9.3 怪物技能详解)
      • [1.9.4 技能配置表结构](#1.9.4 技能配置表结构)
    • [1.10 数据配置系统](#1.10 数据配置系统)
      • [1.10.1 配置表分类](#1.10.1 配置表分类)
      • [1.10.2 base.csv结构详解](#1.10.2 base.csv结构详解)
      • [1.10.3 checkpoint.csv结构详解](#1.10.3 checkpoint.csv结构详解)
      • [1.10.4 mapXX.csv结构详解](#1.10.4 mapXX.csv结构详解)
      • [1.10.5 LocalConfig(配置表加载)](#1.10.5 LocalConfig(配置表加载))
    • [1.11 UI界面系统](#1.11 UI界面系统)
      • [1.11.1 界面结构](#1.11.1 界面结构)
      • [1.11.2 界面生命周期](#1.11.2 界面生命周期)
      • [1.11.3 核心界面详解](#1.11.3 核心界面详解)
        • [1.11.3.1 homePanel(主界面)](#1.11.3.1 homePanel(主界面))
        • [1.11.3.2 fightPanel(战斗界面)](#1.11.3.2 fightPanel(战斗界面))
        • [1.11.3.3 revivePanel(复活界面)](#1.11.3.3 revivePanel(复活界面))
    • [1.12 资源管理与性能优化](#1.12 资源管理与性能优化)
      • [1.12.1 对象池系统(PoolManager)](#1.12.1 对象池系统(PoolManager))
      • [1.12.2 资源预加载](#1.12.2 资源预加载)
      • [1.12.3 性能监控](#1.12.3 性能监控)
    • [1.13 实战演练](#1.13 实战演练)
      • [1.13.1 如何添加新怪物](#1.13.1 如何添加新怪物)
      • [1.13.2 如何添加新技能](#1.13.2 如何添加新技能)
      • [1.13.3 如何创建新关卡](#1.13.3 如何创建新关卡)
    • [1.14 项目部署与发布](#1.14 项目部署与发布)
      • [1.14.1 构建配置](#1.14.1 构建配置)
      • [1.14.2 平台适配](#1.14.2 平台适配)
      • [1.14.3 性能优化建议](#1.14.3 性能优化建议)
    • 附录:常用调试命令
    • 总结

概述

本章讲解如何系统化地理解并扩展一个完整的Cocos Creator俯视角射击游戏项目,包括掌握其框架层(单例、事件、对象池)、战斗系统(玩家、怪物、技能、地图)、数据配置与UI管理等内容。


1.1 项目简介

本项目是一款基于 Cocos Creator 引擎开发的俯视角射击游戏《幽灵射手》。玩家控制角色在关卡中移动、射击敌人、收集奖励,通过不断获取技能提升战斗力,挑战更高关卡。

1.2 游戏特色

  • 俯视角射击玩法:玩家控制角色自动瞄准并射击最近的敌人
  • 技能系统:多种技能类型(形态变化、数值提升、Buff效果、触发技能)
  • 关卡系统:多个地图场景,难度递进的关卡设计
  • 敌人AI:多种怪物类型,不同的移动模式和攻击技能
  • 资源管理:完善的对象池、资源加载、音频管理系统

1.3 项目目录结构

复制代码
NewProject/
├── assets/                    # 游戏资源目录
│   ├── res/                   # 静态资源(纹理、模型、动画等)
│   ├── resources/             # 动态资源(配置表、音频、预制体等)
│   ├── scene/                 # 场景文件
│   └── script/                # TypeScript脚本
│       ├── framework/         # 框架层(核心管理类)
│       ├── fight/             # 战斗系统
│       └── ui/                # UI界面
├── extensions/                # 扩展插件
└── docs/                      # 学习文档

1.4 核心技术栈

技术 版本 说明
Cocos Creator 3.x 游戏引擎
TypeScript 4.x 开发语言
Node.js 14+ 构建工具

1.5 关键设计模式

  1. 单例模式:全局管理器类(GameManager、UIManager等)
  2. 观察者模式:事件系统(ClientEvent)
  3. 对象池模式:资源复用(PoolManager)
  4. 状态模式:角色状态管理

1.6 项目启动流程

1.6.1 场景加载流程

游戏启动时按以下顺序加载:

  1. login场景 - 初始化国际化、加载资源包
  2. fight场景 - 主战斗场景,包含所有游戏逻辑

1.6.2 入口脚本分析

1.6.2.1 login.ts(登录场景入口)

挂载位置:login场景 -> Canvas节点

核心功能

  • 初始化i18n国际化系统
  • 将Canvas设置为持久节点(跨场景保留)
  • 预加载资源包(resources、main)
  • 加载主战斗场景

关键代码逻辑

typescript 复制代码
start() {
    this._initLanguage();                    // 初始化语言
    director.addPersistRootNode(this.ndCanvas); // 持久化Canvas
    Constant.LOGIN_TIME = Date.now();        // 记录登录时间
    
    // 微信平台优化加载性能
    if (window.wx) {
        // 并行加载资源包
        Promise.all(arr).then(() => {
            director.loadScene("fight");
        })
    } else {
        director.loadScene("fight");
    }
}
1.6.2.2 main.ts(战斗场景入口)

挂载位置:fight场景 -> Canvas节点

核心功能

  • 设置游戏帧率(默认60帧,低配设备30帧)
  • 初始化调试模式
  • 加载玩家数据和配置表
  • 初始化音频系统
  • 显示主界面

关键代码逻辑

typescript 复制代码
start() {
    // 设置帧率
    game.frameRate = frameRate;
    PhysicsSystem.instance.fixedTimeStep = 1 / frameRate;
    
    // 初始化玩家数据
    PlayerData.instance.loadGlobalCache();
    PlayerData.instance.loadFromCache();
    
    // 加载CSV配置表
    LocalConfig.instance.loadConfig(() => {
        this._loadFinish();
    });
    
    // 初始化音频
    AudioManager.instance.init();
}

1.6.3 启动流程图

复制代码
用户启动游戏
    │
    ▼
┌─────────────────────────────────┐
│      login场景加载              │
│  ├─ 初始化i18n                 │
│  ├─ Canvas持久化               │
│  └─ 加载fight场景              │
└─────────────────────────────────┘
    │
    ▼
┌─────────────────────────────────┐
│      fight场景加载              │
│  ├─ 设置帧率                   │
│  ├─ 加载玩家数据               │
│  ├─ 加载CSV配置表              │
│  ├─ 初始化音频                 │
│  └─ 显示主界面                 │
└─────────────────────────────────┘
    │
    ▼
   游戏开始

1.7 框架层核心模块

1.7.1 Constant(常量定义)

文件位置:assets/script/framework/constant.ts

功能概述:定义游戏中所有常量配置,包括:

常量类别 说明
游戏基础配置 游戏名称、版本、帧率
本地缓存Key 玩家数据、设置、历史记录等缓存键
动画类型 玩家和怪物的动画状态(待机、奔跑、攻击、死亡)
碰撞分组 物理碰撞层定义(玩家、怪物、障碍物等)
事件类型 游戏事件名称(攻击玩家、游戏结束、刷新金币等)
技能定义 玩家技能ID映射
音效名称 音效资源路径映射

关键代码示例

typescript 复制代码
// 碰撞分组定义
public static PHY_GROUP = {
    DEFAULT: 1 << 0,           // 默认
    PLAYER: 1 << 1,            // 玩家
    COLLIDER_ITEM: 1 << 2,     // 碰撞器
    MONSTER: 1 << 3,           // 小怪
    REWARD: 1 << 4,            // 奖品
    MONSTER_SKILL_COLLIDER: 1 << 5, // 怪物技能
    OBSTACLE: 1 << 6,          // 障碍
}

// 事件类型定义
public static EVENT_TYPE = {
    ATTACK_PLAYER: "attackPlayer",
    ON_GAME_INIT: "onInitGame",
    ON_GAME_OVER: "onGameOver",
    ON_GAME_PAUSE: "onGamePause",
    REFRESH_GOLD: "refreshGold",
    // ...
}

1.7.2 ClientEvent(事件系统)

文件位置:assets/script/framework/clientEvent.ts

功能概述:基于观察者模式的事件分发系统,实现解耦的组件通信。

核心方法

方法 功能 参数
on(eventName, handler, target) 监听事件 事件名、回调函数、目标对象
off(eventName, handler, target) 取消监听 事件名、回调函数、目标对象
dispatchEvent(eventName, ...args) 分发事件 事件名、可变参数

使用示例

typescript 复制代码
// 监听游戏结束事件
ClientEvent.on(Constant.EVENT_TYPE.ON_GAME_OVER, this._onGameOver, this);

// 取消监听
ClientEvent.off(Constant.EVENT_TYPE.ON_GAME_OVER, this._onGameOver, this);

// 分发事件
ClientEvent.dispatchEvent(Constant.EVENT_TYPE.ON_GAME_INIT);

1.7.3 PlayerData(玩家数据管理)

文件位置:assets/script/framework/playerData.ts

功能概述:管理玩家数据的单例类,包括:

  • 玩家基础信息(金币、钻石、等级)
  • 技能解锁状态
  • 设置配置
  • 数据持久化

核心属性

属性 类型 说明
playerInfo object 玩家核心数据
settings object 设置配置
history object 历史记录
userId string 用户ID

核心方法

typescript 复制代码
// 加载本地缓存
loadFromCache()

// 创建玩家数据
createPlayerInfo()

// 更新玩家信息(增量修改)
updatePlayerInfo(key, value)

// 添加技能
addPlayerSkill(info)

// 获取未解锁技能
getLockPlyerSkill()

数据结构示例

typescript 复制代码
playerInfo = {
    diamond: 0,           // 钻石
    gold: 0,              // 金币
    level: 1,             // 当前关卡
    highestLevel: 1,      // 最高通关关卡
    arrSkill: [],         // 已解锁技能ID数组
    createDate: Date,     // 创建时间
}

1.7.4 UIManager(界面管理)

文件位置:assets/script/framework/uiManager.ts

功能概述:UI界面的统一管理,实现:

  • 单例界面的显示/隐藏
  • 弹窗队列管理
  • 血条显示
  • 血量提示

核心方法

方法 功能
showDialog(panelPath, args, cb) 显示UI面板
hideDialog(panelPath, cb) 隐藏UI面板
showPlayerBloodBar() 显示玩家血条
showMonsterBloodBar() 显示怪物血条
showBloodTips() 显示血量变化提示

界面优先级定义

typescript 复制代码
PRIORITY = {
    ZERO: 0,              // 最底层
    BLOOD: 5,             // 血条
    BLOOD_TIP: 6,         // 血量提示
    NORMAL: 10,           // 普通界面
    DIALOG: 100,          // 弹窗
    REWARD: 200,          // 奖励弹窗
    WAITING: 300,         // 等待界面
    TIPS: 400,            // 提示
}

1.7.5 ResourceUtil(资源管理)

文件位置:assets/script/framework/resourceUtil.ts

功能概述:资源加载的工具类,提供统一的资源加载接口。

核心方法

方法 功能
loadRes(url, type) 通用资源加载
loadEffectRes(path) 加载特效预制体
loadModelRes(path) 加载模型预制体
createUI(path, parent) 创建UI节点
getUIPrefabRes(path) 获取UI预制体

资源路径约定

typescript 复制代码
// 特效路径
`prefab/effect/${modulePath}`

// 模型路径
`prefab/model/${modulePath}`

// UI路径
`prefab/ui/${prefabPath}`

1.7.6 AudioManager(音频管理)

文件位置:assets/script/framework/audioManager.ts

功能概述:音频资源管理和播放控制。

核心功能

  • 背景音乐播放/暂停/停止
  • 音效播放(支持同时播放多个相同音效)
  • 音量控制
  • 音效对象池复用

核心方法

方法 功能
playMusic(name, loop, cb) 播放背景音乐
playSound(name, loop, cb) 播放音效
stopMusic() 停止音乐
stopAllSound() 停止所有音效
switchMusic(open) 开关音乐
switchSound(open) 开关音效

音效名称定义

typescript 复制代码
SOUND = {
    CLICK: "click",           // 按钮点击
    LOOSE: "loose",           // 射箭
    HIT_PLAYER: "hitPlayer",  // 玩家受击
    GOLD_DROP: "goldDrop",    // 金币掉落
    REVIVE: "revive",         // 复活
    // ...
}

1.8 战斗系统核心模块

1.8.1 GameManager(游戏管理)

文件位置:assets/script/fight/gameManager.ts

功能概述:游戏全局状态管理,是战斗系统的核心控制器。

挂载位置fight场景 -> GameManager节点

核心职责

  1. 游戏状态管理:开始、暂停、结束状态控制
  2. 关卡管理:加载地图、刷新关卡
  3. 玩家管理:创建玩家、重置状态
  4. 怪物管理:管理怪物数组、查找最近怪物
  5. 资源回收:关卡切换时回收所有资源

关键属性

typescript 复制代码
// 静态属性(全局访问)
isGameStart: boolean      // 游戏是否开始
isGamePause: boolean      // 游戏是否暂停
isGameOver: boolean       // 游戏是否结束
isWin: boolean            // 是否胜利
ndPlayer: Node            // 玩家节点
ndBoss: Node              // Boss节点
arrMonster: Node[]        // 怪物数组
attackAddition: number    // 敌人攻击加成
hpAddition: number        // 敌人生命加成

核心方法

方法 功能
_onGameInit() 初始化游戏
_refreshLevel() 刷新关卡
_createPlayer() 创建玩家
_recycleAll() 回收所有资源
getNearestMonster() 获取最近怪物
getNearbyMonster() 获取附近怪物
addGold() 增加金币

游戏初始化流程

typescript 复制代码
private _onGameInit(finishCb) {
    // 1. 获取关卡配置
    let level = PlayerData.instance.playerInfo.level;
    this.mapInfo = LocalConfig.instance.queryByID("checkpoint", level);
    
    // 2. 设置敌人属性加成
    GameManager.attackAddition = this.mapInfo.attackAddition;
    GameManager.hpAddition = this.mapInfo.hpAddition;
    // ...
    
    // 3. 重置游戏状态
    GameManager.isGameStart = false;
    GameManager.isGamePause = false;
    GameManager.isGameOver = false;
    
    // 4. 显示加载界面并刷新关卡
    UIManager.instance.showDialog("loading/loadingPanel", [], () => {
        this._refreshLevel();
    });
}

1.8.2 Player(玩家控制)

文件位置:assets/script/fight/player.ts

功能概述:玩家角色控制脚本,处理玩家移动、攻击、技能等逻辑。

挂载位置player01预制体

核心属性

typescript 复制代码
// 当前属性值
curAttackPower: number     // 攻击力
curDefensePower: number    // 防御力
curAttackSpeed: number     // 攻击速度
curMoveSpeed: number       // 移动速度
curHpLimit: number         // 生命上限

// 技能状态(布尔标志)
isArrowDouble: boolean     // 双重射击
isArrowPenetrate: boolean  // 穿透
isArrowIce: boolean        // 冰冻
isArrowFire: boolean       // 灼烧
isBloodthirsty: boolean    // 嗜血
isArrowLightning: boolean  // 闪电

核心方法

方法 功能
init() 初始化玩家
playAction(obj) 执行玩家动作(移动/停止)
throwArrowToEnemy() 向敌人射箭
addBlood(num, isLimit) 增加血量
reduceBlood(baseInfo) 减少血量
_parsePlayerSkill() 解析玩家技能

玩家攻击逻辑

typescript 复制代码
private _attackMonster() {
    // 获取最近的怪物作为目标
    this._ndTarget = GameManager.getNearestMonster();
    
    if (!this._ndTarget || this.isDie) return;
    
    // 转向目标
    this._moveToTargetWorPos(this._ndTarget.worldPosition);
    
    // 播放攻击动画
    this.scriptPlayerModel.playAni(Constant.PLAYER_ANI_TYPE.ATTACK, false, () => {
        if (!this.scriptPlayerModel.isRunning) {
            this._attackMonster(); // 循环攻击
        }
    });
}

// 射箭方法
public throwArrowToEnemy() {
    // 设置朝向
    this.node.forward = Vec3.subtract(this._forWard, 
        this.node.worldPosition, this._ndTarget.worldPosition)
        .normalize().negative();
    
    // 根据技能状态初始化箭
    if (this.isArrowDouble) {
        if (this.isArrowContinuous) {
            this._initArrow("arrowDoubleContinuous");
        } else {
            this._initArrow("arrowDouble");
        }
    } else {
        this._initArrow("arrowSingle");
    }
}

技能解析逻辑

typescript 复制代码
private _parsePlayerSkill(isCoverSkill = false) {
    let arrSkill = PlayerData.instance.playerInfo.arrSkill;
    
    // 分类技能
    let arrFormChangeSkill = arrSkill.filter(s => s.startsWith("1")); // 形态技能
    let arrValueChangeSkill = arrSkill.filter(s => s.startsWith("2")); // 数值技能
    let arrBuffSkill = arrSkill.filter(s => s.startsWith("3"));       // Buff技能
    let arrTriggerSkill = arrSkill.filter(s => s.startsWith("4"));     // 触发技能
    
    // 设置技能标志
    this.isArrowDouble = arrFormChangeSkill.includes(Constant.PLAYER_SKILL.ARROW_DOUBLE);
    this.isArrowIce = arrBuffSkill.includes(Constant.PLAYER_SKILL.ARROW_ICE);
    // ...
    
    // 应用数值技能效果
    if (arrValueChangeSkill.length) {
        let oriAttackPower = this.playerBaseInfo.attackPower;
        let raiseRate = this.getValueSkillRate(Constant.PLAYER_SKILL.RAISE_ATTACK_01);
        this.curAttackPower = oriAttackPower * (1 + raiseRate);
        // ...
    }
}

1.8.3 Monster(怪物控制)

文件位置:assets/script/fight/monster.ts

功能概述:普通怪物AI控制脚本。

挂载位置:各怪物预制体(aula、boomDragon、hellFire、magician等)

核心属性

typescript 复制代码
baseInfo: any              // 怪物基础配置(从base.csv读取)
layerInfo: any             // 怪物关卡配置(从mapXX.csv读取)
curMoveSpeed: number       // 当前移动速度
curAttackSpeed: number     // 当前攻击速度
isDie: boolean             // 是否死亡
isMoving: boolean          // 是否移动
_skillInfo: any            // 当前技能信息
_allSkillInfo: string[]    // 所有技能ID数组

怪物移动模式

typescript 复制代码
MONSTER_MOVE_PATTERN = {
    RANDOM: 1,              // 随机移动
    FORWARD_PLAYER: 2,      // 朝向玩家移动
    NO_MOVE: 3,             // 不移动,原地攻击
}

核心方法

方法 功能
init(baseInfo, layerInfo) 初始化怪物
playAction(obj) 执行怪物动作
playHit(isArrowLaunch, isPassiveLightning) 播放受击效果
releaseSkillToPlayer() 向玩家释放技能
showDie() 播放死亡动画

怪物攻击逻辑

typescript 复制代码
protected _attackPlayer() {
    if (GameManager.scriptPlayer.isDie || this._scriptMonsterModel.isAttacking) {
        return;
    }
    
    // 计算朝向和攻击位置
    Vec3.subtract(this._offsetPos_2, GameManager.ndPlayer.worldPosition, this.node.worldPosition);
    this.attackForward = this._offsetPos_2.normalize().negative();
    this.attackPos.set(GameManager.ndPlayer.worldPosition);
    
    // 显示预警(如果技能有预警)
    if (this._allSkillInfo.length && this.skillInfo && this.skillInfo.warning) {
        EffectManager.instance.showWarning(this.skillInfo.warning, scale, this).then(() => {
            this.playAttackAni();
        });
    } else {
        this.playAttackAni();
    }
}

// 释放技能
public releaseSkillToPlayer() {
    // 近战攻击(无技能时)
    if (!this._allSkillInfo.length) {
        let offsetLength = Util.getTwoNodeXZLength(this.node, GameManager.ndPlayer);
        if (offsetLength <= this._minLength * this._minLengthRatio) {
            GameManager.scriptPlayer.reduceBlood(this.baseInfo);
        }
        return;
    }
    
    // 远程技能攻击
    ResourceUtil.loadEffectRes(`${this.skillInfo.resName}/${this.skillInfo.resName}`).then((prefab) => {
        this._ndMonsterSkill = PoolManager.instance.getNode(prefab, GameManager.ndGameManager);
        this._ndMonsterSkill.setWorldPosition(this.node.worldPosition);
        this._ndMonsterSkill.forward = this.attackForward.negative();
        
        // 根据技能类型初始化
        switch (this.skillInfo.ID) {
            case Constant.MONSTER_SKILL.ENERGY_BALL:
                let script = this._ndMonsterSkill.getComponent(EnergyBall);
                script.init(this.skillInfo, this.baseInfo, this);
                break;
            // ...其他技能
        }
    });
}

1.8.4 MapManager(地图管理)

文件位置:assets/script/fight/mapManager.ts

功能概述:关卡模型管理,负责加载地图、创建怪物/NPC/道具等。

挂载位置fight场景 -> mapManager节点

核心方法

方法 功能
buildMap(mapName, progressCb, completeCb) 构建地图
recycle() 回收所有地图资源
_showWarpGate() 显示传送门

地图构建流程

typescript 复制代码
public buildMap(mapName, progressCb, completeCb) {
    // 1. 获取地图配置数据
    this._arrMap = LocalConfig.instance.getTableArr(mapName);
    
    // 2. 根据类型分组(怪物、Boss、NPC、爱心等)
    for (let item of this._arrMap) {
        let baseInfo = LocalConfig.instance.queryByID('base', item.ID);
        if (!this._dictModuleType.hasOwnProperty(baseInfo.type)) {
            this._dictModuleType[baseInfo.type] = [];
        }
        this._dictModuleType[baseInfo.type].push(item);
    }
    
    // 3. 批量加载并创建各类型对象
    let arrPromise = [];
    for (const type in this._dictModuleType) {
        if (this._dictModuleType[type].length) {
            arrPromise.push(this._buildModel(type));
        }
    }
    
    Promise.all(arrPromise).then(() => {
        completeCb && completeCb();
    });
}

模块创建逻辑

typescript 复制代码
private _buildModel(type) {
    return new Promise((resolve) => {
        let objItems = this._dictModuleType[type];
        
        for (let layerInfo of objItems) {
            let baseInfo = LocalConfig.instance.queryByID("base", layerInfo.ID);
            let modelPath = `${type}/${baseInfo.resName}`;
            
            ResourceUtil.loadModelRes(modelPath).then((prefab) => {
                // 创建父节点
                let parentName = type + 'Group';
                let ndParent = this.node.getChildByName(parentName) || new Node(parentName);
                
                // 创建实例
                let ndChild = PoolManager.instance.getNode(prefab, ndParent);
                
                // 设置位置、角度、缩放
                ndChild.setPosition(...);
                ndChild.eulerAngles = ...;
                ndChild.setScale(...);
                
                // 初始化组件
                if (baseInfo.type === Constant.BASE_TYPE.MONSTER) {
                    let script = ndChild.getComponent(Monster);
                    script.init(baseInfo, layerInfo);
                    GameManager.arrMonster.push(ndChild);
                } else if (baseInfo.type === Constant.BASE_TYPE.BOSS) {
                    GameManager.arrMonster.push(ndChild);
                    GameManager.ndBoss = ndChild;
                    GameManager.scriptBoss = ndChild.getComponent(Boss);
                    GameManager.scriptBoss.init(baseInfo, layerInfo);
                }
            });
        }
    });
}

1.8.5 Arrow(箭矢控制)

文件位置:assets/script/fight/arrow.ts

功能概述:箭矢飞行和碰撞检测逻辑。

核心属性

typescript 复制代码
_speed: number              // 飞行速度
_damage: number             // 伤害值
_isPenetrate: boolean       // 是否穿透
_isIce: boolean             // 是否冰冻
_isFire: boolean            // 是否灼烧
_isLightning: boolean       // 是否闪电
_isLaunch: boolean          // 是否弹射

核心方法

方法 功能
init(speed, startPos) 初始化箭矢
_onCollisionEnter(other) 碰撞检测
_playHitEffect() 播放击中特效

碰撞处理逻辑

typescript 复制代码
private _onCollisionEnter(other: ColliderComponent) {
    let group = other.getGroup();
    
    // 击中怪物
    if (group === Constant.PHY_GROUP.MONSTER || group === Constant.PHY_GROUP.BOSS) {
        let scriptMonster = other.node.getComponent(Monster) || other.node.getComponent(Boss);
        scriptMonster.playHit(this._isLaunch);
        
        // 穿透处理
        if (!this._isPenetrate) {
            this._destroyArrow();
            return;
        }
    }
    
    // 击中障碍物
    if (group === Constant.PHY_GROUP.OBSTACLE) {
        if (!this._isPenetrate) {
            this._destroyArrow();
        }
    }
}

1.9 技能系统

1.9.1 技能分类体系

游戏中的技能分为四大类:

分类 ID前缀 示例技能 效果说明
形态技能 10x 双重射击、连续射击、伞型射击 改变箭矢形态和数量
数值技能 20x 攻击力提升、攻速提升、生命上限 永久提升角色属性
Buff技能 30x 冰冻、灼烧 箭矢附加元素效果
触发技能 40x 闪电链、嗜血、弹射 攻击时触发额外效果

1.9.2 玩家技能详解

1.9.2.1 形态技能
技能ID 技能名称 效果
10101 双重射击 同时射出两支箭
10201 连续射击 快速连续射击
10301 伞型射击 扇形射出多支箭
10401 反向射击 向后射出箭
10501 侧面射击 向两侧射出箭
10601 穿透 箭矢可穿透敌人
1.9.2.2 数值技能
技能ID 技能名称 效果
20101 攻击提升1 攻击力+25%
20102 攻击提升2 攻击力+50%
20201 闪避 闪避率+10%
20301 暴击提升1 暴击率+5%,爆伤+10%
20302 暴击提升2 暴击率+10%,爆伤+20%
20401 攻速提升1 攻速+20%
20402 攻速提升2 攻速+40%
20501 生命上限 生命上限+20%
20601 生命回复 立即回复30%生命
20701 移动速度 移速+20%
1.9.2.3 Buff技能
技能ID 技能名称 效果
30101 冰冻 箭矢附带冰冻效果,减缓敌人移速和攻速
30201 灼烧 箭矢附带灼烧效果,持续造成伤害
1.9.2.4 触发技能
技能ID 技能名称 效果
40101 闪电链 击中敌人时向周围敌人释放闪电
40201 嗜血 击杀敌人回复2%生命上限
40301 弹射 箭矢击中后弹射到下一个目标

1.9.3 怪物技能详解

技能ID 技能名称 效果
101 能量球 发射能量球追踪玩家
102 小火球 发射小型火球
103 直线火焰 喷射直线范围火焰
104 散射子弹 180度散射攻击
105 龙卷风 S形移动的龙卷风
106 大火团 发射大型火球
107 六角散射 360度六角散射
108 激光 发射直线激光

1.9.4 技能配置表结构

playerSkill.csv结构

字段 类型 说明
ID string 技能唯一标识
name string 技能名称
describe string 技能描述
value string 技能数值(百分比或具体值)
resName string 资源路径
type string 技能类型(1/2/3/4)

monsterSkill.csv结构

字段 类型 说明
ID string 技能唯一标识
name string 技能名称
resName string 资源路径
warning string 预警类型(circle/line/strip)
damage number 伤害值
speed number 技能飞行速度
range number 攻击范围

1.10 数据配置系统

1.10.1 配置表分类

项目使用CSV文件存储游戏数据,主要包括:

配置表 用途
base.csv 基础实体配置(玩家、怪物、Boss、NPC、道具)
checkpoint.csv 关卡配置(敌人属性加成、地图列表)
map001~map105.csv 各关卡地图布局配置
playerSkill.csv 玩家技能配置
monsterSkill.csv 怪物技能配置

1.10.2 base.csv结构详解

字段 类型 说明
ID string 实体唯一标识
name string 实体名称
type string 类型(player/monster/boss/heart/npc)
resName string 资源路径
position string 默认位置(x,y,z)
angle string 默认角度(x,y,z)
scale string 默认缩放(x,y,z)
attackPower number 攻击力
defensePower number 防御力
hp number 生命值
attackSpeed number 攻击速度
moveSpeed number 移动速度
dodgeRate number 闪避率
criticalHitRate number 暴击率
criticalHitDamage number 暴击伤害
movePattern number 移动模式
goldNum number 掉落金币数量
heartDropRate number 爱心掉落概率

1.10.3 checkpoint.csv结构详解

字段 类型 说明
ID string 关卡ID
mapName string 地图名称(多个用#分隔)
attackAddition number 敌人攻击加成
defenseAddition number 敌人防御加成
hpAddition number 敌人生命加成
moveSpeedAddition number 敌人移速加成
attackSpeedAddition number 敌人攻速加成

1.10.4 mapXX.csv结构详解

字段 类型 说明
ID string 实体ID(对应base.csv)
position string 在地图中的位置(可选,默认使用base配置)
angle string 在地图中的角度(可选)
scale string 在地图中的缩放(可选)
skill string 怪物技能(多个用#分隔)
movePattern number 移动模式(可选)

1.10.5 LocalConfig(配置表加载)

文件位置:assets/script/framework/localConfig.ts

功能概述:CSV配置表的加载和查询管理。

核心方法

方法 功能
loadConfig(callback) 加载所有配置表
getTableArr(tableName) 获取整个表数据
queryByID(tableName, id) 根据ID查询数据

1.11 UI界面系统

1.11.1 界面结构

项目UI分为以下几类:

界面类别 包含面板 用途
主界面 homePanel 游戏主菜单
战斗界面 fightPanel、bloodBar 战斗HUD
弹窗界面 pausePanel、revivePanel、settingPanel、shopPanel 功能弹窗
结算界面 settlementPanel 关卡结算

1.11.2 界面生命周期

所有UI面板遵循统一的生命周期:

typescript 复制代码
// 显示面板
show(args) {
    // 初始化界面元素
    // 绑定事件监听
}

// 隐藏面板
hide() {
    // 清理事件监听
    // 保存状态(如需要)
}

1.11.3 核心界面详解

1.11.3.1 homePanel(主界面)

功能:游戏主菜单,包含:

  • 开始游戏按钮
  • 关卡显示
  • 金币/钻石显示
  • 商店入口
  • 设置入口

关键逻辑

typescript 复制代码
show() {
    // 更新金币和钻石显示
    this.updateGold();
    this.updateDiamond();
    
    // 更新当前关卡
    this.updateLevel();
    
    // 绑定按钮事件
    this.btnStart.on('click', this._onStartGame, this);
    this.btnShop.on('click', this._onOpenShop, this);
}
1.11.3.2 fightPanel(战斗界面)

功能:战斗HUD,包含:

  • 玩家血条
  • 技能图标
  • 暂停按钮
  • 暂停菜单

关键逻辑

typescript 复制代码
show() {
    // 监听血量变化事件
    ClientEvent.on(Constant.EVENT_TYPE.REFRESH_GOLD, this.updateGold, this);
    
    // 初始化技能图标
    this.initSkillIcons();
}
1.11.3.3 revivePanel(复活界面)

功能:玩家死亡后显示的复活弹窗,提供多种复活方式。

关键逻辑

typescript 复制代码
show() {
    // 更新复活选项(广告复活、分享复活等)
    this.updateReviveOptions();
    
    // 绑定事件
    this.btnReviveAd.on('click', this._onReviveWithAd, this);
    this.btnReviveShare.on('click', this._onReviveWithShare, this);
    this.btnGiveUp.on('click', this._onGiveUp, this);
}

1.12 资源管理与性能优化

1.12.1 对象池系统(PoolManager)

功能:复用频繁创建/销毁的对象,减少内存分配和GC压力。

核心方法

方法 功能
getNode(prefab, parent) 从对象池获取或创建节点
putNode(node) 将节点放回对象池
preloadPool(prefab, num) 预加载对象池

使用示例

typescript 复制代码
// 获取箭矢节点
let ndArrow = PoolManager.instance.getNode(arrowPrefab, parentNode);

// 回收箭矢
PoolManager.instance.putNode(ndArrow);

1.12.2 资源预加载

策略

  1. 关卡切换时预加载:预加载下一关所需的怪物技能
  2. 玩家技能预加载:根据玩家已解锁技能预加载对应箭矢
  3. 异步加载:使用Promise并行加载资源

关键代码

typescript 复制代码
// 预加载怪物技能
public preloadMonsterSkill(mapName) {
    return new Promise((resolve) => {
        let arrInfo = LocalConfig.instance.getTableArr(mapName);
        let arrSkill = arrInfo.filter(item => item.ID.startsWith("2")) // 怪物
        
        // 获取所有技能ID
        let skillIds = arrSkill.flatMap(item => item.skill.split("#"));
        
        // 预加载每个技能
        let arrPromise = skillIds.map(id => {
            let skillInfo = LocalConfig.instance.queryByID("monsterSkill", id);
            return ResourceUtil.loadEffectRes(`${skillInfo.resName}/${skillInfo.resName}`);
        });
        
        Promise.all(arrPromise).then(() => resolve(null));
    });
}

1.12.3 性能监控

监控指标

  • FPS帧率监控
  • 内存使用监控
  • 资源加载时间监控

调试模式

typescript 复制代码
// 在GameManager中开启调试模式
if (GameManager.isTesting) {
    // 暴露全局对象供调试
    window.GameManager = GameManager;
    window.playerData = PlayerData.instance;
    window.UIManager = UIManager.instance;
}

1.13 实战演练

1.13.1 如何添加新怪物

步骤1:添加基础配置(base.csv)

csv 复制代码
ID,name,type,resName,position,angle,scale,attackPower,defensePower,hp,attackSpeed,moveSpeed,dodgeRate,criticalHitRate,criticalHitDamage,movePattern,goldNum,heartDropRate
2005,newMonster,monster,monster/newMonster,0,0,0,100,20,500,1,2,0.1,0.1,1.5,1,10,0.3

步骤2:创建怪物预制体

  1. assets/resources/prefab/model/monster/目录下创建newMonster.prefab
  2. 添加必要组件:
    • Monster脚本
    • CharacterRigid组件(物理移动)
    • SkinnedMeshRenderer组件(渲染)
    • 碰撞组件

步骤3:配置怪物技能(可选)

monsterSkill.csv中添加技能配置,或在地图配置中指定已有技能。

步骤4:在地图中使用

在对应关卡的mapXX.csv中添加:

csv 复制代码
ID,position,skill
2005,10,5,0,101#102

1.13.2 如何添加新技能

步骤1:添加技能配置(playerSkill.csv)

csv 复制代码
ID,name,describe,value,resName,type
10701,新技能,描述文字,0.5,arrowNew,1

步骤2:创建技能箭矢预制体

assets/resources/prefab/model/weapon/arrow/目录下创建对应的箭矢预制体。

步骤3:在Player.ts中添加技能逻辑

typescript 复制代码
// 在_parsePlayerSkill方法中添加技能检测
if (this._arrFormChangeSkill.length) {
    this.isArrowDouble = this._arrFormChangeSkill.indexOf(Constant.PLAYER_SKILL.ARROW_DOUBLE) !== -1;
    // 添加新技能检测
    this.isArrowNew = this._arrFormChangeSkill.indexOf(Constant.PLAYER_SKILL.ARROW_NEW) !== -1;
}

// 在throwArrowToEnemy方法中添加技能逻辑
if (this.isArrowNew) {
    this._initArrow("arrowNew");
}

步骤4:在Constant.ts中添加技能常量

typescript 复制代码
public static PLAYER_SKILL = {
    // ...已有技能
    ARROW_NEW: "10701",
}

1.13.3 如何创建新关卡

步骤1:添加关卡配置(checkpoint.csv)

csv 复制代码
ID,mapName,attackAddition,defenseAddition,hpAddition,moveSpeedAddition,attackSpeedAddition
12,map012#map013,1.5,1.2,1.8,1.1,1.2

步骤2:创建地图配置(map012.csv)

csv 复制代码
ID,position,skill
2001,5,2,0,101
2002,15,2,0,102#103
3001,25,2,0,105#106

步骤3:测试关卡

通过调试工具设置玩家关卡并测试:

typescript 复制代码
PlayerData.instance.playerInfo.level = 12;
ClientEvent.dispatchEvent(Constant.EVENT_TYPE.ON_GAME_INIT);

1.14 项目部署与发布

1.14.1 构建配置

构建前检查

  1. 确保所有资源已正确导入
  2. 检查路径配置(resources目录必须包含所有动态加载资源)
  3. 确认脚本编译无错误

构建步骤

  1. 打开 Cocos Creator
  2. 点击菜单栏 项目 -> 构建发布
  3. 选择目标平台(Web、微信小游戏、iOS、Android等)
  4. 配置构建选项
  5. 点击"构建"按钮

1.14.2 平台适配

微信小游戏

  • 需要配置 game.json
  • 需要在后台配置域名白名单
  • 需要处理微信授权登录

Web平台

  • 注意跨域问题
  • 优化资源加载顺序

移动端

  • 注意性能优化(帧率、内存)
  • 适配不同屏幕分辨率

1.14.3 性能优化建议

  1. 对象池优化:复用频繁创建的对象(箭矢、特效、血条等)
  2. 资源预加载:关卡切换前预加载所需资源
  3. 纹理压缩:使用合适的纹理格式和压缩方式
  4. Draw Call合并:使用图集合并渲染批次
  5. 距离剔除:对远距离对象进行遮挡剔除
  6. 帧率控制:根据设备性能动态调整帧率

附录:常用调试命令

在调试模式下(GameManager.isTesting = true),可通过控制台执行以下命令:

javascript 复制代码
// 查看玩家数据
playerData.playerInfo

// 查看当前游戏状态
GameManager.isGameStart
GameManager.isGamePause
GameManager.isGameOver

// 设置金币
PlayerData.instance.updatePlayerInfo('gold', 1000)

// 解锁技能
PlayerData.instance.addPlayerSkill({ID: "10101"})

// 重新初始化游戏
ClientEvent.dispatchEvent(Constant.EVENT_TYPE.ON_GAME_INIT)

// 显示调试面板
UIManager.instance.showDialog("debug/debugPanel")

总结

本项目是一个结构清晰、功能完整的射击游戏项目。通过学习本讲义,你可以:

  1. 理解项目架构:掌握框架层、战斗系统、UI系统的设计
  2. 掌握核心机制:玩家控制、怪物AI、技能系统、资源管理
  3. 学会扩展开发:添加新怪物、新技能、新关卡
  4. 理解优化策略:对象池、预加载、性能监控

建议按照章节顺序学习,先理解整体架构,再深入各模块细节,最后通过实战演练巩固知识。

相关推荐
LcGero11 天前
Cocos Creator 热更新地址动态化方案
cocos·动态化·热更
weixin_409383122 个月前
cocosshader像素风沙消散
shader·cocos
weixin_409383123 个月前
cocos shader消失
shader·cocos
weixin_409383123 个月前
cocos魔法阵shader
shader·cocos
weixin_409383123 个月前
cocos抛物线掉落装备 游戏中的抛物线应用x²=-2py 开口向下
游戏·cocos·抛物线
weixin_409383123 个月前
cocos 按钮光环shader
shader·cocos
weixin_409383124 个月前
a星学习记录 通过父节点从目的地格子坐标回溯起点
学习·cocos·a星
weixin_409383124 个月前
简单四方向a*寻路学习记录2 先做个数组地图 在cocos编辑器模式上运行出格子 计算角色世界坐标跟数组地图的联系
学习·编辑器·cocos
weixin_409383126 个月前
cocos 用widget将ui组件固定在屏 随着分辨率自适应 编辑器界面canvas作为手机屏参考 将ui组件放进去 deepseek解答
ui·cocos