2012-01-16 3 views
2

Я разрабатываю небольшую игру на Java, и у меня возникла проблема, позволяющая отвлечь мой игровой мир от используемой структуры.Java Game Dev: попытка разделить мир и рендеринга

Как у меня сейчас, у меня есть класс World, который отслеживает все разные объекты в мире и обновляет их в соответствии с правилами игры. Затем у меня есть три основных класса объектов Person, Obstacle и Item. Каждый объект имеет разные «типы», которые представлены переменной-членом. Все классы объектов расширены из класса GameObject.

Как у меня сейчас, World и классы объектов отделены от рамки, которая отображает игру и т. Д. Класс Game обе сообщает миру обновлять и отображать мир и объекты в мире.

Проблема заключается в том, что я визуализировать объекты с тремя методами drawPersons(), drawObstacles() и drawItems() это хорошо, потому что я уже написал код, и я не буду добавлять любые другие классы объектов. Реальная проблема заключается в рендеринге разных «типов» каждого класса объектов. Поскольку у меня есть это сейчас, методы рисования рисуют элементы, проверяя переменную object.type, тогда есть оператор switch, который выбирает соответствующий растровый рисунок для рисования.

Я хочу упростить это, поэтому мне не нужно добавлять оператор switch каждый раз, когда я добавляю новый «тип» к классу Item, например. Единственный способ, с помощью которого я могу это сделать, - это сохранить объекты в том, какие растровые изображения они должны отображаться, как при их построении, и установить их переменную item.type. Таким образом, я могу удалить инструкции switch из метода drawItems(). Кроме того, я мог бы также дать каждому классу объектов метод draw() blah blah blah, но причина, по которой я не хочу этого делать, заключается в том, что он разрушает разделение, которое я получаю от рендеринга/рамки и воображаемого игрового мира.

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

Есть ли способ, которым я могу иметь оба?

+2

Как примечание стороны: вы можете получить более конкретную помощь здесь: http://gamedev.stackexchange.com/ – Thomas

+0

Благодарим за предложение, есть ли способ переместить этот вопрос там или просто передать вопрос ? –

+0

Я не уверен, если вы можете задать вопрос, но я уверен, что модератор может это сделать. Мы могли бы отметить это для внимания модератора, чтобы заставить их переместить его, если хотите. – Thomas

ответ

2

Что вы можете сделать, это использовать композицию, то есть ваши объекты содержат несколько компонентов, которые имеют разные цели. Например, может быть компонент рендеринга, физический компонент, компонент ai и т. Д.

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

В этом случае компоненты рендеринга может содержать данные, такие как текстуры/растровое изображение, форма, материал и т.д.

Для получения дополнительной информации вы можете посмотреть в entity systems.

+0

Ваша ссылка привела меня в [эту статью] (http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/), и мне любопытно, как я это сделаю прямо в Java. –

+0

@StickFigs Взгляните на разделы, посвященные раскрывающимся версиям ссылки, которую я опубликовал. У автора есть пример реализации Java там (на самом деле есть два: ES Alpha и ES Beta). Вот ссылка на репозиторий ES Beta для удобства: https://github.com/adamgit/Entity-System-RDBMS-Beta--Java- – Thomas

+0

Поскольку я больше не могу редактировать свой комментарий, вот вам поправка: посмотрите на ссылке «Подходы ES» в первом разделе статьи, которую я связал :) – Thomas

2

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

+1

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

+0

Абстракция может наилучшим образом служить вам в объектно-ориентированной среде с большим количеством перекрытий данных. Также подумайте о модульности кода. Абстракция может иметь разные формы. Исчерпывая методы draw() из ваших доступных объектов, вы жертвуете гибкостью своего цикла визуализации World. Там могут быть более жизнеспособные решения, но оператор switch() определенно * не * способ приблизиться к нему. Удачи. – collinjsimpson

2

Вы можете изучить Visitor pattern. Объекты игрового мира принимают посетителя, который грамотно через них выполняет некоторую операцию: в этом случае операция выполняется. Логика выбора различных реализаций на основе того, что игровой объект хранится на стороне посетителя.

2

Я считаю, что вы можете обернуть свои классы, используя Decorator Pattern.

Декоратор содержит экземпляр GameObject, а также реализует функции GameObject, вызывая методы на исходном экземпляре.

Когда вы подклассифицируете GameObject таким образом, вы также можете сделать декораторы реализовывать интерфейс Renderable с помощью метода draw().

1

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

как этот

public abstract class GameObject{ 

... 
... 
.. 

public abstract TextureRegion getGameObjectTextureRegion(); 
... 
.. 
} 

и в каждом классе, который расширяет GameObject хранить переменную экземпляра, как этот

public class Person extends GameObject{ 
.... 
.... 
... 
public static final TextureRegion person_region = new TextureRegion(top,left,height,width); 
... 
... 
public TextureRegion getGameObjectTextureRegion(){ 
return person_region; 
} 

затем хранить все ваши игровые объекты в массиве или ArrayList как это

ArrayList<GameObject> game_objects = new ArrayList<GameObject>(); 
//add items to it 
game_objects.add(new Person()); 
gmae_objects.add(...); 

и в методе рисования ha Список me_objects и вызвать getGameObjectTextureRegion

for(GameObject item : game_objects) 
{ 
TextureRegion region = item.getGameObjectTextureRegion(); 
// then pass them with the game object position to your rendering method 
... 


} 

примечания: TextureRegion выглядит следующим образом

public class TextureRegion{ 

float top; 
float left; 
float width; 
float height; 
} 
+0

Мне нравится эта идея в теории, но, к сожалению, я часто подвержен изменениям графических активов, и мой рабочий процесс недостаточно сложный, чтобы автоматически обрабатывать все смещения вокруг мне нужно было бы сделать с атласом –

0

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

У вас может быть какая-то переменная «resources», в которой хранятся пары объектов object_type: data, которые содержат необходимые ресурсы для каждого типа объектов, которые вы собираетесь вставлять в свой мир. Переменная «resources» может быть списком анимаций или любых других общих ресурсов.

Чтобы быть более конкретным, позвольте привести пример в Python (так как это то, что я знаю лучше всего). Не должно быть проблемой применять одно и то же на Java или практически на любом другом языке. В Python, я хотел бы создать словарь переменную, которая выглядит следующим образом:

{ 
Person1:["person1.bmp", "person1_alternative1.bmp", "person1_whatever.wmv"], 
Person2:["person2.bmp", "person2_alternative1.bmp", "person2_whatever.wmv"], 
Obstacle1:["Obstacle1.bmp", "Obstacle1_alternative1.bmp", "Obstacle1_whatever.xyz"], 
Obstacle1:["Item1.bmp", "Item1_alternative1.bmp", "Item1_whatever.xyz"] 
} 

... и так далее

Вы можете расширить, что, кроме того, как вы считаете нужным; Добавьте другие виды ресурсов, возможно, координаты объектов, размеры или что-то еще.Например,

{ 
person1:{basic_animation:"person1.bmp", alt_animation:"person1_alternative1.bmp", sfx1:"person1_whatever.wmv"}, 
person2:{basic_animation:"person2.bmp", alt_animation:"person2_alternative1.bmp", sfx1:"person2_whatever.wmv"}, 
obstacle1:{basic_animation:"obstacle1.bmp", alt_animation:"obstacle1_alternative1.bmp", res1:"obstacle1_whatever.xyz"}, 
item1:{basic_animation:"item1.bmp", alt_animation:"item1_alternative1.bmp", sfx1:"item1_whatever.wmv"} 
} 

Синтаксис и, вероятно, отличается в Java, но вы получаете общую идею. Я не уверен, как Java обрабатывает ключ: значение типа переменных, я предполагаю, что для этого есть некоторый класс. Если нет, вы всегда можете сделать свой собственный.

Эта большая переменная ресурсов может быть частью вашего игрового класса и быть инициализирована и заполнена соответствующими данными, когда вы экземпляр класса игры. Его можно даже хранить в другом месте, если вы предпочитаете группировать все свои константы в отдельном месте/модуле/независимо от того, что я делаю!). Затем вы можете объединить эти drawPersons(), drawObstacles() и drawItems() в одну функцию draw(), которая проверяет «object.type» для каждого «объекта» и ищет его в «ресурсах», чтобы получить соответствующие данные.

Теперь я не знаю о производительности и других факторах, возможно, это требует некоторой оптимизации от кого-то умнее!

+0

Ничего себе! Я только что понял, сколько лет вопрос: | –

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