java - Slick2D 和 JBox2D。如何绘制

标签 java physics-engine slick2d jbox2d

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

如果其他人在相同的障碍前发现他自己,我发布了一个 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 绘制了完全不同的东西,然后我的渲染函数。我有点困惑。

最佳答案

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

您需要跟踪的两件事是:

  • 每个 Sprite 都需要在世界中拥有自己的位置
  • 您的“相机”需要跟踪其相对于世界的位置。

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

    假设您使用箭头键在世界范围内移动该相机。

    因此,您的世界坐标空间映射到您的屏幕如下:
    (0, 0)        +x
          +------------------>
          |
       +y |
          |      *  <= example sprite in your world @ coordinates (x=200, y=200)
          |
         \ /
    

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

    现在,您在我们的屏幕上看到的只是相机对世界的看法。所以,让我们设置相机的左上角在 (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)(即相机 View 的左上角,如本例所示,位于世界坐标 (500, 500) 处)。并且因为相机向您显示一个 1024x768 大小的区域,然后右下角是 (500+1024, 500+768) = (x=1524, y=1268)

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

    相反,如果相机移动到 (200, 200),那么相机的 View 区域将覆盖从左上角@(200, 200) 到右下角@(1224, 968) 的世界坐标,并且看起来有些东西像这样:
    (0, 0)        +x
          +---------------------------------->
          |   
       +y |  +===================+
          |  |                   |
          |  |   * <= sprite     |
          |  |                   |
          |  |                   | <= camera's view of the world
          |  +===================+
          |
          |
          |
          |
         \ /
    

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

    为什么?

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

    因此,要审查:

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

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

    绘制世界上的每一个 Sprite 实在是太低效了。您只需要绘制相机 View 内的 Sprite ,否则您将绘制在屏幕上看不到的东西,因此会浪费渲染/CPU/GPU 时间。

    所以,当你渲染相机的 View 时,你需要遍历你的 Sprite ,检查它们是否“在相机上”(即,它们是否在相机的 View 内),并且只绘制如果他们在这个 View 中。

    为此,您必须使用 尺寸 相机(在我们的示例中为 1024x768),并检查 Sprite 的位置是否在相机 View 的矩形内 - 这是相机左上角的位置,加上相机的宽度和高度。

    所以,如果我们的相机向我们展示了一个大小为 1024x768 像素的 View ,并且它的左上角在 (200, 200),那么 View 矩形是:
    (200, 200)                      (1224, 200)
               +===================+
               |                   |
               |    *              |
               |                   |
               |                   |
               +===================+
    (200, 968)                      (1224, 968)
    

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

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

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

    我还有各种关于行人运行的视频 my YouTube channel (最相关的视频可能是 this one ,它显示了我的基本行人被渲染,以及相机四处移动),因此您无需先构建项目即可看到这一切。

    关于java - Slick2D 和 JBox2D。如何绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9997006/

    相关文章:

    java - 防止命令提示符窗口打开以启动应用程序

    java - 播放多个视频JavaFx

    javascript - angularJS中的WebGL ThreeJS和PhysiJS无法启动物理?

    java - 在当前线程中找不到 OpenGL 上下文,如何修复此错误?

    java - 我如何在 Slick2D/LWJGL 或一般游戏编程中使用 "delta"?

    java - java中如何将一个元素移动到已排序数组的底部?

    java - 同步j进度条

    Java - 如何检查字符串中下一个即将出现的空格? (对于 IRC 机器人)

    c++ - 如何使用 Bullet Physics 制作 Spring 约束?

    swift - (Sugar, Sugar 等游戏的物理引擎)SpriteKit 对许多物理 Sprite 的性能优化