Java 面向对象的游戏设计
我正在设计一个简单的游戏,它使用Java2D和牛顿物理学。目前,我的主要“游戏循环”看起来像:Java 面向对象的游戏设计,java,oop,java-2d,Java,Oop,Java 2d,我正在设计一个简单的游戏,它使用Java2D和牛顿物理学。目前,我的主要“游戏循环”看起来像: do { for (GameEntity entity : entities) { entity.update(gameContext); } for (Drawable drawable : drawables) { drawable.draw(graphics2d); } } while (gameRunning); 当指示实体更新自身时,它将根据应用于它的当前
do {
for (GameEntity entity : entities) {
entity.update(gameContext);
}
for (Drawable drawable : drawables) {
drawable.draw(graphics2d);
}
} while (gameRunning);
当指示实体更新自身时,它将根据应用于它的当前力调整其速度和位置。然而,我需要实体展示其他行为;e、 如果一个“坏家伙”被玩家射杀,该实体应该被销毁并从游戏世界中移除
我的问题:以面向对象的方式实现这一点的最佳方式是什么?到目前为止,我看到的所有示例都将游戏循环合并到一个名为“game
”的God类中,该类执行以下步骤:检测碰撞、检查坏人是否被杀、检查玩家是否被杀、重新绘制等,并封装所有游戏状态(剩余生命等)。换句话说,它是非常程序化的和所有逻辑都在游戏类中。有谁能推荐一个更好的方法吗
到目前为止,我想到了以下几种选择:
- 将
传递给每个实体,如果需要,该实体可以从中删除自身或更新游戏状态(例如,如果玩家被杀,则为“未运行”)GameContext
- 注册每个
作为中心GameEntity
类的侦听器,并采取面向事件的方法;e、 g.碰撞将导致向碰撞中的两个参与者触发Game
碰撞事件李>
如果我记得(已经12年了),我们对场景有一个抽象的概念,所以游戏就是一系列场景。当一个场景结束时,会触发一个事件,该事件通常会发送一个命令,取下当前场景并开始另一个场景。我不同意,因为您有一个主游戏类,所有逻辑都必须在该类中发生 这里过于简化,模仿你的例子只是为了说明我的观点:
mainloop:
moveEntities()
resolveCollisions() [objects may "disappear"/explode here]
drawEntities() [drawing before or after cleanEntitites() ain't an issue, a dead entity won't draw itself]
cleanDeadEntities()
现在您有了一个气泡类:
Bubble implements Drawable {
handle( Needle needle ) {
if ( needle collide with us ) {
exploded = true;
}
}
draw (...) {
if (!exploded) {
draw();
}
}
}
因此,当然,有一个主循环负责在实体之间传递消息,但是与气泡和针之间的碰撞相关的逻辑肯定不在主游戏类中
我很确定,即使在你的例子中,所有与运动相关的逻辑都不会发生在主类中
所以我不同意你的说法,你用粗体写的,“所有的逻辑都发生在主类中”
这根本不正确
至于好的设计:如果你可以很容易地提供游戏的另一个“视图”(比如说,一张迷你地图),如果你可以很容易地编写一个“帧对帧完美重放器”,那么你的设计可能没有那么糟糕(也就是说:通过只记录输入和发生的时间,你应该能够完全按照玩过的方式重新创建游戏。这就是《帝国时代》、《魔兽争霸3》等游戏的重播方式:只记录用户输入和发生的时间[这也是重播文件通常如此之小的原因]).这是一个将模型和视图分开的实验。它使用观察者模式通知视图游戏状态的变化,但事件可能会提供更丰富的上下文。最初,模型是由键盘输入驱动的,但分开后可以很容易地添加计时器驱动的动画
附录:你需要保持游戏模型的独立性,但你可以根据需要将该模型重新划分为多个类。我编写了自己的引擎(原始和肮脏),但有一个不错的OO模型的预构建引擎是。我建议看一看(它的对象模型/API).节点分配有点古怪,但你越看它就越有意义。它也有大量的工作游戏示例,文档记录得非常好
我自己也从中学到了一些技巧。我与两个商业游戏引擎密切合作,它们遵循类似的模式:
- 对象表示游戏实体的组件或方面(如物理、可渲染等),而不是整个实体。对于每种类型的组件,都有一个巨大的组件列表,每个包含该组件的实体实例都有一个组件列表
- “游戏实体”类型本身只是一个唯一的ID。每个巨大的组件列表都有一个映射,用于查找与实体ID对应的组件(如果存在)
- 如果组件需要更新,它将由服务或系统对象调用。每个服务都直接从游戏循环中更新。或者,您可以从调度程序对象调用服务,该调度程序对象根据依赖关系图确定更新顺序
- 您可以自由组合功能 没有为每个人编写新的类 组合或使用复杂继承 树木
- 几乎没有什么功能可以 你可以