Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 面向对象的游戏设计_Java_Oop_Java 2d - Fatal编程技术网

Java 面向对象的游戏设计

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); 当指示实体更新自身时,它将根据应用于它的当前

我正在设计一个简单的游戏,它使用Java2D和牛顿物理学。目前,我的主要“游戏循环”看起来像:

do {
  for (GameEntity entity : entities) {
    entity.update(gameContext);
  }

  for (Drawable drawable : drawables) {
    drawable.draw(graphics2d);
  }
} while (gameRunning);
当指示实体更新自身时,它将根据应用于它的当前力调整其速度和位置。然而,我需要实体展示其他行为;e、 如果一个“坏家伙”被玩家射杀,该实体应该被销毁并从游戏世界中移除

我的问题:以面向对象的方式实现这一点的最佳方式是什么?到目前为止,我看到的所有示例都将游戏循环合并到一个名为“
game
”的God类中,该类执行以下步骤:检测碰撞、检查坏人是否被杀、检查玩家是否被杀、重新绘制等,并封装所有游戏状态(剩余生命等)。换句话说,它是非常程序化的所有逻辑都在游戏类中。有谁能推荐一个更好的方法吗

到目前为止,我想到了以下几种选择:

  • GameContext
    传递给每个实体,如果需要,该实体可以从中删除自身或更新游戏状态(例如,如果玩家被杀,则为“未运行”)
  • 注册每个
    GameEntity
    作为中心
    Game
    类的侦听器,并采取面向事件的方法;e、 g.碰撞将导致向碰撞中的两个参与者触发
    碰撞事件
    
在我所研究的一个特定引擎中,我们将逻辑与图形表示分离,然后使用对象发送消息以实现他们想要做的事情。我们这样做是为了让游戏存在于本地机器或网络上,并且从代码的角度来看,它们彼此无法区分。(命令模式)

我们还在一个单独的对象中进行了实际的物理建模,该对象可以在运行中进行更改。这让我们很容易搞砸重力等等

我们大量使用事件驱动代码(侦听器模式)和大量计时器

例如,我们有一个可相交对象的基类,可以监听碰撞事件。我们将其细分为一个健康箱。在碰撞时,如果它被玩家实体击中,它会向碰撞器发送一个命令,指示它应该获得健康状态,发送一条消息向所有能听到声音的人广播声音,停用碰撞,激活动画以从场景图中删除图形,并设置一个计时器以稍后重新实例化自身。听起来很复杂,但事实并非如此


如果我记得(已经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对应的组件(如果存在)

  • 如果组件需要更新,它将由服务或系统对象调用。每个服务都直接从游戏循环中更新。或者,您可以从调度程序对象调用服务,该调度程序对象根据依赖关系图确定更新顺序

以下是这种方法的优点:

  • 您可以自由组合功能 没有为每个人编写新的类 组合或使用复杂继承 树木

  • 几乎没有什么功能可以 你可以