为什么在 LibGDX 中简单地按比例放大并使 Box2D 无法正常工作?
Why doesn't simply scaling things up in LibGDX and Box2D work correctly?
我试图摆脱在使用 Box2D 和 LibGDX.
时必须缩放精灵上的所有坐标的麻烦
以下是我的视口和物理世界的设置:
// Used to create an Extend Viewport
public static final int MIN_WIDTH = 480;
public static final int MIN_HEIGHT = 800;
// Used to scale all sprite's coordinates
public static final float PIXELS_TO_METERS = 100f;
// Used with physics world.
public static final float GRAVITY = -9.8f;
public static final float IMPULSE = 0.15f;
world.setGravity(new Vector2(0f, GRAVITY));
当我对我的角色应用线性脉冲时(当用户点击屏幕时)一切正常:
body.setLinearVelocity(0f, 0f);
body.applyLinearImpulse(0, IMPULSE, body.getPosition().x, body.getPosition().y, true);
body的密度是0f
,但是改成1f
甚至100f
似乎都没有什么实际效果。
这意味着我必须按 PIXELS_TO_METERS
缩放绘制方法中所有精灵的位置。我认为(可能是错误的)我可以简单地将 GRAVITY
和 IMPULSE
缩放 PIXELS_TO_METERS
并使其工作完全相同。似乎并非如此。重力似乎很小,施加冲量几乎没有任何影响。
// Used to scale all sprite's coordinates
public static final float PIXELS_TO_METERS = 1f;
// Used with physics world.
public static final float GRAVITY = -9.8f * 100;
public static final float IMPULSE = 0.15f * 100;
所以:
1) 为什么简单地放大所有值不能使其工作相同?
2) 有更好的方法吗?
看起来您使用一些虚构的像素单位使您的设计过于复杂(我怀疑您指的是实际像素)。我建议您改为使用有意义的单位,例如 meters,并坚持使用。因此,对所有坐标(包括您的虚拟视口)使用米。因此,实际上将您的代码修改为如下所示:
// Used to create an Extend Viewport
public static final float MIN_WIDTH = 4.8f; // at least 4.8 meters in width is visible
public static final float MIN_HEIGHT = 8.0f; // at least 8 meter in height is visible
这完全消除了将仪表缩放到您想象的像素单位的需要。从您的单位(虚拟视口大小)到 screen (values between -1 and +1) is done by the camera 的实际缩放。您不必考虑设计中的缩放单位。
确保删除您的 PIXELS_TO_METERS
常量(不要将其设置为 1f
,它只会使您的代码复杂化而没有任何好处)并确保您没有使用假想像素都在你的代码中。后者包括您创建的所有精灵,但没有明确指定其大小(以米为单位)。
由于正当理由,与 SI 单位相比,"scale" 您的单位(在您的游戏逻辑中)仍然是可能的。例如,在创建 space 游戏时,您可能会发现自己在使用仪表时使用了非常大的数字。通常您希望将值保持在 1f
左右以避免浮点错误。在这种情况下,使用例如十米 (x10)、百米 (x100) 或公里 (x1000)。如果这样做,请确保保持一致。在评论中添加单位可能会有所帮助,这样您就不会忘记正确缩放(例如 GRAVITY = -0.0098f; // kilometer per second per second
)。
我是这样实现的:
// in declaration
float PIXELS_TO_METERS = 32; // in my case: 1m = 32 pixels
Matrix4 projection = new Matrix4();
// in creation
viewport = new FitViewport(
Application.width
, Application.height
, Application.camera);
viewport.apply();
// set vieport dimensions
camera.setToOrtho(false, gameWidth, gameHeight);
// in render
projection.set(batch.getProjectionMatrix());
projection.scl(PIXELS_TO_METERS);
box2dDebugRenderer.render(world, projection);
// in player body creation
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.x = getPosition().x / PIXELS_TO_METERS;
bodyDef.position.y = getPosition().y / PIXELS_TO_METERS;
CircleShape shape = new CircleShape();
shape.setRadius((getBounds().width * 0.5f) / PIXELS_TO_METERS);
// in player update
setPosition(
body.getPosition().x * PIXELS_TO_METERS - playerWidth,
body.getPosition().y * PIXELS_TO_METERS - playerHeight);
因此,要在 box2d 方法中将像素设置为米,您必须将像素位置除以 PIXELS_TO_METERS,并将米设置为玩家位置中的像素,您必须将 box2d 值乘以 PIXELS_TO_METERS。
将您的 PIXELS_TO_METERS 正确设置为您的屏幕中有多少像素与 1 米相匹配。
祝你好运。
我试图摆脱在使用 Box2D 和 LibGDX.
时必须缩放精灵上的所有坐标的麻烦以下是我的视口和物理世界的设置:
// Used to create an Extend Viewport
public static final int MIN_WIDTH = 480;
public static final int MIN_HEIGHT = 800;
// Used to scale all sprite's coordinates
public static final float PIXELS_TO_METERS = 100f;
// Used with physics world.
public static final float GRAVITY = -9.8f;
public static final float IMPULSE = 0.15f;
world.setGravity(new Vector2(0f, GRAVITY));
当我对我的角色应用线性脉冲时(当用户点击屏幕时)一切正常:
body.setLinearVelocity(0f, 0f);
body.applyLinearImpulse(0, IMPULSE, body.getPosition().x, body.getPosition().y, true);
body的密度是0f
,但是改成1f
甚至100f
似乎都没有什么实际效果。
这意味着我必须按 PIXELS_TO_METERS
缩放绘制方法中所有精灵的位置。我认为(可能是错误的)我可以简单地将 GRAVITY
和 IMPULSE
缩放 PIXELS_TO_METERS
并使其工作完全相同。似乎并非如此。重力似乎很小,施加冲量几乎没有任何影响。
// Used to scale all sprite's coordinates
public static final float PIXELS_TO_METERS = 1f;
// Used with physics world.
public static final float GRAVITY = -9.8f * 100;
public static final float IMPULSE = 0.15f * 100;
所以:
1) 为什么简单地放大所有值不能使其工作相同?
2) 有更好的方法吗?
看起来您使用一些虚构的像素单位使您的设计过于复杂(我怀疑您指的是实际像素)。我建议您改为使用有意义的单位,例如 meters,并坚持使用。因此,对所有坐标(包括您的虚拟视口)使用米。因此,实际上将您的代码修改为如下所示:
// Used to create an Extend Viewport
public static final float MIN_WIDTH = 4.8f; // at least 4.8 meters in width is visible
public static final float MIN_HEIGHT = 8.0f; // at least 8 meter in height is visible
这完全消除了将仪表缩放到您想象的像素单位的需要。从您的单位(虚拟视口大小)到 screen (values between -1 and +1) is done by the camera 的实际缩放。您不必考虑设计中的缩放单位。
确保删除您的 PIXELS_TO_METERS
常量(不要将其设置为 1f
,它只会使您的代码复杂化而没有任何好处)并确保您没有使用假想像素都在你的代码中。后者包括您创建的所有精灵,但没有明确指定其大小(以米为单位)。
由于正当理由,与 SI 单位相比,"scale" 您的单位(在您的游戏逻辑中)仍然是可能的。例如,在创建 space 游戏时,您可能会发现自己在使用仪表时使用了非常大的数字。通常您希望将值保持在 1f
左右以避免浮点错误。在这种情况下,使用例如十米 (x10)、百米 (x100) 或公里 (x1000)。如果这样做,请确保保持一致。在评论中添加单位可能会有所帮助,这样您就不会忘记正确缩放(例如 GRAVITY = -0.0098f; // kilometer per second per second
)。
我是这样实现的:
// in declaration
float PIXELS_TO_METERS = 32; // in my case: 1m = 32 pixels
Matrix4 projection = new Matrix4();
// in creation
viewport = new FitViewport(
Application.width
, Application.height
, Application.camera);
viewport.apply();
// set vieport dimensions
camera.setToOrtho(false, gameWidth, gameHeight);
// in render
projection.set(batch.getProjectionMatrix());
projection.scl(PIXELS_TO_METERS);
box2dDebugRenderer.render(world, projection);
// in player body creation
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.x = getPosition().x / PIXELS_TO_METERS;
bodyDef.position.y = getPosition().y / PIXELS_TO_METERS;
CircleShape shape = new CircleShape();
shape.setRadius((getBounds().width * 0.5f) / PIXELS_TO_METERS);
// in player update
setPosition(
body.getPosition().x * PIXELS_TO_METERS - playerWidth,
body.getPosition().y * PIXELS_TO_METERS - playerHeight);
因此,要在 box2d 方法中将像素设置为米,您必须将像素位置除以 PIXELS_TO_METERS,并将米设置为玩家位置中的像素,您必须将 box2d 值乘以 PIXELS_TO_METERS。
将您的 PIXELS_TO_METERS 正确设置为您的屏幕中有多少像素与 1 米相匹配。
祝你好运。