Max Dohme
Max Dohme

Reputation: 700

How do you give multiple classes additional functionality without inheritance in AS3?

I am writing a game in ActionScript where I've got multiple classes that should be "hitable" by shots.

The most generic class that all other in-game entities inherit from is CombatObject; The classes CombatShip, CombatAsteroid and various others inherit from it. The classes CombatAi and CombatPlayer both inherit from CombatShip.

Now I want to make CombatAi, CombatPlayer and CombatAsteroid hitable by shots, but I don't want them to inherit it (later there might be CombatShips that shouldn't be hitable).

My idea now was to have these three implement an Interface, IHitable, so that when they collide with a shot, I can ask if(hitObject is IHitable) and if true, have the shot destroyed and do damage.

Now the question is, would it be best to have each of these classes

  1. Implement all the needed code to take damage (such as checking shields, calculating damage percentages, etc.) themselves
  2. Have them all own an instance of the class DamageManager and implement a function getDamageManager():DamageManager, that returns a class that handles all damage related functionality
  3. One disadvantage of (2.) would be that each CombatShip, CombatAsteroid, etc would have to own an Instance of DamageManager. Would it perhaps be even better to have DamageManager be a Singleton and just have a reference to the ship and the shot given to it and let it handle the rest?

Upvotes: 0

Views: 721

Answers (3)

subb
subb

Reputation: 1568

Mixins are a good idea, but its support in AS3 is, well, simulated.

Option 2 will work, but exposing the instance of DamageManager breaks the encapsulation. You could solve this by adding a hit method in your IHitable interface. This method will be called by your game when something hits this object. The implementation of this method is up to the object. You could implement it differently for each object (option 1) but you could also create a generic DamageManager class and use it to calculate the damage.

class DamageManager {
    public function calculateDamage(...){
        // implement your damage logic...
    } 
}

interface IHitable {
    function hit(by:GameObject);
}

And for exemple in CombatPlayer

class CombatPlayer implements IHitable
{
    private var _damage:DamageManager;

    public function CombatPlayer(){
         _damage = new DamageManager();
    }

    public function hit(by:GameObject):void {
        _damage.calculateDamage(...);
    }
}

I've left the implementation on DamageManager open since I don't know how your objects are implemented neither how you want to calculate the damage.

I think that ideally, the DamageManager should not modify directly your object. You could pass a Stat object (which holds the object's health and shield information) along with another object describing the properties of the "hitter" and the DamageManager will return another Stat object which you can use to update the "hittee"'s stats.

Hope it makes some senses!

Upvotes: 1

PatrickS
PatrickS

Reputation: 9572

What about implementing an isHitable getter , in the IHitable interface, this could allow more flexibility if you want to make changes in certain classes later in the game, because with a IHitable instance "is IHitable" will always return true.

Depending on the type of calculations & resulting modifications, DamageManager doesn't really have to be a Singleton, you could call a static method that would handle the damage assessment and return your modified object.

Upvotes: 0

geofflee
geofflee

Reputation: 3781

Option 1 would result in a lot of repetitive code, and that's bad for obvious reasons.

Option 3 would mean that all your collision code goes into a single class. From an encapsulation standpoint, this is bad because you'll end-up with a behemoth class that handles everything.

That leaves Option 2 as the best option. Option 2 is better than option 3 because you can extend the DamageManager class for different types of ships and asteroids.

However, I would also like to present an option 4: mixins

Mixins are a language-level feature that allow you to add common functionality to multiple classes without inheritance. Although the ActionScript 3 language doesn't support mixins, AS3 is flexible enough that you can simulate it. Mixin or Trait implementation in AS3?

Upvotes: 1

Related Questions