如何模块化游戏对象渲染和行为?

我正在为Android手机制作一个Java射击游戏。 我在游戏中有20个奇怪的敌人,每个都有一些独特的行为,但是大多数行为都被重用。 我需要模拟子弹,爆炸,小行星等等,其他的东西也都像敌人一样。 我目前的devise倾向于inheritance的构成,并代表游戏对象有点像这样:

// 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 } } 

或者添加更复杂的行为,如等待玩家closures之前closures:

 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; } } } 

到目前为止,我对这个devise非常满意。 这是很好的和灵活的,你可以例如模块化后一类,所以你可以提供“睡眠”行为和“清醒”的行为,所以你可以说像新的WaitUntilCloseBehaviour(播放器,50 / 像素 /,新的MoveRandomlyBehaviour() HomingBehaviour())。 这使得新的敌人很容易。

    困扰我的唯一部分是行为和渲染者如何沟通。 目前,实体包含一个行为可以修改,如果它select这样做的图像对象。 例如,一个行为可能会改变睡眠和清醒图像之间的对象,渲染器只会绘制图像。 我不确定这是怎么回事,例如:

    • 如何面对一个方向的炮塔般的敌人呢? 我想我可以添加一个旋转字段到行为和渲染器都可以修改/读取的实体。

      • 那么坦克的身体和坦克的枪有不同的方向呢? 现在,渲染器需要从某个地方访问两个旋转以及要使用的两个图像。 如果只有一个坦克,你不会真的想膨胀实体类。

      • 当他的枪补充一个敌人发光呢? 您确实需要将充值时间存储在Behavior对象中,但是Renderer类无法看到它。

    我很难想出如何对上面的模型进行build模,所以渲染器和行为可以保持一定的分离。 我能想到的最好的方法是让行为对象包含额外的状态渲染器对象,然后行为对象调用渲染器的绘制方法,并在需要时传递额外的状态(如旋转)。

    然后,你可以有一个坦克般的行为对象,想要一个坦克般的渲染器,后者要求两个图像和两个旋转来绘制。 如果你想让你的坦克只是一个普通的图像,你只需要写一个忽略旋转的子类渲染器。

    任何人都可以想到任何替代品? 我真的很想简单。 因为这是一个游戏,效率也可能是一个问题,例如,如果绘制一个5×5的敌人图像,当我有五十个敌人以60fps的速度飞行时,涉及到很多层的函数调用。

    Related of "如何模块化游戏对象渲染和行为?"

    组合devise是有效的,因为它允许混合和匹配行为和渲染。

    在我们玩的游戏中,我们添加了一个“数据包”,其中包含基本信息(在您的情况下是位置和死/活状态)以及由行为和碰撞子系统设置/取消设置的variables数据。 渲染器可以使用这些数据(如果不需要,也可以不使用)。 这个工作很好,并允许整齐的效果,比如为给定的graphics效果设置“目标”。

    一些问题:

    • 如果渲染器请求数据表明行为没有设置。 在我们的例子中,事件被logging,并且使用默认值(在渲染器中定义)。
    • 事先检查需要的信息有点困难(比如,渲染器A的数据包中应该包含哪些数据?由行为B设置了哪些数据?)。 我们试图保持文档是最新的,但我们正在考虑通过类loggingset / get,并生成一个文档页面…

    目前我们正在使用数据包的HashMap,但这是在PC上,而不是在iPhone上。 我不知道性能是否足够,在这种情况下,另一个结构可能会更好。

    同样在我们的例子中,我们已经决定了一套专门的渲染器。 例如,如果这个实体拥有一个无效的盾牌数据,ShieldRenderer会显示这个表示…在你的情况下,坦克可以拥有两个连接到两个(初始化定义的)数据的渲染器:

     Renderer renderer1 = new RotatedImage("Tank.png", "TankRotation"); Renderer enderer2 = new RotatedImage("Turret.png", "TurretRotation"); 

    与“TankRotation”和“TurretRotation”所设定的行为。 渲染器只是在显示图像之前旋转图像。

      image.rotate (entity.databag.getData(variable)); 

    希望这个帮助

    问候
    纪尧姆

    你的devise与我看起来不错。 组件的这一章可能会帮助你。