feat: 新增英雄召唤事件并优化UI布局与组件注释
- 在 MissionHeroComp 中召唤英雄后派发 MasterCalled 事件,以更新英雄信息面板 - 调整 hnode.prefab 中多个节点的位置和尺寸,优化界面布局 - 为多个 TypeScript 组件文件添加详细注释,说明职责、关键设计和依赖关系 - 在 MissionCardComp 中完善英雄信息面板的创建、排序和布局逻辑
This commit is contained in:
@@ -578,7 +578,7 @@
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 55,
|
||||
"x": 65,
|
||||
"y": 12.894000000000005,
|
||||
"z": 0
|
||||
},
|
||||
@@ -672,7 +672,7 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 110,
|
||||
"width": 130,
|
||||
"height": 165
|
||||
},
|
||||
"_anchorPoint": {
|
||||
@@ -1509,7 +1509,7 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 110,
|
||||
"width": 130,
|
||||
"height": 165
|
||||
},
|
||||
"_anchorPoint": {
|
||||
@@ -1611,7 +1611,7 @@
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 55,
|
||||
"x": 65,
|
||||
"y": 12.894000000000005,
|
||||
"z": 0
|
||||
},
|
||||
@@ -1705,7 +1705,7 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 110,
|
||||
"width": 130,
|
||||
"height": 165
|
||||
},
|
||||
"_anchorPoint": {
|
||||
@@ -2542,7 +2542,7 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 110,
|
||||
"width": 130,
|
||||
"height": 165
|
||||
},
|
||||
"_anchorPoint": {
|
||||
@@ -4549,7 +4549,7 @@
|
||||
},
|
||||
"_lpos": {
|
||||
"__type__": "cc.Vec3",
|
||||
"x": 55,
|
||||
"x": 65,
|
||||
"y": -90,
|
||||
"z": 0
|
||||
},
|
||||
@@ -4749,7 +4749,7 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 104,
|
||||
"width": 124,
|
||||
"height": 40
|
||||
},
|
||||
"_anchorPoint": {
|
||||
@@ -4946,7 +4946,7 @@
|
||||
},
|
||||
"_contentSize": {
|
||||
"__type__": "cc.Size",
|
||||
"width": 110,
|
||||
"width": 130,
|
||||
"height": 150
|
||||
},
|
||||
"_anchorPoint": {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -61,60 +61,102 @@ const { ccclass, property } = _decorator;
|
||||
@ccclass('MissionCardComp')
|
||||
@ecs.register('MissionCard', false)
|
||||
export class MissionCardComp extends CCComp {
|
||||
/** 是否启用调试日志 */
|
||||
private debugMode: boolean = true;
|
||||
/** 卡牌槽位宽度(像素),用于水平等距布局 */
|
||||
private readonly cardWidth: number = 175;
|
||||
/** 按钮正常缩放 */
|
||||
private readonly buttonNormalScale: number = 1;
|
||||
/** 按钮按下缩放 */
|
||||
private readonly buttonPressScale: number = 0.94;
|
||||
/** 按钮弹起缩放(峰值) */
|
||||
private readonly buttonClickScale: number = 1.06;
|
||||
/** 抽卡(刷新)费用 */
|
||||
refreshCost: number = 1;
|
||||
/** 卡牌面板展开/收起动画时长(秒) */
|
||||
cardsPanelMoveDuration: number = 0.2;
|
||||
|
||||
/** 四个插卡槽位(固定顺序分发:1~4) */
|
||||
// ======================== 编辑器绑定节点 ========================
|
||||
|
||||
/** 卡牌面板根节点(战斗阶段收起,准备阶段展开) */
|
||||
@property(Node)
|
||||
cards_node:Node = null!
|
||||
/** 卡牌槽位 1 节点 */
|
||||
@property(Node)
|
||||
card1:Node = null!
|
||||
/** 卡牌槽位 2 节点 */
|
||||
@property(Node)
|
||||
card2:Node = null!
|
||||
/** 卡牌槽位 3 节点 */
|
||||
@property(Node)
|
||||
card3:Node = null!
|
||||
/** 卡牌槽位 4 节点 */
|
||||
@property(Node)
|
||||
card4:Node = null!
|
||||
/** 抽卡(刷新)按钮节点 */
|
||||
@property(Node)
|
||||
cards_chou:Node = null!
|
||||
/** 卡池升级按钮节点 */
|
||||
@property(Node)
|
||||
cards_up:Node = null!
|
||||
/** 金币显示节点(含 icon + num 子节点) */
|
||||
@property(Node)
|
||||
coins_node:Node = null!
|
||||
/** 卡池等级显示节点 */
|
||||
@property(Node)
|
||||
pool_lv_node:Node = null!
|
||||
/** 场上英雄信息面板容器节点(HInfoComp 实例的父节点) */
|
||||
@property(Node)
|
||||
hero_info_node:Node = null! //场上英雄信息面板所在节点
|
||||
hero_info_node:Node = null!
|
||||
/** 英雄信息面板预制体(每个英雄上场时实例化一份) */
|
||||
@property(Prefab)
|
||||
hero_info_prefab:Prefab=null! //场上英雄信息面板Prefab
|
||||
hero_info_prefab:Prefab=null!
|
||||
/** 英雄数量显示节点(含 icon + num 子节点) */
|
||||
@property(Node)
|
||||
hero_num_node:Node=null!
|
||||
|
||||
// ======================== 运行时状态 ========================
|
||||
|
||||
/** 预留图集缓存(后续接入按钮/卡面图标时复用) */
|
||||
private uiconsAtlas: SpriteAtlas | null = null;
|
||||
/** 四个槽位对应的单卡控制器缓存 */
|
||||
/** 四个槽位对应的 CardComp 控制器缓存(有序数组) */
|
||||
private cardComps: CardComp[] = [];
|
||||
/** 当前卡池等级(仅影响抽卡来源,不直接改卡槽现有内容) */
|
||||
private poolLv: number = CARD_POOL_INIT_LEVEL;
|
||||
private readonly heroInfoItemGap: number = 110;
|
||||
/** 英雄信息面板项间距(像素) */
|
||||
private readonly heroInfoItemGap: number = 130;
|
||||
/** 英雄信息面板项间额外间距(像素) */
|
||||
private readonly heroInfoItemSpacing: number = 5;
|
||||
/** 英雄信息面板同步计时器(降频刷新用) */
|
||||
private heroInfoSyncTimer: number = 0;
|
||||
/** 是否已缓存卡牌面板基准缩放 */
|
||||
private hasCachedCardsBaseScale: boolean = false;
|
||||
/** 卡牌面板基准缩放(从场景读取) */
|
||||
private cardsBaseScale: Vec3 = new Vec3(1, 1, 1);
|
||||
/** 卡牌面板展开态缩放 */
|
||||
private cardsShowScale: Vec3 = new Vec3(1, 1, 1);
|
||||
/** 卡牌面板收起态缩放(scale=0 隐藏) */
|
||||
private cardsHideScale: Vec3 = new Vec3(0, 0, 1);
|
||||
/**
|
||||
* 英雄信息面板映射:EID → { node, model, comp }
|
||||
* 用于追踪每个出战英雄的面板实例和数据引用
|
||||
*/
|
||||
private heroInfoItems: Map<number, {
|
||||
node: Node,
|
||||
model: HeroAttrsComp,
|
||||
comp: HInfoComp
|
||||
}> = new Map();
|
||||
// ======================== 生命周期 ========================
|
||||
|
||||
/**
|
||||
* 组件加载:
|
||||
* 1. 绑定生命周期事件和按钮交互事件。
|
||||
* 2. 缓存 4 个 CardComp 子控制器引用。
|
||||
* 3. 计算并设置槽位水平布局。
|
||||
* 4. 初始化卡牌面板缩放参数。
|
||||
* 5. 触发首次任务开始流程。
|
||||
*/
|
||||
onLoad() {
|
||||
/** 绑定事件 -> 缓存子控制器 -> 初始化UI状态 */
|
||||
this.bindEvents();
|
||||
this.cacheCardComps();
|
||||
this.layoutCardSlots();
|
||||
@@ -126,15 +168,26 @@ export class MissionCardComp extends CCComp {
|
||||
});
|
||||
}
|
||||
|
||||
/** 组件销毁时解绑所有事件并清理英雄信息面板 */
|
||||
onDestroy() {
|
||||
this.unbindEvents();
|
||||
this.clearHeroInfoPanels();
|
||||
}
|
||||
|
||||
/** 外部初始化入口(由 CardController 调用) */
|
||||
init(){
|
||||
this.onMissionStart();
|
||||
}
|
||||
|
||||
/** 任务开始时:重置卡池等级、清空4槽、显示面板 刷新一次卡池*/
|
||||
/**
|
||||
* 任务开始:
|
||||
* 1. 进入准备阶段(展开卡牌面板)。
|
||||
* 2. 重置卡池等级为初始值。
|
||||
* 3. 初始化局内数据(金币、英雄数量上限)。
|
||||
* 4. 清空旧英雄信息面板和卡牌槽位。
|
||||
* 5. 重置按钮状态和 UI 显示。
|
||||
* 6. 执行首次抽卡并分发到 4 个槽位。
|
||||
*/
|
||||
onMissionStart() {
|
||||
this.enterPreparePhase();
|
||||
this.poolLv = CARD_POOL_INIT_LEVEL;
|
||||
@@ -163,15 +216,20 @@ export class MissionCardComp extends CCComp {
|
||||
});
|
||||
}
|
||||
|
||||
/** 任务结束时:清空4槽并隐藏面板 */
|
||||
/** 任务结束:清空 4 槽 + 英雄面板并隐藏整个节点 */
|
||||
onMissionEnd() {
|
||||
this.clearAllCards();
|
||||
this.clearHeroInfoPanels();
|
||||
this.node.active = false;
|
||||
}
|
||||
|
||||
start() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 帧更新:每 0.15 秒刷新一次场上英雄信息面板(降频)。
|
||||
* 检测已死亡 / 已失效的面板并移除,刷新存活面板属性。
|
||||
*/
|
||||
update(dt: number) {
|
||||
this.heroInfoSyncTimer += dt;
|
||||
if (this.heroInfoSyncTimer < 0.15) return;
|
||||
@@ -186,20 +244,28 @@ export class MissionCardComp extends CCComp {
|
||||
this.node.active = false;
|
||||
}
|
||||
|
||||
/** 只处理UI层事件,不做卡牌效果分发 */
|
||||
// ======================== 事件绑定 ========================
|
||||
|
||||
/**
|
||||
* 绑定所有事件监听:
|
||||
* - 节点级事件:MissionStart / MissionEnd / NewWave / FightStart
|
||||
* - 全局消息:CoinAdd / MasterCalled / HeroDead / UseHeroCard / UseSpecialCard
|
||||
* - 按钮触控:抽卡(cards_chou)、升级(cards_up)
|
||||
*/
|
||||
private bindEvents() {
|
||||
/** 生命周期事件 */
|
||||
/** 生命周期事件(节点级) */
|
||||
this.on(GameEvent.MissionStart, this.onMissionStart, this);
|
||||
this.on(GameEvent.MissionEnd, this.onMissionEnd, this);
|
||||
this.on(GameEvent.NewWave, this.onNewWave, this);
|
||||
this.on(GameEvent.FightStart, this.onFightStart, this);
|
||||
/** 全局消息事件 */
|
||||
oops.message.on(GameEvent.CoinAdd, this.onCoinAdd, this);
|
||||
oops.message.on(GameEvent.MasterCalled, this.onMasterCalled, this);
|
||||
oops.message.on(GameEvent.HeroDead, this.onHeroDead, this);
|
||||
oops.message.on(GameEvent.UseHeroCard, this.onUseHeroCard, this);
|
||||
oops.message.on(GameEvent.UseSpecialCard, this.onUseSpecialCard, this);
|
||||
|
||||
/** 按钮事件:抽卡与卡池升级 */
|
||||
/** 按钮触控事件:抽卡与卡池升级 */
|
||||
this.cards_chou?.on(NodeEventType.TOUCH_START, this.onDrawTouchStart, this);
|
||||
this.cards_chou?.on(NodeEventType.TOUCH_END, this.onDrawTouchEnd, this);
|
||||
this.cards_chou?.on(NodeEventType.TOUCH_CANCEL, this.onDrawTouchCancel, this);
|
||||
@@ -207,6 +273,13 @@ export class MissionCardComp extends CCComp {
|
||||
this.cards_up?.on(NodeEventType.TOUCH_END, this.onUpgradeTouchEnd, this);
|
||||
this.cards_up?.on(NodeEventType.TOUCH_CANCEL, this.onUpgradeTouchCancel, this);
|
||||
}
|
||||
// ======================== 事件回调 ========================
|
||||
|
||||
/**
|
||||
* 金币变化事件回调:
|
||||
* - syncOnly=true:仅同步 UI 显示(金币已被外部修改过)。
|
||||
* - 否则:累加 delta 到 mission_data.coin 后刷新 UI。
|
||||
*/
|
||||
private onCoinAdd(event: string, args: any){
|
||||
const payload = args ?? event;
|
||||
if (payload?.syncOnly) {
|
||||
@@ -221,10 +294,12 @@ export class MissionCardComp extends CCComp {
|
||||
this.playCoinChangeAnim(v > 0);
|
||||
}
|
||||
|
||||
/** 战斗开始:收起卡牌面板 */
|
||||
private onFightStart() {
|
||||
this.enterBattlePhase();
|
||||
}
|
||||
|
||||
/** 新一波:展开面板 → 刷新费用 UI → 重新抽卡分发 */
|
||||
private onNewWave() {
|
||||
this.enterPreparePhase();
|
||||
this.updateCoinAndCostUI();
|
||||
@@ -248,10 +323,17 @@ export class MissionCardComp extends CCComp {
|
||||
this.cards_up?.off(NodeEventType.TOUCH_CANCEL, this.onUpgradeTouchCancel, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 英雄上场事件回调(MasterCalled):
|
||||
* 为新上场英雄创建或更新信息面板,并刷新英雄数量 UI。
|
||||
*/
|
||||
private onMasterCalled(event: string, args: any) {
|
||||
const payload = args ?? event;
|
||||
const eid = Number(payload?.eid ?? 0);
|
||||
const model = payload?.model as HeroAttrsComp | undefined;
|
||||
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "onMasterCalled received payload:", { eid, hasModel: !!model });
|
||||
|
||||
if (!eid || !model) return;
|
||||
const before = this.getAliveHeroCount();
|
||||
this.ensureHeroInfoPanel(eid, model);
|
||||
@@ -259,11 +341,18 @@ export class MissionCardComp extends CCComp {
|
||||
this.updateHeroNumUI(true, after > before);
|
||||
}
|
||||
|
||||
/** 英雄死亡事件回调:刷新面板列表并更新英雄数量 UI */
|
||||
private onHeroDead() {
|
||||
this.refreshHeroInfoPanels();
|
||||
this.updateHeroNumUI(true, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用英雄卡的 guard 校验(由 CardComp 通过 UseHeroCard 事件调用):
|
||||
* - 当前英雄数 < 上限 → 允许使用。
|
||||
* - 已满但新卡可触发合成(腾位) → 允许使用。
|
||||
* - 已满且不可合成 → 阻止使用(cancel=true),弹 toast。
|
||||
*/
|
||||
private onUseHeroCard(event: string, args: any) {
|
||||
const payload = args ?? event;
|
||||
if (!payload) return;
|
||||
@@ -274,6 +363,7 @@ export class MissionCardComp extends CCComp {
|
||||
const heroUuid = Number(payload?.uuid ?? 0);
|
||||
const heroLv = Math.max(1, Math.floor(Number(payload?.hero_lv ?? 1)));
|
||||
const cardLv = Math.max(1, Math.floor(Number(payload?.pool_lv ?? 1)));
|
||||
// 检查是否可以通过合成腾出位置
|
||||
if (this.canUseHeroCardByMerge(heroUuid, heroLv)) {
|
||||
payload.cancel = false;
|
||||
payload.reason = "";
|
||||
@@ -286,6 +376,10 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断新召唤的英雄是否能通过合成腾位:
|
||||
* 场上同 UUID 同等级数量 + 1(新卡自身)>= 合成所需数量 → 可以合成。
|
||||
*/
|
||||
private canUseHeroCardByMerge(heroUuid: number, heroLv: number): boolean {
|
||||
if (!heroUuid) return false;
|
||||
const mergeRule = this.getMergeRule();
|
||||
@@ -294,6 +388,7 @@ export class MissionCardComp extends CCComp {
|
||||
return sameCount + 1 >= mergeRule.needCount;
|
||||
}
|
||||
|
||||
/** 统计场上同 UUID 同等级的存活英雄数量 */
|
||||
private countAliveHeroesByUuidAndLv(heroUuid: number, heroLv: number): number {
|
||||
let count = 0;
|
||||
const actors = this.queryAliveHeroActors();
|
||||
@@ -307,6 +402,11 @@ export class MissionCardComp extends CCComp {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 MissionHeroCompComp 实时读取合成规则。
|
||||
* 通过 ECS 查询获取,避免硬编码与 MissionHeroComp 不一致。
|
||||
* @returns { needCount: 合成所需数量, maxLv: 最大合成等级 }
|
||||
*/
|
||||
private getMergeRule(): { needCount: number, maxLv: number } {
|
||||
let needCount = 3;
|
||||
let maxLv = 2; // 兜底值改为2,与 MissionHeroComp 保持一致
|
||||
@@ -319,6 +419,11 @@ export class MissionCardComp extends CCComp {
|
||||
return { needCount, maxLv };
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用特殊卡事件回调:
|
||||
* - SpecialUpgrade:随机选一个指定等级的英雄升级到目标等级。
|
||||
* - SpecialRefresh:按英雄类型 / 指定等级重新抽取英雄卡。
|
||||
*/
|
||||
private onUseSpecialCard(event: string, args: any) {
|
||||
const payload = args ?? event;
|
||||
const uuid = Number(payload?.uuid ?? 0);
|
||||
@@ -343,26 +448,29 @@ export class MissionCardComp extends CCComp {
|
||||
});
|
||||
}
|
||||
|
||||
// ======================== 按钮触控回调 ========================
|
||||
|
||||
/** 抽卡按钮按下反馈 */
|
||||
private onDrawTouchStart() {
|
||||
this.playButtonPressAnim(this.cards_chou);
|
||||
}
|
||||
|
||||
/** 抽卡按钮释放 → 执行抽卡逻辑 */
|
||||
private onDrawTouchEnd() {
|
||||
this.playButtonClickAnim(this.cards_chou, () => this.onClickDraw());
|
||||
}
|
||||
|
||||
/** 抽卡按钮取消 → 恢复缩放 */
|
||||
private onDrawTouchCancel() {
|
||||
this.playButtonResetAnim(this.cards_chou);
|
||||
}
|
||||
|
||||
/** 升级按钮按下反馈 */
|
||||
private onUpgradeTouchStart() {
|
||||
this.playButtonPressAnim(this.cards_up);
|
||||
}
|
||||
|
||||
/** 升级按钮释放 → 执行升级逻辑 */
|
||||
private onUpgradeTouchEnd() {
|
||||
this.playButtonClickAnim(this.cards_up, () => this.onClickUpgrade());
|
||||
}
|
||||
|
||||
/** 升级按钮取消 → 恢复缩放 */
|
||||
private onUpgradeTouchCancel() {
|
||||
this.playButtonResetAnim(this.cards_up);
|
||||
}
|
||||
@@ -375,7 +483,14 @@ export class MissionCardComp extends CCComp {
|
||||
.filter((comp): comp is CardComp => !!comp);
|
||||
}
|
||||
|
||||
/** 抽卡按钮:每次固定抽4张,然后顺序分发给4个单卡脚本 */
|
||||
// ======================== 核心业务:抽卡 & 升级 ========================
|
||||
|
||||
/**
|
||||
* 抽卡按钮核心逻辑:
|
||||
* 1. 检查金币是否足够 → 不够则 toast 提示。
|
||||
* 2. 扣除费用、播放金币动画。
|
||||
* 3. 重新布局槽位 → 从卡池构建 4 张卡 → 分发到槽位。
|
||||
*/
|
||||
private onClickDraw() {
|
||||
const cost = this.getRefreshCost();
|
||||
const currentCoin = this.getMissionCoin();
|
||||
@@ -430,6 +545,9 @@ export class MissionCardComp extends CCComp {
|
||||
});
|
||||
}
|
||||
|
||||
// ======================== 阶段切换 ========================
|
||||
|
||||
/** 缓存卡牌面板的基准缩放值(从场景初始状态读取,仅缓存一次) */
|
||||
private initCardsPanelPos() {
|
||||
if (!this.cards_node || !this.cards_node.isValid) return;
|
||||
if (!this.hasCachedCardsBaseScale) {
|
||||
@@ -441,6 +559,7 @@ export class MissionCardComp extends CCComp {
|
||||
this.cardsHideScale = new Vec3(0, 0, this.cardsBaseScale.z);
|
||||
}
|
||||
|
||||
/** 进入准备阶段:展开卡牌面板(立即恢复缩放,无动画) */
|
||||
private enterPreparePhase() {
|
||||
if (!this.cards_node || !this.cards_node.isValid) return;
|
||||
this.initCardsPanelPos();
|
||||
@@ -637,7 +756,10 @@ export class MissionCardComp extends CCComp {
|
||||
}
|
||||
|
||||
private ensureHeroInfoPanel(eid: number, model: HeroAttrsComp) {
|
||||
if (!this.hero_info_node || !this.hero_info_prefab) return;
|
||||
if (!this.hero_info_node || !this.hero_info_prefab) {
|
||||
mLogger.error(this.debugMode, "MissionCardComp", "ensureHeroInfoPanel: missing hero_info_node or hero_info_prefab");
|
||||
return;
|
||||
}
|
||||
this.hero_info_node.active = true;
|
||||
const current = this.heroInfoItems.get(eid);
|
||||
if (current) {
|
||||
@@ -646,14 +768,24 @@ export class MissionCardComp extends CCComp {
|
||||
this.updateHeroInfoPanel(current);
|
||||
return;
|
||||
}
|
||||
|
||||
mLogger.log(this.debugMode, "MissionCardComp", "ensureHeroInfoPanel: creating new panel for eid", eid);
|
||||
const node = instantiate(this.hero_info_prefab);
|
||||
node.parent = this.hero_info_node;
|
||||
node.active = true;
|
||||
const comp = node.getComponent(HInfoComp);
|
||||
|
||||
// 尝试两种方式获取组件,并输出日志
|
||||
let comp = node.getComponent(HInfoComp) as any;
|
||||
if (!comp) {
|
||||
comp = node.getComponent("HInfoComp") as any;
|
||||
}
|
||||
|
||||
if (!comp) {
|
||||
mLogger.error(this.debugMode, "MissionCardComp", "ensureHeroInfoPanel: Failed to get HInfoComp from prefab!");
|
||||
node.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
const item = {
|
||||
node,
|
||||
model,
|
||||
@@ -663,6 +795,8 @@ export class MissionCardComp extends CCComp {
|
||||
this.heroInfoItems.set(eid, item);
|
||||
this.relayoutHeroInfoPanels();
|
||||
this.updateHeroInfoPanel(item);
|
||||
|
||||
mLogger.log(this.debugMode, "MissionCardComp", `ensureHeroInfoPanel: new panel created for eid ${eid}, final position:`, item.node.position);
|
||||
}
|
||||
|
||||
private refreshHeroInfoPanels() {
|
||||
@@ -707,21 +841,31 @@ export class MissionCardComp extends CCComp {
|
||||
const bView = bEnt?.get(HeroViewComp);
|
||||
const aMove = aEnt?.get(MoveComp);
|
||||
const bMove = bEnt?.get(MoveComp);
|
||||
// 排序逻辑:
|
||||
// 1. 如果有 x 坐标,按照 x 坐标从大到小(在前面)排序
|
||||
// 2. 如果没有 x 坐标,默认退化到按照生成顺序或 eid 排序
|
||||
const aFrontScore = aView?.node?.position?.x ?? -999999;
|
||||
const bFrontScore = bView?.node?.position?.x ?? -999999;
|
||||
if (aFrontScore !== bFrontScore) return aFrontScore - bFrontScore;
|
||||
if (aFrontScore !== bFrontScore) return bFrontScore - aFrontScore;
|
||||
|
||||
const aSpawnOrder = aMove?.spawnOrder ?? 0;
|
||||
const bSpawnOrder = bMove?.spawnOrder ?? 0;
|
||||
if (aSpawnOrder !== bSpawnOrder) return aSpawnOrder - bSpawnOrder;
|
||||
|
||||
const aEid = aEnt?.eid ?? 0;
|
||||
const bEid = bEnt?.eid ?? 0;
|
||||
return aEid - bEid;
|
||||
});
|
||||
|
||||
for (let index = 0; index < sortedItems.length; index++) {
|
||||
const item = sortedItems[index];
|
||||
if (!item.node || !item.node.isValid) continue;
|
||||
|
||||
// 使用 Widget 布局的话需要禁用它或者单纯调整位置
|
||||
// 这里我们使用绝对坐标进行排列,假设是从左到右
|
||||
const targetX = index * (this.heroInfoItemGap + this.heroInfoItemSpacing);
|
||||
const pos = item.node.position;
|
||||
item.node.setPosition(index * (this.heroInfoItemGap + this.heroInfoItemSpacing), pos.y, pos.z);
|
||||
item.node.setPosition(targetX, pos.y, pos.z);
|
||||
item.node.setSiblingIndex(index);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,6 +157,16 @@ export class MissionHeroCompComp extends CCComp {
|
||||
const landingPos = this.resolveHeroLandingPos(uuid);
|
||||
let spawnPos:Vec3 = v3(landingPos.x, landingPos.y + MissionHeroCompComp.HERO_DROP_HEIGHT, 0);
|
||||
hero.load(spawnPos,scale,uuid,landingPos.y,hero_lv,pool_lv);
|
||||
|
||||
// 召唤完成后,派发事件以更新英雄面板
|
||||
const model = hero.get(HeroAttrsComp);
|
||||
if (model) {
|
||||
oops.message.dispatchEvent(GameEvent.MasterCalled, {
|
||||
eid: hero.eid,
|
||||
model: model
|
||||
});
|
||||
}
|
||||
|
||||
return hero;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/**
|
||||
* @file MapModelComp.ts
|
||||
* @description 地图数据模型组件(ECS 纯数据层)
|
||||
*
|
||||
* 职责:
|
||||
* 1. 存储地图相关的 **静态配置数据**(编号、资源路径等)。
|
||||
* 2. 作为 GameMap 实体的数据层,由 ECS 自动注册和管理。
|
||||
* 3. 不包含任何视图逻辑,纯粹作为数据容器供视图层读取。
|
||||
*
|
||||
* 关键属性:
|
||||
* - id:地图编号,标识当前加载的关卡。
|
||||
* - resPrefab:地图显示预制体的资源路径,由 GameMap.load() 异步加载。
|
||||
*
|
||||
* 注释掉的代码说明:
|
||||
* - resConfigMap / resDeliveryMap:计划中的地图配置和传送点数据路径(已废弃)。
|
||||
* - getResContentMiniMap / getResContentSlices / getResContentData:
|
||||
* 瓦片地图相关的资源路径生成方法(当前版本不使用瓦片地图)。
|
||||
*
|
||||
* 依赖:
|
||||
* - ecs(ECS 框架)—— 通过 @ecs.register 注册为 ECS 组件
|
||||
*/
|
||||
/*
|
||||
* @Author: dgflash
|
||||
* @Date: 2022-08-04 15:08:34
|
||||
@@ -7,35 +28,42 @@
|
||||
|
||||
import { ecs } from "../../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
|
||||
/**
|
||||
* MapModelComp —— 地图数据模型
|
||||
*
|
||||
* 存储地图编号和预制体路径等静态配置。
|
||||
* 由 GameMap 实体在 init() 阶段自动挂载。
|
||||
*/
|
||||
@ecs.register('MapModel')
|
||||
export class MapModelComp extends ecs.Comp {
|
||||
/** 初始地图编号 */
|
||||
/** 初始地图编号(当前固定为 1) */
|
||||
id: number = 1;
|
||||
|
||||
// /** 地图数据配置 */
|
||||
// /** 地图数据配置路径(已废弃) */
|
||||
// resConfigMap: string = "config/map/map";
|
||||
|
||||
// /** 地图转场点数据配置 */
|
||||
// /** 地图转场点数据配置路径(已废弃) */
|
||||
// resDeliveryMap: string = "config/map/map_delivery";
|
||||
|
||||
/** 地图显示预制 */
|
||||
/** 地图显示预制体资源路径(由 GameMap.load() 加载) */
|
||||
resPrefab: string = "game/map/map_rpg";
|
||||
|
||||
/** 地图内容资源 */
|
||||
// /** 获取小地图纹理资源路径(已废弃) */
|
||||
// getResContentMiniMap(mapName: string): string {
|
||||
// return `content/map/${mapName}/${mapName}/miniMap/texture`;
|
||||
// };
|
||||
|
||||
// /** 地图瓦片资源 */
|
||||
// /** 获取地图瓦片资源路径(已废弃) */
|
||||
// getResContentSlices(bgName: string, key: string): string {
|
||||
// return `content/map/${bgName}/${bgName}/slices/${key}/texture`;
|
||||
// };
|
||||
|
||||
// /** 地图数据资源 */
|
||||
// /** 获取地图数据资源路径(已废弃) */
|
||||
// getResContentData(mapName: string): string {
|
||||
// return `content/map/${mapName}/${mapName}`;
|
||||
// };
|
||||
|
||||
/** ECS 组件移除时的释放钩子(当前无需清理) */
|
||||
reset() {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,24 @@
|
||||
/**
|
||||
* @file MapViewComp.ts
|
||||
* @description 地图视图组件(ECS 视图层)
|
||||
*
|
||||
* 职责:
|
||||
* 1. 作为地图的顶层 **视图逻辑控制器**,挂载在地图预制体的 "map" 子节点上。
|
||||
* 2. 持有 MapViewScene 引用,用于访问场景中的各图层(实体层、技能层、地图层)。
|
||||
* 3. 提供全局事件监听接口(当前已注释,预留扩展)。
|
||||
* 4. 管理游戏内计时器(game_timer,预留 1 秒间隔周期逻辑)。
|
||||
*
|
||||
* 关键设计:
|
||||
* - start() 时获取同节点上的 MapViewScene 组件引用。
|
||||
* - reset() 在 ECS 实体移除时取消全局事件监听。
|
||||
* - 当前 update / onLoad 为空实现,预留帧更新和初始化扩展位。
|
||||
*
|
||||
* 依赖:
|
||||
* - MapViewScene(view/MapViewScene.ts)—— 场景图层管理
|
||||
* - Timer(oops-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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
/**
|
||||
* @file MapViewScene.ts
|
||||
* @description 地图场景管理器(负责图层持有与场景生命周期)
|
||||
*
|
||||
* 职责:
|
||||
* 1. 持有场景中的各个显示图层引用:
|
||||
* - camera:场景摄像机
|
||||
* - layer:通用容器层
|
||||
* - mapLayer:地图背景层(MapLayer)
|
||||
* - floorLayer:地面装饰层
|
||||
* - entityLayer:实体层(EntityLayer,承载英雄/怪物节点)
|
||||
* - SkillLayer:技能效果层
|
||||
* 2. 提供 init() 初始化入口和 reset() 清理入口。
|
||||
* 3. 控制摄像机是否跟随玩家(isFollowPlayer)。
|
||||
*
|
||||
* 关键设计:
|
||||
* - ratio:2D 到 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;
|
||||
|
||||
/** 2D转3D位置比例值 */
|
||||
/** 2D→3D 位置比例值(预留,混合渲染时使用) */
|
||||
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) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,21 @@
|
||||
/**
|
||||
* @file EntityLayer.ts
|
||||
* @description 实体图层组件(场景显示层)
|
||||
*
|
||||
* 职责:
|
||||
* 1. 作为所有游戏实体(英雄、怪物)的 **父容器节点**。
|
||||
* 2. 预留深度排序逻辑(当前已注释,按 Y 坐标排序子节点渲染顺序)。
|
||||
* 3. 提供 clear() 方法清除所有子节点(用于场景重置)。
|
||||
*
|
||||
* 关键设计:
|
||||
* - 使用 Timer(0.2 秒间隔)降频排序,避免每帧排序导致性能问题。
|
||||
* - 深度排序按 Y 坐标从大到小(Y 越小渲染越靠前),
|
||||
* 模拟 2D 俯视角的遮挡关系。
|
||||
* - 如果后续切换为全 3D 渲染,则不需要 2D 深度排序。
|
||||
*
|
||||
* 依赖:
|
||||
* - Timer(oops-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 => {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
/**
|
||||
* @file SkillLayer.ts
|
||||
* @description 技能效果图层组件(场景显示层)
|
||||
*
|
||||
* 职责:
|
||||
* 1. 作为所有技能效果节点(弹道、范围指示器、特效等)的 **父容器**。
|
||||
* 2. 预留 doSkill() 方法用于外部触发技能视觉效果。
|
||||
* 3. 提供 clear() 方法清除所有技能效果子节点。
|
||||
* 4. 持有 light 预制体引用(预留,用于技能光效实例化)。
|
||||
*
|
||||
* 关键设计:
|
||||
* - 与 EntityLayer 类似,使用 Timer 降频处理。
|
||||
* - 深度排序逻辑当前已注释(预留)。
|
||||
* - clear() 遍历子节点但未执行实际清理(需后续补充)。
|
||||
*
|
||||
* 依赖:
|
||||
* - Timer(oops-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 => {
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user