Files
pixelheros/.qoder/repowiki/zh/content/奖励系统/奖励机制/奖励机制.md
2025-10-30 16:49:19 +08:00

12 KiB
Raw Blame History

奖励机制

**本文档引用文件** - [Mission.ts](file://assets/script/game/common/config/Mission.ts) - *奖励常量配置* - [MissionComp.ts](file://assets/script/game/map/MissionComp.ts) - *奖励数据管理与实体销毁逻辑* - [VictoryComp.ts](file://assets/script/game/map/VictoryComp.ts) - *奖励界面展示* - [GameEvent.ts](file://assets/script/game/common/config/GameEvent.ts) - *事件定义* - [MissionMonComp.ts](file://assets/script/game/map/MissionMonComp.ts) - *怪物生成与事件处理* - [RogueConfig.ts](file://assets/script/game/map/RogueConfig.ts) - *肉鸽关卡配置* - [Design.md](file://assets/script/Design.md) - *系统设计概述*

更新摘要

变更内容

  • 更新了MissionComp中实体销毁逻辑,修复空引用问题
  • 修正奖励发放流程中组件清理的实现方式
  • 更新相关章节以反映最新的代码实现
  • 增强源码追踪信息,标注关键修改点

目录

  1. 奖励系统概述
  2. 三选一奖励机制
  3. FightSet常量配置与奖励类型
  4. 奖励数据结构与流程
  5. 掉落处理与数据更新
  6. 奖励界面触发与数据传递
  7. 扩展新奖励类型

奖励系统概述

本游戏采用肉鸽Roguelike塔防玩法奖励系统是核心成长机制之一。玩家通过击败怪物获得金币并在每波战斗结束后从三个奖励选项中选择一个用于强化英雄能力。奖励类型包括属性提升、技能升级、装备获取、新技能解锁等不同奖励具有不同的战力评分和金币消耗玩家需要根据当前局势进行策略性选择。

奖励系统通过事件驱动机制实现,主要由MissionComp组件负责奖励数据的收集与分发,VictoryComp组件负责奖励界面的展示与交互。系统采用ECS架构通过事件总线oops.message)进行组件间通信,确保了高内聚低耦合的设计原则。

Section sources

三选一奖励机制

三选一奖励机制是游戏的核心决策系统,其触发条件为每波怪物被全部击败后。当MissionMonComp组件检测到当前波次怪物全部死亡时,会触发FightEnd事件,进而启动奖励选择流程。

该机制的实现逻辑如下:

  1. 战斗结束时,MissionComp组件监听到FightEnd事件
  2. 收集本局战斗的奖励数据(金币、经验、钻石等)
  3. 构建奖励选项数组,通常包含三个不同强度的奖励
  4. 通过GUI系统打开胜利界面Victory界面并传递奖励数据
  5. 玩家在界面中选择一个奖励,系统应用对应效果

奖励选项的设计遵循"弱、一般、强"的梯度原则,不同选项消耗的金币数量不同,战力评分也不同,鼓励玩家进行策略性决策。

sequenceDiagram
participant MissionMonComp as MissionMonComp
participant MissionComp as MissionComp
participant VictoryComp as VictoryComp
participant GUI as GUI系统
MissionMonComp->>MissionComp : MonDead事件(最后一只怪物死亡)
MissionComp->>MissionComp : 检查怪物数量是否为0
MissionComp->>MissionComp : 触发FightEnd事件
MissionComp->>MissionComp : 收集game_data(金币、经验等)
MissionComp->>GUI : 打开Victory界面并传递数据
GUI->>VictoryComp : 初始化奖励界面
VictoryComp->>Player : 显示三个奖励选项
Player->>VictoryComp : 选择奖励
VictoryComp->>MissionComp : 应用所选奖励效果

Diagram sources

FightSet常量配置与奖励类型

FightSet枚举定义在Mission.ts文件中,包含了游戏的核心配置常量,其中与奖励系统直接相关的配置项包括:

  • GREEN_GOLD=1:绿色金币,基础奖励单位
  • BLUE_GOLD=2:蓝色金币,中级奖励单位
  • PURPLE_GOLD=3:紫色金币,高级奖励单位
  • ORANGE_GOLD=4:橙色金币,稀有奖励单位
  • ATK_ADD_GLOD=1:伙伴攻击力增加对应的金币奖励值

这些常量定义了不同品质奖励的数值基准,系统根据这些基准值计算实际奖励数量。例如,普通怪物可能掉落GREEN_GOLD数量的金币而精英怪物或Boss可能掉落PURPLE_GOLDORANGE_GOLD数量的金币。

此外,FightSet还定义了其他影响奖励获取的参数,如MORE_RC=10表示通过观看广告可获得的额外次数,这与奖励系统的双倍奖励功能相关联。

Section sources

奖励数据结构与流程

数据结构分析

MissionComp组件中定义了两个关键数据结构:

  1. rewards数组:用于存储掉落物品列表
rewards:any[]=[]
  1. game_data对象:用于存储游戏数据
game_data:any={
    exp:0,
    gold:0,
    diamond:0
}

rewards数组存储具体的物品奖励,如装备、技能书等;game_data对象则存储基础资源类奖励,包括经验值、金币和钻石。

奖励收集流程

奖励数据的收集与分发流程如下:

  1. 初始化阶段:在data_init()方法中,重置rewards数组和game_data对象
  2. 战斗阶段:通过监听MonDead事件,逐步累积奖励数据
  3. 结束阶段:当战斗结束时,将收集到的奖励数据传递给胜利界面

数据流从怪物死亡事件开始,经过MissionComp组件的收集处理,最终传递给VictoryComp组件进行展示,形成了完整的奖励数据流转闭环。

flowchart TD
A[怪物死亡] --> B{是否为最后一只}
B --> |是| C[触发FightEnd事件]
B --> |否| D[继续战斗]
C --> E[收集奖励数据]
E --> F[填充rewards数组和game_data]
F --> G[打开Victory界面]
G --> H[展示奖励选项]
H --> I[玩家选择奖励]
I --> J[应用奖励效果]

Diagram sources

掉落处理与数据更新

do_drop方法是处理掉落物品和更新游戏数据的核心方法。该方法接收两个参数:drop_item数组和game_data对象,分别表示掉落的物品列表和基础资源奖励。

do_drop(drop_item:any[],game_data:any={exp:0,gold:0,diamond:0}){
    // console.log("[MissionComp] do_drop",drop_item,game_data)
     
}

虽然当前实现为空,但从方法签名可以看出其设计意图:

  • drop_item参数接收掉落的物品数组,可能包含装备、道具等
  • game_data参数接收基础资源奖励,默认值为零
  • 方法内部应实现将掉落物品添加到rewards数组,并将资源奖励累加到game_data对象中

MissionMonComp组件中,可以找到实际的奖励发放逻辑。当关卡类型为"event"(事件关卡)时,会触发随机事件,其中EventType.TREASURE宝藏事件会直接增加50金币

switch (this.currentEvent) {
    case EventType.TREASURE:
        smc.vmdata.mission_data.gold += 50; // 增加50金币
        break;
}

这种设计模式表明,实际的奖励发放可能分散在多个组件中,最终由MissionComp统一收集和管理。

Section sources

奖励界面触发与数据传递

事件监听机制

MissionComp组件通过事件监听机制触发奖励界面的展示。在onLoad方法中,注册了对FightEnd事件的监听:

this.on(GameEvent.FightEnd,this.fight_end,this)

当战斗结束时,fight_end方法会被调用,该方法通过oops.gui.open方法打开胜利界面,并传递奖励数据:

oops.gui.open(UIID.Victory,{victory:false,rewards:this.rewards,game_data:this.game_data})

数据传递机制

数据传递通过open方法的参数实现,传递了三个关键数据:

  • victory:布尔值,表示战斗结果
  • rewards:奖励物品数组
  • game_data:基础资源数据对象

VictoryComp组件的onAdded方法中接收这些数据:

onAdded(args: any) {
    if(args.game_data){
        this.game_data=args.game_data
    }
}

这种事件驱动的数据传递机制确保了组件间的松耦合,MissionComp只需关注奖励数据的收集,而VictoryComp只需关注奖励数据的展示,职责分离清晰。

classDiagram
class MissionComp {
+rewards : any[]
+game_data : any
+onLoad()
+fight_end()
+do_drop()
}
class VictoryComp {
+rewards : any[]
+game_data : any
+onAdded(args)
+victory_end()
}
class GameEvent {
+FightEnd : "FightEnd"
+MissionEnd : "MissionEnd"
}
class UIID {
+Victory : 2
}
MissionComp --> GameEvent : "监听"
MissionComp --> UIID : "使用"
MissionComp --> VictoryComp : "传递数据"
VictoryComp --> GameEvent : "触发"

Diagram sources

实体销毁逻辑优化

根据最新代码变更,MissionComp中的cleanComponents方法已优化修复了实体销毁时可能出现的空引用问题。新的实现直接销毁实体让ECS系统自动处理组件清理避免在组件reset方法中访问已被销毁的实体引用。

private cleanComponents() {
    // 优化销毁顺序直接销毁实体让ECS系统自动处理组件清理
    // 这样可以避免在组件reset方法中访问已经被销毁的实体引用
    ecs.query(ecs.allOf(HeroViewComp)).forEach(entity => {
        entity.destroy();
    });
    ecs.query(ecs.allOf(AtkConCom)).forEach(entity => {
        entity.destroy();
    });
    ecs.query(ecs.allOf(SkillViewCom)).forEach(entity => {
        entity.destroy();
    });
}

此变更确保了在战斗结束后的清理过程中,不会因组件访问已被销毁的实体而导致运行时错误,提高了系统的稳定性。

Section sources

扩展新奖励类型

配置修改步骤

  1. 在Mission.ts中添加常量:在FightSet枚举中添加新的奖励类型常量
NEW_REWARD_TYPE=5 // 新奖励类型
  1. 在RogueConfig.ts中定义事件:如果涉及新事件类型,需在EventType枚举中添加
NEW_EVENT = "new_event"
  1. 更新事件概率配置:在EventConfig中添加新事件的触发概率

代码集成步骤

  1. 修改MissionComp.ts

    • game_data对象中添加新奖励字段
    • do_drop方法中处理新奖励类型的逻辑
    • 确保rewards数组能正确存储新类型的奖励物品
  2. 更新VictoryComp.ts

    • onAdded方法中处理新奖励数据
    • 更新界面展示逻辑以支持新奖励类型的显示
  3. 添加事件处理:在MissionMonComp或相关组件中添加对新奖励事件的处理逻辑

  4. 更新UI配置确保GUI系统能正确加载和显示新奖励类型的界面元素

通过以上步骤,可以无缝集成新的奖励类型,系统的设计具有良好的扩展性,新增奖励类型不会影响现有功能的稳定性。

Section sources