Libgdx Box2D 像素到米的转换?
在尝试使用 Box2D 编写游戏时,我遇到了 Box2D 的问题.我为纹理和精灵的长度填充了像素数,以在其周围创建一个框.一切都在正确的地方,但出于某种原因,一切都进展得很慢.通过查看互联网,我发现如果您不将像素转换为米,box2d 可能会将形状处理为非常大的对象.这似乎是一切进展缓慢的合乎逻辑的原因.
When trying to program a game using Box2D, I ran into a problem with Box2D. I filled in pixel numbers for the lengths of the the textures and sprites to create a box around it. Everything was at the right place, but for some reason everything went very slowly. By looking on the internet I found out that if you didn't convert pixels to meters box2d might handle shapes as very large objects. this seemed to be a logical cause of everything moving slowly.
我在这个网站上发现了类似的问题,但答案似乎并没有帮助.在大多数情况下,解决方案是制定使用比例因子将像素数转换为米的方法.我试过了,但是所有东西都放错了位置并且尺寸不对.这对我来说似乎是合乎逻辑的,因为数字发生了变化但具有相同的含义.
I found similar questions on this site, but the answers didn't really seem to help out. in most of the cases the solution was to make methods to convert the pixel numbers to meters using a scaling factor. I tried this out, but everything got misplaced and had wrong sizes. this seemed logical to me since the numbers where changed but had the same meaning.
我想知道是否有办法使像素意味着更少的米,所以所有东西都应该在同一个地方以相同的(像素)大小,但意味着更少的米.如果您有其他您认为可能会有所帮助的方式,我也很想听听.
I was wondering if there is a way to make the pixels mean less meters, so everything whould be at the same place with the same (pixel) size, but mean less meters. If you have a different way which you think might help, I whould also like to hear it..
这是我用来创建相机的代码
Here is the code i use to create the camera
width = Gdx.graphics.getWidth() / 5;
height = Gdx.graphics.getHeight() / 5;
camera = new OrthographicCamera(width, height);
camera.setToOrtho(false, 1628, 440);
camera.update();
这是我用来创建对象的方法:
This is the method I use to create an object:
public void Create(float X, float Y, float Width, float Height, float density, float friction, float restitution, World world){
//Method to create an item
width = Width;
height = Height;
polygonDef = new BodyDef();
polygonDef.type = BodyType.DynamicBody;
polygonDef.position.set(X + (Width / 2f), Y + (Height / 2f));
polygonBody = world.createBody(polygonDef);
polygonShape = new PolygonShape();
polygonShape.setAsBox(Width / 2f, Height / 2f);
polygonFixture = new FixtureDef();
polygonFixture.shape = polygonShape;
polygonFixture.density = density;
polygonFixture.friction = friction;
polygonFixture.restitution = restitution;
polygonBody.createFixture(polygonFixture);
}
要创建一个项目,在本例中是一个表格,我使用以下内容:
To create an item, in this case a table, I use the following:
Table = new Item();
Table.Create(372f, 60f, 152f, 96f, 1.0f, 0.2f, 0.2f, world);
使用以下方法在项目上绘制 Sprite:
The Sprites are drawn on the item by using the following method:
public void drawSprite(Sprite sprite){
polygonBody.setUserData(sprite);
Utils.batch.begin();
if(polygonBody.getUserData() instanceof Sprite){
Sprite Sprite = (Sprite) polygonBody.getUserData();
Sprite.setPosition(polygonBody.getPosition().x - Sprite.getWidth() / 2, polygonBody.getPosition().y - Sprite.getHeight() / 2);
Sprite.setRotation(polygonBody.getAngle() * MathUtils.radiansToDegrees);
Sprite.draw(Utils.batch);
}
Utils.batch.end();
}
精灵也有像素大小.
使用这种方法,它会在正确的位置显示图像,但一切都移动得很慢.我想知道如何或是否必须更改它以使对象正确移动和/或减少.提前致谢.
推荐答案
Box2D 完全独立于您使用的图形库.它没有任何精灵和纹理的概念.您在线阅读的内容是正确的,您必须将像素转换为米,因为 Box2D 使用米(距离的标准单位).
Box2D is an entirely independent of the graphics library that you use. It doesn't have any notion of sprites and textures. What you read online is correct, you'll have to convert pixels to metres, as Box2D works with metres(the standard unit for distance).
例如,如果您绘制了一个大小为 100x100 像素的精灵,那么这就是您希望用户在屏幕上看到的精灵的大小.在现实世界中,对象的大小应该以米为单位,而不是以像素为单位——所以如果你说 1px = 1m,那么这会将精灵映射到一个巨大的 100x100 米对象.在 Box2D 中,大型世界对象会减慢计算速度.因此,您需要做的是将 100 像素映射到较小的米数,例如 1 米 - 因此 100x100px 的精灵将在 Box2D 世界中由 1x1 米对象表示.
For example, if you drew a sprite of size 100x100 pixels, that's the size of the sprite that you want the user to see on the screen. In real world the size of the object should be in metres and not in pixels - so if you say 1px = 1m, then that'll map the sprite to a gigantic 100x100 meter object. In Box2D, large world objects will slow down calculations. So what you need to do is map the 100 pixels to a smaller number of meters, say, 1 meter - thus 100x100px sprite will be represented in Box2D world by a 1x1 meter object.
Box2D 不适用于非常小的数字和非常大的数字.因此,请将其保持在 0.5 到 100 之间,以获得良好的性能.
Box2D doesn't work well with very small numbers and very large numbers. So keep it in between, say between 0.5 and 100, to have good performance.
行.现在我明白你的问题了.不要编码到像素.就这么简单.我知道这需要一些时间才能理解(这对我来说).但是一旦你掌握了它的窍门,它就直截了当.而不是像素,使用一个单位,比如说,你称之为米.所以我们决定我们的视口应该是 6mx5m.
Ok. Now I get your question. Don't code to pixels. Its as simple as that. I know it'll take some time to understand this(it took for me). But once you get the hang of it, its straight forward. Instead of pixels, use a unit, say, you call it meter. So we decide our viewport should be say 6mx5m.
所以初始化是
Constants.VIEWPORT_WIDTH = 6;
Constants.VIEWPORT_HEIGHT = 5;
...
void init() {
camera = new OrthographicCamera(Constants.VIEWPORT_WIDTH, Constants.VIEWPORT_HEIGHT);
camera.position.set(Constants.VIEWPORT_WIDTH/2, Constants.VIEWPORT_HEIGHT/2, 0);
camera.update();
}
一旦知道了实际的宽度和高度,就可以调用以下函数来保持纵横比:
Once you know the actual width and height, you call the following function in order to maintain aspect ratio:
public void resize(int width, int height) {
camera.viewportHeight = (Constants.VIEWPORT_WIDTH / width) * height;
camera.update();
}
resize()
可以在您更改屏幕大小的任何时候调用(例如:当您更改屏幕方向时).resize()
取实际的宽度和高度(320x480 等),即像素值.
resize()
can be called anytime you change your screen size(eg: when you screen orientation changes). resize()
takes the actual width and height (320x480 etc), which is the pixel value.
现在您可以在这个 6x5 大小的新世界中指定精灵的大小、位置等.你可以忘记像素.填充屏幕的精灵的最小尺寸为 6x5.
Now you specify you sprite sizes, their positions etc. in this new world of size 6x5. You can forget pixels. The minimum size of the sprite that'll fill the screen will be 6x5.
您现在可以使用与 Box2D 相同的单位.由于新的尺寸会更小,这对 Box2D 来说不是问题.如果我没记错的话,Box2D 没有任何单位.为方便起见,我们将其称为仪表.
You can now use the same unit with Box2D. Since the new dimensions will be smaller, it won't be a problem for Box2D. If I remember correctly Box2D doesn't have any unit. We just call it meter for convenience sake.
现在您可能会问在哪里指定窗口的尺寸.这取决于平台.以下代码显示了一个 320x480 窗口桌面游戏:
Now you might ask where you specify the dimensions of the window. It depends on the platform. Following code shows a 320x480 windowed desktop game:
public class Main {
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "my-game";
cfg.useGL20 = false;
cfg.width = 480;
cfg.height = 320;
new LwjglApplication(new MyGame(), cfg);
}
}
我们的相机会智能地将 6x5 视口映射到 480x320.
Our camera will intelligently map the 6x5 viewport to 480x320.
相关文章