【问题标题】:Slick2D and JBox2D. How to drawSlick2D 和 JBox2D。如何绘制
【发布时间】:2012-04-03 15:56:13
【问题描述】:

在问这个之前,我在网上做了很多搜索。我就是做不到。我有点难以理解。那么我如何在正确的屏幕位置绘制图像,对应于世界位置的身体?谢谢。

如果其他人在同一障碍物前发现他自己,我发布了一个 HOW TO,感谢 normalocity 的良好解释。你可以在这里找到它:http://romeo.akademx.ro/2012/04/06/slick-and-box2d/

这是渲染函数:

public void render(GameContainer container, StateBasedGame game, Graphics g)
        throws SlickException {
    g.setBackground(Color.white);

    g.pushTransform();
    g.translate(worldToScreen(body.getPosition()).x, worldToScreen(body.getPosition()).y);
    g.rotate(15, 15, (float) Math.toDegrees(body.getAngle()));
    part.draw();
    g.popTransform();

    g.drawString("Count: " + cont, 5, 40);
    //world.drawDebugData();
}

这些是我用来转换世界屏幕坐标的函数:

public Vec2 screenToWorld(Vec2 screenV) {
    return new Vec2((screenV.x - offset.x) / scaleFactor, yFlip
            * (screenV.y - offset.y) / scaleFactor);
}

public Vec2 worldToScreen(Vec2 worldV) {
    return new Vec2(worldV.x * scaleFactor + offset.x, yFlip * worldV.y
            * scaleFactor + offset.y);
}

我也碰巧使用了在这个链接上找到的 SlickDebugDraw:http://slick.javaunlimited.net/viewtopic.php?f=19&t=3610&sid=69614ac53aaf5724b808b75173e8e48e

但他的 DebugDraw 绘制的完全是另一回事,然后是我的渲染函数。我有点困惑。

【问题讨论】:

  • 您能否向我们发布一些您遇到问题的代码?这将有助于我们回答您的问题。
  • 来吧,没人知道吗?我非常需要这个,所以我可以继续我的项目。

标签: java physics-engine slick2d jbox2d


【解决方案1】:

如果您所做的只是在 2D 世界中绘制精灵,那么您基本上需要跟踪两件事,以便决定在屏幕上绘制哪些精灵以及在屏幕上的哪个位置绘制它们。您必须将您的 sprite 视为存在于世界上的某个位置,而您在屏幕上看到的只是世界的一种视图,专注于一个区域。

您需要跟踪的两件事是:

  1. 每个精灵都需要在世界中拥有自己的位置
  2. 您的“相机”需要跟踪其相对于世界的位置。

所以,假设你有一个很大很大的世界,2D 坐标 (x, y) 空间为 1,000,000 x 1,000,000 像素(我在这里使用像素作为度量单位,但这是一个任意选择,并且世界的大小无所谓,我只是选择了一个大的)。然后,假设您有一个指向那个世界的“相机”,并且该相机的视图就是您屏幕上显示的内容。相机为您提供的显示尺寸为 1024x768 像素。

假设您使用箭头键在世界各地移动相机。

因此,您的世界坐标空间会这样映射到您的屏幕:

(0, 0)        +x
      +------------------>
      |
   +y |
      |      *  <= example sprite in your world @ coordinates (x=200, y=200)
      |
     \ /

当您的精灵“向右”移动时,它们会增加x 坐标。当他们向“左”移动时,他们会减少他们的x 坐标。当“向上”移动时,它们减小他们的y 坐标(因为y 在监视器上向下增加),并且当“向下”移动时,精灵增加他们的@987654333 @坐标。

现在,您在我们的屏幕上看到的只是相机对世界的看法。所以,让我们将相机的左上角设置为(x=500, y=500)。这看起来像:

(0, 0)        +x
      +---------------------------------->
      |
   +y |
      |      *  <= example sprite in your world @ coordinates (x=200, y=200)
      |
      |
      |         +===================+
      |         |     the area      |
      |         |  that the camera  |
      |         |    "sees" and     |
      |         |   shows on your   |
      |         |       screen      |
      |         +===================+
     \ /

使用该设置,假设相机位于 (500, 500)(即相机视图的左上角,如本例所示,位于世界坐标 (500, 500))。由于相机显示的区域大小为 1024x768,因此对面的右下角为 (500+1024, 500+768) = (x=1524, y=1268)

请注意,我们世界中的精灵不在相机的视野范围内。这意味着,当我们在屏幕上渲染相机的视图时,我们不会看到精灵。

如果相反,相机移动到 (200, 200),那么相机的视野区域将覆盖从左上角 @ (200, 200) 到右下角 @ (1224, 968) 的世界坐标,看起来像这样:

(0, 0)        +x
      +---------------------------------->
      |   
   +y |  +===================+
      |  |                   |
      |  |   * <= sprite     |
      |  |                   |
      |  |                   | <= camera's view of the world
      |  +===================+
      |
      |
      |
      |
     \ /

当相机在这个位置时,精灵是可见的。如果精灵是@(500, 500),并且相机在(200, 200),那么当我们在屏幕上绘制精灵时,精灵会出现在我们的屏幕坐标300 , 300.

为什么?

因为,这确实是您问题的答案,哪里您在屏幕上绘制的东西是精灵的世界位置(500、500),减去相机的位置 (200, 200),等于 (300, 300)。

所以,回顾一下:

您使用箭头键(或鼠标,或您想要的任何其他控制方案)在世界各地移动相机的位置,并通过获取精灵的位置和 来渲染相对于相机位置的精灵位置减去相机的位置,得到的是屏幕坐标应该出现的精灵。

但还有一件事......

绘制世界上的每一个精灵确实效率低下。您只需要绘制相机视图内的精灵,否则您将绘制在屏幕上看不到的东西,因此会浪费渲染/CPU/GPU 时间。

因此,当您渲染相机的视图时,您需要遍历您的精灵,检查它们是否“在相机上”(即,它们是否在相机的视图内),并且仅当它们在此视图内时才绘制它们。

为此,您必须获取相机的尺寸(在我们的示例中为 1024x768),并检查精灵的位置是否在相机视图的矩形内 -即相机左上角的位置,加上相机的宽度和高度。

所以,如果我们的相机向我们展示了一个大小为 1024x768 像素的视图,并且它的左上角位于 (200, 200),那么该视图矩形为:

(200, 200)                      (1224, 200)
           +===================+
           |                   |
           |    *              |
           |                   |
           |                   |
           +===================+
(200, 968)                      (1224, 968)

在这种情况下,精灵的位置 @ (500, 500) 在相机的视野内。

如果您需要更多示例,我有一个有效的 Slick2D 技术演示,名为 Pedestrians,其中包含您可以查看的代码。有关我如何计算应该渲染的世界面积的详细信息,请查看this file 中的render 方法,并特别注意startXstartYstopXstopY 变量,这对我来说控制了我要绘制的精灵区域。还应该注意的是,我的精灵(或“行人”)存在于TileMap 上,因此它们的大小不是 1 像素——它们有自己的宽度和高度。这为如何决定绘制什么增加了一点复杂性,但它基本上归结为“绘制相机视野内的东西,加上边缘周围的一些额外内容。”

在您自己的机器上克隆 Pedeestrians 存储库,通过将与任何其他 Slick2D 项目相同的依赖项添加到项目中来使其工作,并播放/修改渲染代码,直到您了解发生了什么。只有通过实践和学习,您才能了解其工作原理的所有细节。好消息是,一旦您弄清楚如何使用这种基本的 2D 世界与相机方法进行渲染,您就会非常了解如何为所有 2D 应用程序渲染图形,因为这些概念适用于所有语言。

我还有各种行人在my YouTube channel 上运行的视频(最相关的视频可能是this one,它显示了我的基本行人正在渲染,并且摄像机四处移动),所以你可以看到这一切的样子就像不必先构建项目一样。

【讨论】:

  • 我在 SO 上读到的最好的、信息量更大的答案之一。很棒的帖子。
  • 你刚刚成为我的偶像。我现在非常爱你。我明白这一切。非常感谢。从现在开始,我是你最大的粉丝。再次感谢!
  • 不客气。仅供参考,还有 gamedev.stackexchange.com - 这是另一个 StackExchange 站点,但致力于游戏开发。尽管我一直关注此站点上的 slick2d 标签,但当您在处理项目时询问更多游戏开发特定问题时,gamedev 站点可能被证明是尝试让他们回答的好地方。
  • @Growler - 您所描述的是相机视图的绘制位置 - 而不是相机。相机只是一个带有(x,y)(width,height) 的矩形区域。这定义了相机“看到”世界的窗口,其尺寸往往反映屏幕的分辨率。旁注:JPanel 是一个 Swing 组件,您不需要(也不想)通过 Swing 进行游戏。 Slick 提供了渲染和输入捕获所需的一切。见:Abandon all hope, ye who enter through Swing to create games!
  • @Growler - 最后一点,Slick2D 作为一个项目已被放弃,我在网上看到的人推荐 libGDX 作为替代品。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多