Я делаю Java-игру «Стреляй им» для телефонов Android. У меня в игре 20 странных врагов, у каждого из которых есть несколько уникальных поведений, но большинство из них используют определенные виды поведения. Мне нужно смоделировать пули, взрывы, астероиды и т. Д. И другие вещи, которые тоже действуют немного как враги. Мой текущий дизайн предпочитает композицию наследованию и представляет игровые объекты примерно так:
// Generic game object
class Entity
{
// Current position
Vector2d position;
// Regular frame updates behaviour
Behaviour updateBehaviour;
// Collision behaviour
Behaviour collideBehaviour;
// What the entity looks like
Image image;
// How to display the entity
Renderer renderer;
// If the entity is dead and should be deleted
int dead;
}
abstract class Renderer { abstract void draw(Canvas c); }
abstract class Behaviour { abstract void update(Entity e); }
Чтобы просто нарисовать все, что хранится в виде изображения сущности, вы можете прикрепить простое средство рендеринга, например,
class SimpleRenderer extends Renderer
{
void draw(Canvas c)
{
// just draw the image
}
}
Чтобы заставить объект беспорядочно летать в каждом кадре, просто добавьте такое поведение:
class RandomlyMoveBehaviour extends Behaviour
{
void update(Entity e)
{
// Add random direction vector to e.position
}
}
Или добавьте более сложное поведение, например, ожидание, пока игрок не приблизится, прежде чем войти в систему:
class SleepAndHomeBehaviour extends Behaviour
{
Entity target;
boolean homing;
void init(Entity t) { target = t; }
void update(Entity e)
{
if (/* distance between t and e < 50 pixels */)
{
homing = true;
// move towards t...
}
else
{
homing = false;
}
}
}
Пока я действительно доволен этим дизайном. Это приятно и гибко, что вы можете, например, Модульный последний класс, чтобы вы могли предоставить поведение «сна» и «пробуждение», чтобы вы могли сказать что-то вроде нового WaitUntilCloseBehaviour (player, 50 / пикселей /, new MoveRandomlyBehaviour (), new HomingBehaviour () ). Это позволяет легко создавать новых врагов.
Единственная часть, которая беспокоит меня, это то, как взаимодействуют поведение и рендеры. На данный момент Entity содержит объект Image, который Поведение может изменить, если решит это сделать. Например, одно поведение может изменить объект между спящим и проснувшимся изображением, а средство визуализации просто нарисует изображение. Я не уверен, как это будет масштабироваться, хотя, например ::
А как насчет турель-подобного врага, который стоит в определенном направлении? Полагаю, я мог бы добавить поле вращения в Entity, чтобы Behavior и Renderer могли изменять и читать.
А как насчет танка, в котором корпус танка и пистолет танка имеют разные направления? Теперь рендереру нужен доступ к двум поворотам откуда-то и двум изображениям для использования. Вы действительно не хотите раздувать класс Entity с этим, если есть только один танк.
А как насчет врага, который светится, когда его пистолет заряжается? Вы бы действительно хотели сохранить время перезарядки в объекте Behavior, но тогда класс Renderer не сможет его увидеть.
Мне трудно подумать о том, как смоделировать вышесказанное, чтобы визуализаторы и поведение можно было разделить. Лучший подход, который я могу придумать, - это чтобы объекты поведения содержали дополнительное состояние и объекта рендеринга, тогда объекты поведения вызывают метод рисования рендерера и передают дополнительное состояние (например, вращение), если они хотят .
Вы могли бы, например, иметь объект поведения, похожий на танк, который требует рендерера, похожего на танк, где последний запрашивает два изображения и два поворота для рисования. Если бы вы хотели, чтобы ваш танк был просто изображением, вы просто написали бы рендерер подкласса, который игнорировал бы повороты.
Может кто-нибудь придумать какие-нибудь альтернативы? Я действительно хочу простоты. Поскольку это игра, эффективность может быть проблемой, если, например, Рисование одного изображения врага 5x5, когда у меня 50 врагов, летающих со скоростью 60 кадров в секунду, включает в себя множество слоев вызовов функций.