feat: 新增英雄召唤事件并优化UI布局与组件注释

- 在 MissionHeroComp 中召唤英雄后派发 MasterCalled 事件,以更新英雄信息面板
- 调整 hnode.prefab 中多个节点的位置和尺寸,优化界面布局
- 为多个 TypeScript 组件文件添加详细注释,说明职责、关键设计和依赖关系
- 在 MissionCardComp 中完善英雄信息面板的创建、排序和布局逻辑
This commit is contained in:
walkpan
2026-04-07 19:52:40 +08:00
parent e880613f8f
commit 81a07bc16c
12 changed files with 2952 additions and 2639 deletions

View File

@@ -1,3 +1,24 @@
/**
* @file MapViewComp.ts
* @description 地图视图组件ECS 视图层)
*
* 职责:
* 1. 作为地图的顶层 **视图逻辑控制器**,挂载在地图预制体的 "map" 子节点上。
* 2. 持有 MapViewScene 引用,用于访问场景中的各图层(实体层、技能层、地图层)。
* 3. 提供全局事件监听接口(当前已注释,预留扩展)。
* 4. 管理游戏内计时器game_timer预留 1 秒间隔周期逻辑)。
*
* 关键设计:
* - start() 时获取同节点上的 MapViewScene 组件引用。
* - reset() 在 ECS 实体移除时取消全局事件监听。
* - 当前 update / onLoad 为空实现,预留帧更新和初始化扩展位。
*
* 依赖:
* - MapViewSceneview/MapViewScene.ts—— 场景图层管理
* - Timeroops-framework—— 周期计时器
* - smc —— 全局单例模块
* - BoxSet —— 游戏常量配置
*/
import { v3, Vec3, _decorator ,Prefab,instantiate,JsonAsset} from "cc";
import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
@@ -8,31 +29,46 @@ import { Timer } from "../../../../../extensions/oops-plugin-framework/assets/co
import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops";
const { ccclass, property } = _decorator;
/**
* MapViewComp —— 地图视图逻辑组件
*
* ECS 视图层入口,通过 scene 属性访问场景中各图层。
*/
@ccclass('MapViewComp')
@ecs.register('MapView', false)
export class MapViewComp extends CCComp {
/** 场景图层管理器引用start 时初始化) */
scene: MapViewScene = null!;
/** 游戏内周期计时器(预留,间隔 1 秒) */
private game_timer: Timer = new Timer(1);
/** 地图加载完成回调(预留) */
private mapLoaded() {
}
/** 初始化:预留全局事件监听位 */
async onLoad(){
// 监听全局事件
}
/** ECS 组件移除时取消全局事件监听 */
reset(): void {
//撤销监听
// oops.message.off("do_add_hero", this.on_do_add_hero, this);
}
/** 启动时获取同节点上的 MapViewScene 组件 */
start() {
this.scene = this.getComponent(MapViewScene);
}
/** 预留:加载游戏数据 */
load_data(){
// let heros = oops.res.get("config/game/heros")
}
/** 帧更新(预留扩展) */
protected update(dt: number): void {
}

View File

@@ -1,3 +1,28 @@
/**
* @file MapViewScene.ts
* @description 地图场景管理器(负责图层持有与场景生命周期)
*
* 职责:
* 1. 持有场景中的各个显示图层引用:
* - camera场景摄像机
* - layer通用容器层
* - mapLayer地图背景层MapLayer
* - floorLayer地面装饰层
* - entityLayer实体层EntityLayer承载英雄/怪物节点)
* - SkillLayer技能效果层
* 2. 提供 init() 初始化入口和 reset() 清理入口。
* 3. 控制摄像机是否跟随玩家isFollowPlayer
*
* 关键设计:
* - ratio2D 到 3D 的位置比例值(预留,用于混合渲染模式)。
* - reset() 清除所有图层子节点,恢复初始状态。
* - onLoad() 时 enabled=false等待外部 init() 后启动。
*
* 依赖:
* - EntityLayer —— 实体图层(管理英雄/怪物的排序与清理)
* - SkillLayer —— 技能图层
* - MapLayer —— 地图背景图层
*/
import { Camera, CCBoolean, Component, EventTouch, Node, screen, Size, Texture2D, UITransform, Vec2, Vec3, view, _decorator } from "cc";
import { oops } from "../../../../../extensions/oops-plugin-framework/assets/core/Oops";
import EntityLayer from "./map/layer/EntityLayer";
@@ -7,40 +32,45 @@ import MapLayer from "./map/layer/MapLayer";
const { ccclass, property } = _decorator;
/**
* 地图场景逻辑
* 1、地图摄像机跟随角色位置移动
* MapViewScene —— 地图场景管理器
*
* 持有场景中所有图层的引用,提供初始化和清理接口。
* 由 MapViewComp 在 start() 时获取引用。
*/
@ccclass('MapViewScene')
export class MapViewScene extends Component {
/** 场景摄像机(可选,用于跟随角色) */
@property(Camera)
public camera: Camera | null = null;
/** 通用容器图层节点 */
@property(Node)
public layer: Node | null = null;
/** 地图背景图层(管理背景图片的尺寸和清理) */
@property(MapLayer)
public mapLayer: MapLayer | null = null;
/** 地面装饰图层节点 */
@property(Node)
public floorLayer: Node | null = null;
/** 实体图层HERO / MON 等游戏实体的父容器) */
@property(EntityLayer)
public entityLayer: EntityLayer | null = null;
/** 技能效果图层 */
@property(SkillLayer)
public SkillLayer: SkillLayer | null = null;
/** 是否启用摄像机跟随玩家 */
@property(CCBoolean)
public isFollowPlayer: boolean = true;
/** 2D3D位置比例值 */
/** 2D3D 位置比例值(预留,混合渲染时使用) */
ratio: Vec2 = new Vec2();
/** 加载时禁用自身,等待 init() 手动启用 */
onLoad() {
this.enabled = false;
}
@@ -49,28 +79,25 @@ export class MapViewScene extends Component {
}
/**
* 重置场景:清除各图层的子节点和数据。
* 用于关卡切换或任务结束时恢复初始状态。
*/
private reset() {
this.floorLayer!.removeAllChildren(); // 清除地面显示对象
this.entityLayer!.clear(); // 清除游戏实体对象
this.mapLayer!.clear();
this.floorLayer!.removeAllChildren(); // 清除地面显示对象
this.entityLayer!.clear(); // 清除游戏实体对象
this.mapLayer!.clear(); // 清除地图背景
}
/** 场景初始化(预留扩展) */
public init() {
}
/** 帧更新(预留摄像机跟随等逻辑) */
update(dt: number) {
}
}

View File

@@ -1,3 +1,27 @@
/**
* @file MoveUV.ts
* @description UV 滚动动画组件(视觉效果层)
*
* 职责:
* 1. 通过每帧修改 Sprite 的 spriteFrame.rect 偏移量,
* 实现纹理的 **UV 滚动效果**(如流水、云层、传送带等)。
* 2. 支持 X / Y 轴独立的滚动速度控制。
* 3. 支持动态切换纹理包裹模式WrapMode
*
* 关键设计:
* - 使用 spriteFrame.rect 的 x / y 偏移模拟 UV 滚动,
* 纹理 WrapMode 必须设为 REPEAT 才能看到循环滚动效果。
* - packable=false禁止图集自动打包确保纹理独立加载以支持 REPEAT 模式。
* - 每帧调用 markForUpdateRenderData() 强制刷新渲染数据,
* 确保 rect 变化能即时反映到渲染管线。
*
* 使用方式:
* 挂载在带有 Sprite 的节点上,设置 moveSpeedX / moveSpeedY 和 wrapMode。
*
* 依赖:
* - cc.Sprite —— 读写 spriteFrame.rect
* - cc.Texture2D.WrapMode —— 控制纹理采样的循环方式
*/
import { Texture2D } from 'cc';
import { Enum } from 'cc';
import { rect } from 'cc';
@@ -5,26 +29,45 @@ import { Sprite } from 'cc';
import { _decorator, Component } from 'cc';
const { ccclass, property } = _decorator;
/**
* MoveUV —— UV 滚动动画组件
*
* 通过修改 Sprite 的 rect 偏移实现纹理循环滚动。
* 适用于水面、云层、传送带等需要连续滚动的视觉效果。
*/
@ccclass('MoveUV')
export class MoveUV extends Component {
/** X 轴滚动速度(像素/秒,正值向右,负值向左) */
@property
moveSpeedX = 0;
/** Y 轴滚动速度(像素/秒,正值向上,负值向下) */
@property
moveSpeedY = 0;
/** 纹理包裹模式(默认 REPEAT循环滚动必须使用此模式 */
@property({ type: Enum(Texture2D.WrapMode) })
wrapMode = Texture2D.WrapMode.REPEAT;
/** Sprite 组件引用 */
private _sprite: Sprite;
/** 当前 rect 偏移量(修改 x / y 实现滚动) */
private _rect = rect();
/** 上一次应用的 WrapMode用于检测变化 */
private _currentWrapMode: number;
/** 获取当前 rect供外部读取偏移状态 */
getRect() {
return this._rect;
}
/**
* 初始化:
* 1. 获取 Sprite 组件(不存在则抛出异常)。
* 2. 记录初始 rect 尺寸。
* 3. 禁止自动打包packable=false确保纹理独立以支持 REPEAT。
*/
onLoad() {
this._sprite = this.getComponent(Sprite);
if (!this._sprite) {
@@ -35,14 +78,23 @@ export class MoveUV extends Component {
this._sprite.spriteFrame.packable = false;
}
/**
* 帧更新:
* 1. 检测 WrapMode 是否变化,变化则重新设置纹理参数。
* 2. 按速度累加 rect 的 x / y 偏移。
* 3. 将新 rect 赋回 spriteFrame 并标记渲染数据更新。
*/
update(dt: number) {
// 动态切换 WrapMode
if (this._currentWrapMode !== this.wrapMode) {
this._currentWrapMode = this.wrapMode;
this._sprite.spriteFrame.texture.setWrapMode(this.wrapMode, this.wrapMode);
}
// 累加 UV 偏移
this._rect.x += this.moveSpeedX * dt;
this._rect.y += this.moveSpeedY * dt;
// 应用新 rect 并强制刷新渲染
this._sprite.spriteFrame.rect = this._rect;
this._sprite.markForUpdateRenderData();
}

View File

@@ -1,3 +1,21 @@
/**
* @file EntityLayer.ts
* @description 实体图层组件(场景显示层)
*
* 职责:
* 1. 作为所有游戏实体(英雄、怪物)的 **父容器节点**。
* 2. 预留深度排序逻辑(当前已注释,按 Y 坐标排序子节点渲染顺序)。
* 3. 提供 clear() 方法清除所有子节点(用于场景重置)。
*
* 关键设计:
* - 使用 Timer0.2 秒间隔)降频排序,避免每帧排序导致性能问题。
* - 深度排序按 Y 坐标从大到小Y 越小渲染越靠前),
* 模拟 2D 俯视角的遮挡关系。
* - 如果后续切换为全 3D 渲染,则不需要 2D 深度排序。
*
* 依赖:
* - Timeroops-framework—— 降频计时器
*/
/*
* @Author: dgflash
* @Date: 2022-08-04 15:22:33
@@ -10,17 +28,26 @@ import { Timer } from '../../../../../../../extensions/oops-plugin-framework/ass
const { ccclass, property } = _decorator;
/**
* 物体
* EntityLayer —— 实体图
*
* 所有英雄和怪物节点的父容器,预留深度排序功能。
*
* 注:
* 1、这里的深度排序如果有性能问题,可考虑修改为非每帧排序
* 2、如果全3D世界显示角色相关显示对象则不需要2D深度排序只引用2D地图上的位置信息
* 1. 如果深度排序存在性能问题,可修改为非每帧排序(使用 Timer 降频)。
* 2. 如果全 3D 渲染,则不需要 2D 深度排序,只引用 2D 地图上的位置信息
*/
@ccclass('EntityLayer')
export default class EntityLayer extends Component {
/** 降频计时器0.2 秒间隔,当前 update 中只调用 update 但未使用返回值) */
private timer: Timer = new Timer(0.2);
/**
* 帧更新:
* 预留深度排序调用位(当前已注释排序逻辑)。
*/
update(dt: number) {
this.timer.update(dt)
// 预留:按 Y 坐标排序子节点渲染顺序
// if (this.timer.update(dt))
// this.node.children.sort(this.zIndexSort);
}
@@ -28,6 +55,10 @@ export default class EntityLayer extends Component {
protected start(): void {
}
/**
* 清除该图层下的所有子节点。
* 由 MapViewScene.reset() 在场景重置时调用。
*/
public clear() {
this.node.children.forEach(n => {

View File

@@ -1,3 +1,23 @@
/**
* @file MapLayer.ts
* @description 地图背景图层组件
*
* 职责:
* 1. 管理地图背景图片bgImg的显示和尺寸。
* 2. 提供 width / height 属性供其他组件查询地图实际尺寸。
* 3. 提供 init() 初始化方法同步 UITransform 尺寸。
* 4. 提供 clear() 清理方法释放背景图片引用。
*
* 关键设计:
* - 地图尺寸由 bgImg 的 UITransform 决定,非固定值。
* - clear() 仅释放 spriteFrame 引用(置 null不销毁节点。
*
* 依赖:
* - cc.Sprite —— 背景图片组件
* - cc.UITransform —— 读写节点尺寸
*
* @author 落日故人 QQ 583051842
*/
import { Component, Layers, Node, Sprite, SpriteFrame, Texture2D, UITransform, Vec3, _decorator } from 'cc';
import { oops } from '../../../../../../../extensions/oops-plugin-framework/assets/core/Oops';
import { LayerUtil } from '../../../../../../../extensions/oops-plugin-framework/assets/core/utils/LayerUtil';
@@ -6,31 +26,37 @@ import { smc } from '../../../../common/SingletonModuleComp';
const { ccclass, property } = _decorator;
/**
* 地图层
* @author 落日故人 QQ 583051842
*
* MapLayer —— 地图背景图层
*
* 管理背景图片的尺寸和清理,由 MapViewScene 持有引用。
*/
@ccclass('MapLayer')
export default class MapLayer extends Component {
/** 背景图片 Sprite在编辑器中绑定 */
@property(Sprite)
private bgImg: Sprite | null = null;
/**
* 初始化:将 MapLayer 节点的 UITransform 尺寸
* 同步为背景图片的实际宽高。
*/
public init(): void {
this.getComponent(UITransform)!.width = this.width;
this.getComponent(UITransform)!.height = this.height;
}
/** 清理:释放背景图片的 spriteFrame 引用 */
public clear(): void {
this.bgImg!.spriteFrame = null;
}
/** 获取背景图片 Sprite 引用 */
public get bgImage(): Sprite {
return this.bgImg!;
}
/** 获取地图宽度(读取背景图片 UITransform 的 width */
public get width(): number {
if (this.bgImg) {
return this.bgImg.getComponent(UITransform)!.width;
@@ -38,6 +64,7 @@ export default class MapLayer extends Component {
}
/** 获取地图高度(读取背景图片 UITransform 的 height */
public get height(): number {
if (this.bgImg) {
return this.bgImg.getComponent(UITransform)!.height;

View File

@@ -1,3 +1,22 @@
/**
* @file SkillLayer.ts
* @description 技能效果图层组件(场景显示层)
*
* 职责:
* 1. 作为所有技能效果节点(弹道、范围指示器、特效等)的 **父容器**。
* 2. 预留 doSkill() 方法用于外部触发技能视觉效果。
* 3. 提供 clear() 方法清除所有技能效果子节点。
* 4. 持有 light 预制体引用(预留,用于技能光效实例化)。
*
* 关键设计:
* - 与 EntityLayer 类似,使用 Timer 降频处理。
* - 深度排序逻辑当前已注释(预留)。
* - clear() 遍历子节点但未执行实际清理(需后续补充)。
*
* 依赖:
* - Timeroops-framework—— 降频计时器
* - BoxSet —— 游戏常量配置
*/
/*
* @Author: dgflash
* @Date: 2022-08-04 15:22:33
@@ -11,23 +30,30 @@ import { BoxSet } from '../../../../common/config/GameSet';
const { ccclass, property } = _decorator;
/**
* 物体
* 注:
* 1、这里的深度排序如果有性能问题可考虑修改为非每帧排序
* 2、如果全3D世界显示角色相关显示对象则不需要2D深度排序只引用2D地图上的位置信息
* SkillLayer —— 技能效果图
*
* 所有技能视觉效果节点的父容器,预留排序和技能触发功能。
*/
@ccclass('SkillLayer')
export default class SkillLayer extends Component {
/** 降频计时器0.2 秒间隔) */
private timer: Timer = new Timer(0.2);
/** 技能光效预制体(在编辑器中绑定,预留) */
@property(Prefab)
light: Prefab = null;
/** 初始化:预留全局事件监听位 */
onLoad(){
// oops.message.on("do_use_skill", this.doSkill, this);
}
/** 外部触发技能效果(预留) */
doSkill(){
}
/** 帧更新(预留深度排序逻辑) */
update(dt: number) {
// this.timer.update(dt)
// if (this.timer.update(dt))
@@ -37,6 +63,7 @@ export default class SkillLayer extends Component {
start(){
}
/** 清除图层下的所有技能效果节点(预留实现) */
public clear() {
this.node.children.forEach(n => {

View File

@@ -1,16 +1,27 @@
/**
* @file light.ts
* @description 光效组件(占位 / 预留)
*
* 职责:
* 当前为空实现的占位组件,预留用于技能光效或环境光效的扩展。
* 后续可在 onLoad / start / update 中加入光照逻辑。
*/
import { _decorator, Component, Node } from 'cc';
const { ccclass, property ,} = _decorator;
/** light —— 光效占位组件(预留扩展) */
@ccclass('light')
export class light extends Component {
start() {
}
protected onLoad(): void {
}
update(deltaTime: number) {
}