java Slick2D 和 JBox2D。如何绘制
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9997006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Slick2D and JBox2D. How to draw
提问by Romeo
Before asking this i did A LOT of searching on the net. I just can't do it. It's a little hard for me to understand. So how do i draw the images at the right screen positions coresponding to bodies in world position? Thanx.
在问这个之前,我在网上做了很多搜索。我就是做不到。我有点难以理解。那么我如何在正确的屏幕位置绘制图像,对应于世界位置的身体?谢谢。
If anyone else finds himslef in front of the same obstacle i posted a HOW TO, thanx to normalocity's good explanation. You can find it here: http://romeo.akademx.ro/2012/04/06/slick-and-box2d/
如果其他人在相同的障碍前发现他自己,我发布了一个 HOW TO,感谢 normalocity 的良好解释。你可以在这里找到它:http: //romeo.akademx.ro/2012/04/06/slick-and-box2d/
This is the render function:
这是渲染函数:
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();
}
And these are the function i use to transform world-screen coordinations:
这些是我用来转换世界屏幕坐标的函数:
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);
}
I also happen to use the SlickDebugDraw found at this link: http://slick.javaunlimited.net/viewtopic.php?f=19&t=3610&sid=69614ac53aaf5724b808b75173e8e48e
我也碰巧使用了在此链接中找到的 SlickDebugDraw:http://slick.javaunlimited.net/viewtopic.php?f=19&t=3610&sid=69614ac53aaf5724b808b75173e8e48e
But his DebugDraw draws a completely another thing then my render function. I'm a bit confused.
但是他的 DebugDraw 绘制了完全不同的东西,然后我的渲染函数。我有点困惑。
回答by jefflunt
If all you're doing is drawing sprites in a 2D world, then there's basically two things you need to keep track of in order to decide which sprites to draw on the screen and where on the screen to draw them. You have to think of your sprites as existing at a certain location in the world, and what you see on the screen as just one view of the world, focusing on an area.
如果您所做的只是在 2D 世界中绘制精灵,那么基本上有两件事您需要跟踪以决定在屏幕上绘制哪些精灵以及在屏幕上的哪个位置绘制它们。您必须将您的精灵视为存在于世界上的某个位置,而您在屏幕上看到的只是世界的一种视图,专注于一个区域。
The two things you need to keep track of are:
您需要跟踪的两件事是:
- Each sprite needs to have its location within the world
- Your "camera" needs to track its location relative to the world.
- 每个精灵都需要在世界中拥有自己的位置
- 您的“相机”需要跟踪其相对于世界的位置。
So, let's say you have a big, big world, with a 2D coordinate (x, y) space of 1,000,000 x 1,000,000 pixels (I'm using pixels as the unit of measure here, but that's an arbitrary choice, and the size of the world doesn't matter, I've just chosen a big one). Then, let's say you have a "camera" that's pointed at that world, and the view of that camera is what is displayed on your screen. The display that camera gives you is 1024x768 pixels in size.
因此,假设您有一个很大很大的世界,其 2D 坐标 (x, y) 空间为 1,000,000 x 1,000,000 像素(我在这里使用像素作为度量单位,但这是一个任意选择,并且世界无所谓,我只是选择了一个大的)。然后,假设您有一个指向那个世界的“相机”,该相机的视图就是您屏幕上显示的内容。相机为您提供的显示尺寸为 1024x768 像素。
Let's also say that you use the arrow keys to move that camera around the world.
假设您使用箭头键在世界范围内移动该相机。
So, your world's coordinate space maps to your screen as such:
因此,您的世界坐标空间映射到您的屏幕,如下所示:
(0, 0) +x
+------------------>
|
+y |
| * <= example sprite in your world @ coordinates (x=200, y=200)
|
\ /
When your sprites move "right" they increase their x
coordinate. When they move "left" they decrease their x
coordinate. When moving "up" they decreasetheir y
coordinate (because y
increases downward, on monitor displays), and when moving "down" sprites increasetheir y
coordinate.
当您的精灵“向右”移动时,它们会增加它们的x
坐标。当他们“向左”移动时,他们会减少他们的x
坐标。当移动“起来”,他们减少他们的y
坐标(因为y
向下增加,对显示器显示),和移动时,“向下”精灵提高他们的y
协调。
Now, again, what you see in our screen is just the camera's view of the world. So, let's set that the camera's upper-left corner is at (x=500, y=500)
. That would look something like:
现在,您在我们的屏幕上看到的只是相机对世界的看法。因此,让我们将相机的左上角设置为(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 |
| +===================+
\ /
With that setup, let's say that the camera is at (500, 500) (that is, the upper-left corner of the camera's view, as shown in this example, is at the world coordinates (500, 500). And because the camera shows you an area that is 1024x768 is size, then the opposite, lower-right corner is (500+1024, 500+768) = (x=1524, y=1268)
.
有了这个设置,假设相机位于 (500, 500)(即,相机视图的左上角,如本例所示,位于世界坐标 (500, 500) 处。并且因为相机向您显示一个 1024x768 大小的区域,然后右下角是 (500+1024, 500+768) = (x=1524, y=1268)
。
Note that the sprite in our world is notinside that camera's view area. That means, when we render the camera's view on the screen, we won't see the sprite.
请注意,我们世界中的精灵不在该相机的视野范围内。这意味着,当我们在屏幕上渲染相机的视图时,我们不会看到精灵。
If, instead, the camera moved to (200, 200), then the view area of the camera would cover the world coordinates from upper-left @ (200, 200) to lower-right @ (1224, 968), and look something like this:
相反,如果相机移动到 (200, 200),那么相机的视图区域将覆盖从左上角@(200, 200) 到右下角@(1224, 968) 的世界坐标,并且看起来有些东西像这样:
(0, 0) +x
+---------------------------------->
|
+y | +===================+
| | |
| | * <= sprite |
| | |
| | | <= camera's view of the world
| +===================+
|
|
|
|
\ /
When the camera is in this position, the sprite is visible. If the sprite is @ (500, 500), and the camera is at (200, 200), then when we draw the sprite on the screen, the sprite will appear, on our screenat coordinates 300, 300.
当相机处于这个位置时,精灵是可见的。如果精灵是@(500, 500),相机在(200, 200),那么当我们在屏幕上绘制精灵时,精灵就会出现在我们的屏幕坐标300, 300处。
Why?
为什么?
Because, and this is really the answer to your question, whereyou draw things on the screen is sprite's world location(500, 500), minus the camera's location(200, 200), which equals (300, 300).
因为,这是真正的回答你的问题,在那里你在屏幕上画一些东西是精灵的世界位置(500,500),减去相机的位置(200,200),它等于(300,300)。
So, to review:
因此,要:
You move the camera's position around the world using the arrow keys (or the mouse, or whatever other control scheme you want), and you render the sprites location relative to the camera position, by taking the sprite's position and subtractingthe camera's position, and what you get are the screen coordinateswhere the sprite should appear.
您可以使用箭头键(或鼠标,或您想要的任何其他控制方案)在世界各地移动相机的位置,并通过获取精灵的位置并减去相机的位置来渲染相对于相机位置的精灵位置,以及你得到的是精灵应该出现的屏幕坐标。
But there's one more thing...
但还有一件事......
It's really inefficient to draw every sprite in the world. You only need to draw the sprites that are within the camera's view, otherwise you're drawing things that you won't see on your screen, and therefore, wasting rendering/CPU/GPU time.
绘制世界上的每个精灵实在是太低效了。您只需要绘制相机视图内的精灵,否则您将绘制在屏幕上看不到的东西,因此会浪费渲染/CPU/GPU 时间。
So, when you're rendering the camera's view, you need to iterate through your sprites, checking to see if they are "on camera" (that is, whether or not they're within the view of the camera), and only drawing them if they are within this view.
所以,当你渲染相机的视图时,你需要遍历你的精灵,检查它们是否“在相机上”(即,它们是否在相机的视图内),并且只绘制如果他们在这个视图内。
In order to do that, you have to take the dimensionsof your camera (1024x768, in our example), and check to see if the sprite's position is inside the rectangle of the camera's view - which is the position of the camera's upper-left corner, plus the camera's width and height.
为此,您必须获取相机的尺寸(在我们的示例中为 1024x768),并检查精灵的位置是否在相机视图的矩形内 - 这是相机左上角的位置角,加上相机的宽度和高度。
So, if our camera shows us a view that's 1024x768 pixels in size, and it's upper-left corner is at (200, 200), then the view rectangle is:
所以,如果我们的相机向我们展示了一个大小为 1024x768 像素的视图,并且它的左上角在 (200, 200),那么视图矩形是:
(200, 200) (1224, 200)
+===================+
| |
| * |
| |
| |
+===================+
(200, 968) (1224, 968)
The sprite's position @ (500, 500) is within the camera's view, in this case.
在这种情况下,精灵的位置@(500, 500) 在相机的视野内。
If you need more examples, I have a working Slick2D tech demo, called Pedestrians, that has code you can look at. For details on how I calculate the area of the world that should be rendered, look at the render
method inside this file, and pay special attention to the startX
, startY
, stopX
, stopY
variables, which for me control the area of sprites I'm going to draw. It should also be noted that my sprites (or "pedestrians") exist on a TileMap
, so they aren't 1 pixel is size - they have a width and height of their own. This adds a small bit of complexity to how to decide what to draw, but it basically comes down to, "draw what's within the camera's view, plus a little extra around the edges."
如果您需要更多示例,我有一个名为Pedestrians的工作 Slick2D 技术演示,其中包含您可以查看的代码。有关如何计算应渲染的世界面积的详细信息,请查看此文件中的render
方法,并特别注意, , ,变量,它们对我来说控制着我将要绘制的精灵区域。还应该注意的是,我的精灵(或“行人”)存在于 上,因此它们的大小不是 1 像素——它们有自己的宽度和高度。这给如何决定要绘制的内容增加了一点复杂性,但基本上归结为“绘制相机视图内的内容,并在边缘周围添加一些额外的内容”。startX
startY
stopX
stopY
TileMap
Clone the Pedeestrians repository on your own machine, get it working by adding the same dependencies to the project as any other Slick2D project, and play/modify the rendering code until you understand what's going on. Only through practice and study will you get all the little ins/outs of how this works. The good news is that once you figure out how to do rendering with this basic 2D world vs. camera method, you'll pretty much know how to render graphics for all 2D apps, because the concepts translate to all languages.
在您自己的机器上克隆 Pedeestrians 存储库,通过向项目添加与任何其他 Slick2D 项目相同的依赖项来使其工作,然后播放/修改渲染代码,直到您了解发生了什么。只有通过实践和学习,您才能了解其运作方式的所有细节。好消息是,一旦您弄清楚如何使用这种基本的 2D 世界与相机方法进行渲染,您将几乎知道如何为所有 2D 应用程序渲染图形,因为这些概念可以转换为所有语言。
I also have various videos of Pedestrians being run on my YouTube channel(the most relevant video is probably this one, which shows my basic pedestrians being rendered, and the camera moving around), so you can see what this all looks like without having to build the project first.
我的YouTube 频道上还有各种关于行人的视频(最相关的视频可能是这个视频,它显示了我的基本行人被渲染,以及相机四处移动),因此您无需观看就可以看到这一切首先构建项目。