【问题标题】:How do you give multiple classes additional functionality without inheritance in AS3?在 AS3 中如何在不继承的情况下为多个类提供附加功能?
【发布时间】:2010-10-29 21:56:26
【问题描述】:

我正在用 ActionScript 编写一个游戏,其中有多个应该可以被击球“击中”的类。

所有其他游戏内实体继承的最通用的类​​是 CombatObject; CombatShip、CombatAsteroid 和其他各种类都继承自它。 CombatAi 和 CombatPlayer 类都继承自 CombatShip。

现在我想让 CombatAi、CombatPlayer 和 CombatAsteroid 可以被击中,但我不希望它们继承它(以后可能会有不应该被击中的 CombatShips)。

我现在的想法是让这三个实现一个接口,IHitable,这样当它们与一个镜头发生碰撞时,我可以询问if(hitObject is IHitable),如果为真,则销毁该镜头并造成伤害。

现在的问题是,最好分别拥有这些课程吗

  1. 自己实现所有需要的代码来承受伤害(例如检查护盾、计算伤害百分比等)
  2. 让他们都拥有一个 DamageManager 类的实例并实现一个函数 getDamageManager():DamageManager,该函数返回一个处理所有与损坏相关的功能的类
  3. (2.) 的一个缺点是每个 CombatShip、CombatAsteroid 等都必须拥有一个 DamageManager 实例。让 DamageManager 成为一个 Singleton 并且只引用船和给它的镜头并让它处理其余部分可能会更好吗?

【问题讨论】:

    标签: actionscript-3 game-engine


    【解决方案1】:

    Mixins 是个好主意,但它在 AS3 中的支持是模拟的。

    选项 2 会起作用,但暴露 DamageManager 的实例会破坏封装。您可以通过在 IHitable 界面中添加 hit 方法来解决此问题。当有东西击中这个对象时,你的游戏会调用这个方法。此方法的实现取决于对象。您可以为每个对象以不同的方式实现它(选项 1),但您也可以创建一个通用的 DamageManager 类并使用它来计算损坏。

    class DamageManager {
        public function calculateDamage(...){
            // implement your damage logic...
        } 
    }
    
    interface IHitable {
        function hit(by:GameObject);
    }
    

    以 CombatPlayer 为例

    class CombatPlayer implements IHitable
    {
        private var _damage:DamageManager;
    
        public function CombatPlayer(){
             _damage = new DamageManager();
        }
    
        public function hit(by:GameObject):void {
            _damage.calculateDamage(...);
        }
    }
    

    我已将 DamageManager 上的实现保持打开状态,因为我不知道您的对象是如何实现的,也不知道您希望如何计算损坏。

    我认为理想情况下,DamageManager 不应该直接修改您的对象。您可以传递一个 Stat 对象(包含对象的健康和护盾信息)以及另一个描述“hitter”属性的对象,DamageManager 将返回另一个 Stat 对象,您可以使用它来更新“hittee”的统计信息。

    希望它有一些意义!

    【讨论】:

    • 您对封装完全正确,这看起来是非常糟糕的做法,我什至从未注意到。您对 stat 对象的想法很有趣:所以想法是您想要操作“hitee”的多个值但您不想传递对自身的引用(即直接操作它),因此您使用 stat 对象作为容器来回传递信息并保持封装完整?另一个问题:这是返回多个值时的一般最佳做法吗?
    • 是的,就是这样。对于您的另一个问题,我不确定是否有另一种方法可以返回多个值,而不是返回具有这些值的对象,至少在 AS3 中是这样。
    【解决方案2】:

    选项 1 会导致大量重复代码,这显然是不好的。

    选项 3 意味着您的所有碰撞代码都进入一个类。从封装的角度来看,这很糟糕,因为您最终会得到一个处理所有事情的庞然大物。

    这使得选项 2 成为最佳选项。选项 2 比选项 3 更好,因为您可以为不同类型的船舶和小行星扩展 DamageManager 类。

    不过,我还想介绍一个选项 4:mixins

    Mixins 是一种语言级别的功能,它允许您向多个类添加通用功能而无需继承。尽管 ActionScript 3 语言不支持 mixin,但 AS3 足够灵活,您可以模拟它。 Mixin or Trait implementation in AS3?

    【讨论】:

    • 选项 3 仅在击中检测(在镜头中)评估了镜头确实击中并且物体可击中后才被调用。然后它会根据某种算法进行伤害计算,并将伤害传递给被击中的物体。
    【解决方案3】:

    在 IHitable 接口中实现 isHitable getter 怎么样,如果您想在游戏后期对某些类进行更改,这可以提供更大的灵活性,因为使用 IHitable 实例“is IHitable”将始终返回 true。

    根据计算类型和产生的修改,DamageManager 不一定是单例,您可以调用静态方法来处理损坏评估并返回修改后的对象。

    【讨论】:

    • 这个想法是只给那些“hitable”的类 IHitable 接口,即 CombatPlayer、CombatAi、CombatAsteroid;但不是战斗舰。使用静态方法而不是 Singleton 有什么好处?单例不只是一个带有静态方法的实例的类吗?
    • 只是跟随你说一些 CombatShips 可能无法被击中,稍后在游戏中。至于Singleton,不是真的……单个静态方法比不上Singleton类。
    猜你喜欢
    • 1970-01-01
    • 2010-12-24
    • 2015-11-25
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 1970-01-01
    • 1970-01-01
    • 2021-05-07
    相关资源
    最近更新 更多