2015-05-29 4 views
0

Я пишу простую игру, в которой у нас есть коллекция объектов, где игрок перемещается по сетке, собирает монету и избегает монстров.Избегайте использования примера:

Моя классная структура выглядит следующим образом.

Game Controller - Ответственный за нерестовые монеты и отслеживание состояния игры

Сетка - класс, который хранит объекты, которые в настоящее время находятся на сетке, и связанные с ними методы несколько сетки.

GridObject - абстрактный класс, представляющий объект на сетке. например игрок, монстр или монета.

Игрок, Монстр, Монета - Все виды GridObject.

Каков самый способ ООП для обработки столкновений? Желаемый результат: Игрок ударяет по монстру - конец игры, Игрок ударяет монеты - увеличивает счет, Монстр хиты Монета - ничего.

В настоящее время, когда объект GridObject перемещается, он уведомляет объект платы, который он хочет переместить; если это вызовет столкновение, я вызываю обработчик на GameController (через шаблон прослушивателя) для обработки столкновения. В этом обработчике, который принимает два GridObjects в качестве параметров, я использую множество команд «instanceof», чтобы отличать вышеуказанные случаи.

Каков наилучший способ избежать использования всего этого «экземпляра», который я прочитал, как правило, означает плохой дизайн?

ответ

0

насчет введения некоторых интерфейсов:

interface Interactable { 

    InteractionResult interact(WorldEntity entity); 

} 

interface WorldEntity { 

    boolean isMonster(); 

    boolean isPlayer(); 

    boolean isPowerUp(); 

} 

Теперь мы можем сказать, что, когда игрок взаимодействует с другими вещами, мы можем сделать:

public InteractionResult interact(WorldEntity entity) { 
     if(entity.isMonster()) { 
      return new DeathInteraction(this); 
     } 
     ... 
    } 

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

+0

Это приятное решение, что-то мне немного неловко об осуществлении этого с моим текущим кодом, но я не могу сейчас на него надавить ... Я еще раз прокомментирую, если у меня возникнут проблемы – WMycroft

+0

Doesn ' t означает, что каждый класс, который реализует этот интерфейс, должен будет переопределить все эти логические методы, возвращая false для всех из них, кроме одного? Я чувствую, что это намного более грязно, чем просто оставлять вызовы instanceof. –

+0

У вас могут быть абстрактные классы с реализацией по умолчанию –

0

Вместо использования instanceof вы можете использовать перечисление в GridObject для определения типа. Таким образом, вы просто сравниваете перечисление, чтобы проверить, какие объекты сталкиваются. Например, (предупреждение, синтаксис может быть не совсем правильно)

public enum ObjectType { 
    Player, Monster, Coin 
} 

private final ObjectType type; 

public GridObject(ObjectType type) { 
    this.type = type; 
} 

public ObjectType getType() {return type;} 

, а затем в ваших подклассов, вы должны сделать следующее:

public Player(your parameters) { 
    super(ObjectType.Player); 
} 

А затем для проверки типов , вы можете просто сделать:

switch(gridObject.getType()) { 
    case ObjectType.Player: 
     // do something 
     break; 
    case ObjectType.Monster: 
     // do something else 
     break; 
    case ObjectType.Coin: 
     // do something else 
     break; 
} 
+0

Hi Joseph, спасибо, что ответ! Это, безусловно, более элегантное решение того, что я делаю в данный момент, но логично, что это точно так же, как с использованием instanceof, так ли это, возможно, скрывает плохой дизайн, а не решает проблему? – WMycroft

+1

@WMycroft Возможно, вы правы, я немного искал, и, кажется, предпочтительный метод, если можно, состоит в том, чтобы создать абстрактный метод в вашем суперклассе и каждый подкласс реализовать его по-разному. См. [Этот вопрос] (http://stackoverflow.com/questions/5579309/switch-instanceof) для примера. Однако, если это невозможно (что, похоже, не будет для вашей ситуации), то, как вы можете видеть из этого же вопроса, перечисление является разумной альтернативой. –

+0

Я предполагаю, что главная проблема, с которой мы сталкиваемся, состоит в том, что столкновение действительно является свойством ** двух ** объектов, и поэтому не будет подходящего места, где мы можем поместить абстрактный метод в иерархию ... – WMycroft

Смежные вопросы