Как вы даете нескольким классам дополнительную функциональность без наследования в AS3? - PullRequest
0 голосов
/ 30 октября 2010

Я пишу игру на 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 был синглтоном и имел бы ссылку на корабль и данный ему выстрел и позволял ему справляться с остальными?

Ответы [ 3 ]

1 голос
/ 30 октября 2010

Mixins - хорошая идея, но ее поддержка в AS3, ну, в общем, имитируется.

Вариант 2 будет работать, но раскрытие экземпляра DamageManager нарушает инкапсуляцию. Вы можете решить эту проблему, добавив метод Hit в ваш интерфейс IHitable. Этот метод будет вызываться вашей игрой, когда что-то попадает в этот объект. Реализация этого метода зависит от объекта. Вы можете реализовать его по-разному для каждого объекта (вариант 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 (который содержит информацию о здоровье и щите объекта) вместе с другим объектом, описывающим свойства "нападающего", и DamageManager вернет другой объект Stat, который можно использовать для обновления статистики "нападающего".

Надеюсь, что это имеет смысл!

1 голос
/ 30 октября 2010

Вариант 1 приведет к большому количеству повторяющегося кода, и это плохо по очевидным причинам.

Вариант 3 будет означать, что весь ваш код столкновения входит в один класс. С точки зрения инкапсуляции это плохо, потому что в итоге вы получите класс бегемота, который обрабатывает все.

Это оставляет вариант 2 лучшим вариантом. Вариант 2 лучше, чем вариант 3, поскольку вы можете расширить класс DamageManager для различных типов кораблей и астероидов.

Тем не менее, я также хотел бы представить вариант 4: mixins

Миксины - это функция уровня языка, которая позволяет добавлять общие функции к нескольким классам без наследования. Хотя язык ActionScript 3 не поддерживает миксины, AS3 достаточно гибок, чтобы его можно было смоделировать. Реализация миксинов или черт в AS3?

0 голосов
/ 30 октября 2010

Что касается реализации isHitable getter, в интерфейсе IHitable, это может позволить больше гибкости, если вы захотите внести изменения в определенные классы позже в игре, потому что с экземпляром IHitable «is IHitable» всегда будет возвращать true.

В зависимости от типа расчетов и полученных изменений, DamageManager на самом деле не обязательно должен быть Singleton, вы можете вызвать статический метод, который будет обрабатывать оценку ущерба и возвращать ваш измененный объект.

...