Объектно-ориентированный дизайн игры на Java: как справиться с партией NPC? - PullRequest
3 голосов
/ 20 апреля 2010

Я делаю очень простую 2D RPG на Java. Моя цель - сделать это как можно более простым кодом. Разобравшись с основами, моя структура классов на данный момент выглядит следующим образом:

  • Физические объекты имеют х и у измерение.
    • Роуминг-объекты - это физические объекты. который может двигаться ().
      • Гуманоидные объекты - это перемещающиеся объекты. которые имеют инвентарь GameItems.
        • Игрок - гуманоид-одиночка объект, который может нанять до 4 NPC гуманоидов присоединиться к его или ее группе и выполнять другие действия, такие как борьба с негуманоидными объектами.
        • NPC Гуманоиды могут быть наняты Объект игрока, чтобы присоединиться к его или ее партия, и однажды нанятый может бороться за игрока.

Пока что я дал классу Игрока "ArrayList" для группы NPC-гуманоидов, а классу "NPC-гуманоиды" - "наемный" логический объект.

Однако мой метод боя неуклюжий, использующий if для проверки размера партии перед началом боя, например,

public class Player extends Humanoids {
   private ArrayList<Humanoids> party;
   // GETTERS AND SETTERS for party here
   //...

   public void fightEnemy(Enemy eneObj) {
      if (this.getParty().size() == 0)
        // Do combat without party issues
      else if (this.getParty().size() == 1)
        // Do combat with party of 1
      else if (this.getParty().size() == 2)
        // Do combat with party of 2
      // etc. 

Мой вопрос заключается в том, что, думая об объектно-ориентированном дизайне, я на правильном пути, чтобы сделать это как можно более простым кодом? Есть ли лучший способ?

Ответы [ 4 ]

7 голосов
/ 20 апреля 2010

" Мой вопрос заключается в том, что, думая об объектно-ориентированном дизайне, я на правильном пути, чтобы сделать это как можно более простым кодом? "

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

Физические объекты имеют размеры x и y (положение).
[Объект роуминга - это физический объект, который имеет изменяемое положение]
Гуманоидные объекты - это перемещающиеся объекты, которые имеют запасы.
Игрок является синглтоном гуманоидным объектом, который может иметь группу
[Партия имеет игрока и] имеет до 4 NPC-гуманоидов

Композиция, хотя слишком редко подчеркивается в объектно-ориентированном дизайне, играет роль в коде. Вот почему различие имеет-1030 * / является-1032 * так часто используется в анализе.

Объявляя игрока одиночным игроком, вы добавили сложность шрифта и, возможно, ограничили свой дизайн. Что если вы хотите иметь двух игроков в будущем? Как насчет большего? Это не является необоснованным расширением, но потребует, чтобы вы нарушили используемый одноэлементный анти-шаблон. Если вам нужен только один игрок, создайте только один экземпляр; кодирование предположения о единственности в классе неоправданно ограничивает. Помните, что кодер должен утвердительно вызывать конструктор и не должен беспокоиться о появлении игроков спонтанно.

У объекта есть отличная позиция: дайте ему одну композицию. Позицию можно изменить, поэтому определите position :: move (). У игрока может быть человек-контролер, который отличает его от NPC, но - по определению - персонаж, не являющийся игроком - это персонаж, у которого есть контроль, который не приходит от игрока. Можете ли вы дать игроку NPC контроль? Многие игры делают, но если вы уже закодировали зависимость персонажа от игрока внутри класса, NPC всегда будет NPC.

Кроме того, насколько вы уверены, что 4 (или 5) - хорошее число для вечеринки? Принцип Zero, One, Infinity гласит, что если вы разрешите более одного, разрешите произвольное число. Если вы не жестко закодируете «пятерку» в своем дизайне, вы ограничите гибкость.

Я обычно рекомендую, чтобы дизайнеры рассматривали наследование как метод последней инстанции из-за истории чрезмерного использования. Дизайн может быть ООП без наследования вообще. Полиморфизм - это круто, но инкапсуляция и абстракция - это, может быть, даже больше.

2 голосов
/ 20 апреля 2010

Что ж, забывая об общем дизайне, с точки зрения программирования, вместо того, чтобы иметь структуру if, у вас должен быть метод, который принимает размер партии в качестве аргумента. Таким образом, вы можете просто ввести this.getParty().size() и избавиться от if s.

т.е.

  combatManager.fight(this.getParty().size(), eneObj);

Где combatManager - это объект (или класс, если вам нужна статическая версия), который знает, как создавать вещи fight.

Как я уже сказал, это не решение для вашего дизайна, просто более хороший способ избежать if s.

Класс Player не должен отвечать за боевые действия, поэтому, возможно, вы можете изменить свой метод fightEnemy на engageEnemy или что-то еще, и просто попросить его перейти в battleManager с правильными параметрами.

0 голосов
/ 20 апреля 2010

Игрок является частью партии. NPC тоже являются частью партии. Зачем игроку вести бой с NPC? Я думаю, что вы должны добавить эту логику в класс NPC (расширяет Humanoid) и позволить добавить немного AI, чтобы NPC действовали вместе с игроком и другими NPC, когда они группируются вместе.

0 голосов
/ 20 апреля 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...