SkillEffectDate——将技能看作多个效果的组合
本文最后更新于17 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

设计思路——组合优于继承

开闭原则——对拓展开放,意味着有新的需求或者变化时,可以对现有代码进行拓展以适应新的情况。

对修改封闭,意味着类一旦设计完成,就可以独立完成其工作,而不要对已有代码进行任何修改

比如技能:吸血🗡——一个伤害效果加一个治疗效果(对象是自身)

效果处理器(effect—processor)

对每一个skilleffec都设置一个专门的处理器去处理这个效果

战斗效果处理系统分析

1. 效果处理器类的核心功能、数据结构及关键方法

1.1 基础架构

效果处理器系统采用了基于 EffectProcessor 基类的继承体系,每个具体处理器负责处理特定类型的效果。

核心数据结构:

  • EffectProcessor:基类,定义了所有效果处理器的通用接口
  • 具体处理器:ApplyStatusProcessorDamageEffectProcessorDispelStatusProcessorHealingEffectProcessor

关键方法:

  • process_effect():处理效果的核心方法,由子类实现
  • get_processor_id():获取处理器唯一标识
  • can_process_effect():检查是否可以处理指定效果类型
  • _request_visual_effect():请求播放视觉效果的辅助方法

1.2 具体处理器分析

1.2.1 伤害效果处理器 (DamageEffectProcessor)

核心功能:处理伤害效果,计算并应用伤害。
关键方法

  • process_effect():处理伤害效果,包括播放动画、计算伤害、应用伤害
  • _calculate_damage():计算伤害值,考虑攻击力、防御力和随机因素

代码示例

func process_effect(effect: SkillEffectData, caster: Character, target: Character) -> Dictionary:
    # 播放施法动画
    _request_visual_effect("cast", caster, {})

    # 计算伤害
    var damage_result = _calculate_damage(caster, target, effect)
    var damage = damage_result["damage"]

    # 播放命中动画
    _request_visual_effect("hit", target, {})
    _request_visual_effect("damage_number", target, {"damage": damage, "color": Color.RED})

    # 应用伤害
    var actual_damage = target.take_damage(damage)

    # 记录结果
    results["damage"] = actual_damage

    return results

1.2.2 治疗效果处理器 (HealingEffectProcessor)

核心功能:处理治疗效果,计算并应用治疗量。
关键方法

  • process_effect():处理治疗效果,包括播放动画、计算治疗量、应用治疗
  • _calculate_healing():计算治疗量,考虑魔法攻击力和随机因素

1.2.3 状态效果处理器 (ApplyStatusProcessor)

核心功能:处理状态效果的应用,包括几率判定和状态管理。
关键方法

  • process_effect():处理状态效果应用,包括几率判定、状态应用、触发初始效果
  • _check_if_can_apply_status_by_chance():检查是否通过几率判定

代码示例

func process_effect(effect_data: SkillEffectData, source: Character, target: Character) -> Dictionary:
    # 检查状态模板有效性
    var status_template_to_apply: SkillStatusData = effect_data.status_to_apply
    if not is_instance_valid(status_template_to_apply):
        results["error"] = "Invalid status_template in effect_data."
        return results

    # 几率判定
    var chance = effect_data.status_application_chance
    var applied_by_chance = _check_if_can_apply_status_by_chance(chance)

    if not applied_by_chance:
        results["reason"] = "chance_roll_failed"
        return results

    # 应用状态
    var application_result: Dictionary = target.apply_skill_status(status_template_to_apply, source, effect_data)
    results["success"] = application_result.get("applied_successfully", false)

    # 触发初始效果
    if results.success and is_instance_valid(applied_status_instance):
        if not applied_status_instance.initial_effects.is_empty():
            await _battle_manager._apply_skill_effects_to_targets(
                applied_status_instance.get_initial_effects(),
                applied_status_instance.source_char, 

[target]

) return results

1.2.4 驱散效果处理器 (DispelStatusProcessor)

核心功能:处理状态效果的驱散,根据类型和数量移除目标身上的状态。
关键方法

  • process_effect():处理驱散效果,包括筛选状态、执行驱散、播放视觉效果

2. 战斗管理器如何初始化、注册和调用效果处理器

2.1 初始化和注册

初始化流程

  1. BattleManager_ready() 方法中调用 _init_effect_processors()
  2. _init_effect_processors() 方法创建并注册各种效果处理器

代码示例

func _init_effect_processors():
    # 注册处理器
    register_effect_processor(DamageEffectProcessor.new(self))
    register_effect_processor(HealingEffectProcessor.new(self))
    register_effect_processor(ApplyStatusProcessor.new(self))

注册机制

  • register_effect_processor() 方法将处理器实例存储在 effect_processors 字典中
  • 字典键为处理器的 ID,值为处理器实例

2.2 调用效果处理器

调用流程

  1. 当技能被执行时,_execute_skill() 方法调用 apply_effects()
  2. apply_effects() 方法对每个目标应用每个效果
  3. 对于每个效果,_apply_effect() 方法根据效果类型获取对应的处理器
  4. 调用处理器的 process_effect() 方法处理效果

代码示例

func _apply_effect(effect: SkillEffectData, source: Character, target: Character) -> Dictionary:
    # 获取对应的处理器
    var processor_id = _get_processor_id_for_effect(effect)
    var processor = effect_processors.get(processor_id)

    if processor and processor.can_process_effect(effect):
        # 使用处理器处理效果
        var result = await processor.process_effect(effect, source, target)

        # 发出信号
        effect_applied.emit(effect.effect_type, source, target, result)
        return result
    else:
        push_error("无效的效果处理器: ", processor_id)
        return {}

处理器选择机制

  • _get_processor_id_for_effect() 方法根据效果类型返回对应的处理器 ID
  • 系统使用这个 ID 从 effect_processors 字典中获取处理器实例

3. 两者在战斗流程中的交互方式

3.1 事件触发机制

事件流程

  1. 战斗管理器处理技能执行请求
  2. 战斗管理器调用效果处理器处理技能效果
  3. 效果处理器执行具体逻辑并返回结果
  4. 战斗管理器发出效果应用信号
  5. 战斗管理器继续处理战斗流程

3.2 数据传递机制

数据流向

  • 战斗管理器 → 效果处理器:传递 SkillEffectData、源角色、目标角色
  • 效果处理器 → 战斗管理器:返回处理结果字典
  • 效果处理器 → 战斗管理器:通过 _request_visual_effect() 请求播放视觉效果

3.3 状态同步机制

状态管理

  • 效果处理器不直接管理战斗状态,而是通过调用角色方法修改角色状态
  • 战斗管理器负责整体战斗状态的管理和同步
  • 状态效果的持续时间、叠加等由角色对象自身管理

4. 关键协作点示例

4.1 技能执行与效果处理

协作流程

  1. 玩家选择技能并指定目标
  2. 战斗管理器调用 _execute_skill()
  3. 战斗管理器检查 MP 并扣除
  4. 战斗管理器获取技能目标
  5. 战斗管理器调用 apply_effects() 处理技能效果
  6. 战斗管理器发出 skill_executed 信号

代码示例

func _execute_skill(caster: Character, custom_targets: Array[Character], skill_data: SkillData) -> Dictionary:
    # 检查MP消耗
    if not skill_data.can_cast(caster.current_mp):
        return {"error": "mp_not_enough"}

    # 扣除MP
    if skill_data.mp_cost > 0:
        caster.use_mp(skill_data.mp_cost)

    # 获取目标
    var targets = custom_targets if !custom_targets.is_empty() else _get_targets_for_skill(skill_data)

    # 处理直接效果
    var effect_results = {}
    if not skill_data.effects.is_empty():
        effect_results = await apply_effects(skill_data.effects, caster, targets)

    # 发送技能执行信号
    skill_executed.emit(caster, targets, skill_data, final_results)
    return final_results

4.2 状态效果的应用与触发

协作流程

  1. 状态效果处理器处理状态应用
  2. 状态成功应用后,触发其初始效果
  3. 状态效果处理器通过战斗管理器调用 _apply_skill_effects_to_targets()
  4. 战斗管理器处理状态的初始效果

代码示例

# 在 ApplyStatusProcessor 中
if results.success and is_instance_valid(applied_status_instance):
    # 状态成功应用/更新后,触发其初始效果
    if not applied_status_instance.initial_effects.is_empty():
        if _battle_manager and _battle_manager.has_method("_apply_skill_effects_to_targets"):
            await _battle_manager._apply_skill_effects_to_targets(
                applied_status_instance.get_initial_effects(),
                applied_status_instance.source_char, 

[target]

)

5. 系统架构设计评估

5.1 优点

  • 模块化设计:效果处理器与战斗管理器分离,职责清晰
  • 可扩展性:新效果类型只需添加新的处理器类
  • 灵活性:效果处理逻辑集中在各自的处理器中,便于维护
  • 一致性:所有效果处理遵循相同的接口和流程

5.2 潜在改进点

  • 错误处理:可以增加更完善的错误处理机制
  • 效果组合:可以考虑支持效果组合和连锁反应
  • 性能优化:对于大量效果的处理可以考虑批处理
  • 可视化调试:可以添加更多的调试信息和可视化工具

6. 总结

战斗效果处理系统采用了基于处理器模式的设计,通过 EffectProcessor 基类和具体实现类,实现了对不同类型效果的统一处理。战斗管理器作为中心协调者,负责初始化、注册和调用效果处理器,同时管理整个战斗流程。

这种设计使得系统具有良好的可扩展性和可维护性,能够轻松添加新的效果类型和处理逻辑。同时,通过信号机制和回调函数,实现了各组件之间的解耦和高效通信。

整体架构清晰、层次分明,为战斗系统提供了灵活而强大的效果处理能力。

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇