我正在为
Android手机制作Java射击游戏.我在游戏中有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(玩家,50 /像素/,新的MoveRandomlyBehaviour(),新的HomingBehaviour()).这使得制造新敌人变得非常容易.
困扰我的唯一部分是行为和渲染器的沟通方式.目前,Entity包含一个Image对象,如果行为选择这样做,行为可以修改.例如,一种行为可以改变睡眠和清醒图像之间的对象,渲染器只会绘制图像.我不确定这是如何规模的,例如:
>面向某个方向的炮塔式敌人怎么样?我想我可以向Entity添加一个旋转字段,行为和渲染器都可以修改/读取.
>坦克的主体和坦克的枪有不同方向的坦克怎么样?现在,渲染器需要访问来自某处的两个旋转以及要使用的两个图像.如果只有一个坦克,你真的不想用这个膨胀Entity类.
>当他的枪充电时,一个发光的敌人怎么样?您确实希望将充电时间存储在Behavior对象中,但Renderer类无法看到它.
我无法想出如何对上述模型进行建模,因此渲染器和行为可以保持一定程度的分离.我能想到的最好的方法是让行为对象包含额外的状态和渲染器对象,然后行为对象调用渲染器绘制方法,并在需要时传递额外的状态(例如旋转).
你可以,例如有一个类似坦克的行为对象,需要一个类似坦克的渲染器,后者要求两个图像和两个旋转绘制.如果你想让你的坦克只是一个普通的图像,你只需要编写一个忽略旋转的子类渲染器.
谁能想到任何替代品?我真的很想要简单.因为它是一种游戏,所以如果例如效率也可能是一个问题.绘制一个5×5的敌人图像,当我有50个敌人以60fps左右飞行时,涉及多层功能调用.