Box2d坐标系
Box2d coordinate system
在我尝试编写代码的游戏中,我必须有两个身体。一个 StaticBody 和一个 DynamicBody。我想在 StaticBody 之上放置 DynamicBody。不知何故,我得到的是:
有没有可能视口左下角不在 0,0?为什么 DynamicBody 不能超越 StaticBody?
Gamescreen.java
package com.joelbrun.jetskirider.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.utils.Scaling;
import com.badlogic.gdx.utils.viewport.ScalingViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class Gamescreen implements Screen {
private static final float TIMESTEP = 1 / 60;
private static final int VELOCITY_ITERATIONS = 8;
private static final int POSITION_ITERATIONS = 3;
public static final int GAMESCREEN_WIDTH = 1920;
public static final int GAMESCREEN_HEIGHT = 720;
public static final int OBSTACLE_TYPES = 5;
private static final int WATER_HEIGHT = 200;
private static final float JETSKI_BOX_X = 200;
private static final float JETSKI_BOX_Y = 100;
private World world;
private Box2DDebugRenderer debugRenderer;
public Texture jetski, wave;
public Sprite background;
public SpriteBatch batch;
public OrthographicCamera camera;
public Label score;
Viewport viewport;
@Override
public void show() {
world = new World(new Vector2(0, -9.81f), true);
debugRenderer = new Box2DDebugRenderer();
Texture[] texture = new Texture[OBSTACLE_TYPES];
//Textures
for (int i=0; i<OBSTACLE_TYPES; i++){
texture[i] = new Texture(Gdx.files.internal("game/obstacles/obstacle" + Integer.toString(i+1)+".png"));
}
background = new Sprite(new Texture("game/background.png"));
jetski = new Texture("game/jetski.png");
wave = new Texture("game/water1.png");
batch = new SpriteBatch();
//Camera & Viewport
camera = new OrthographicCamera();
viewport = new ScalingViewport(Scaling.fillY, GAMESCREEN_WIDTH, GAMESCREEN_HEIGHT, camera);
viewport.apply();
camera.position.set(GAMESCREEN_WIDTH / 2, GAMESCREEN_HEIGHT / 2, 0);
//body definition Water
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(0, 0);
Body body = world.createBody(bodyDef);
//shape
PolygonShape box = new PolygonShape();
box.setAsBox(2560, WATER_HEIGHT);
//fixture definition
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = box;
fixtureDef.density = 1000;
fixtureDef.friction = .25f;
fixtureDef.restitution = .1f;
Fixture fixture = body.createFixture(fixtureDef);
box.dispose();
//Jetski
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(1280,WATER_HEIGHT + 100);
Body jetskiObject = world.createBody(bodyDef);
PolygonShape jetskiBox = new PolygonShape();
jetskiBox.setAsBox(JETSKI_BOX_X, JETSKI_BOX_Y);
fixtureDef.shape = jetskiBox;
fixtureDef.density = 100;
fixtureDef.friction = 0;
Fixture jetskiFixture = body.createFixture(fixtureDef);
jetskiBox.dispose();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
debugRenderer.render(world, camera.combined);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.end();
camera.update();
world.step(TIMESTEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
}
@Override
public void resize(int width, int height) {
int SCREEN_WIDTH = width;
int SCREEN_HEIGHT = height;
viewport.setWorldSize(GAMESCREEN_WIDTH, GAMESCREEN_HEIGHT);
viewport.update(SCREEN_WIDTH, SCREEN_HEIGHT,true);
camera.update();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
dispose();
}
@Override
public void dispose() {
batch.dispose();
background.getTexture().dispose();
jetski.dispose();
wave.dispose();
world.dispose();
debugRenderer.dispose();
}
}
是的,对于 Box2D,原点是视口的左下角。
您可以在设置 BodyDef :
时设置身体的位置
bodyDef.position.set(x, y);
并且不要忘记,在 Box2D 中,您的 body 的位置是 Body 的中心。因此,当您将 PolygonShape 设置为这样的框时:
polygonShape.setAsBox(width, height);
您的实际框宽为width*2,实际框高为height*2
你用错了Box2D。你应该将 Box2D 缩小到一个小世界,因为如果不这样做,物理相互作用将是 1px = 1m 并且 1920 x 720 太大(这将反映为你的身体移动太慢,因为它们太大)。
检查您的代码:
PolygonShape box = new PolygonShape();
box.setAsBox(2560, WATER_HEIGHT); // <- your water object dimensions
和
PolygonShape jetskiBox = new PolygonShape();dimensions
jetskiBox.setAsBox(JETSKI_BOX_X, JETSKI_BOX_Y); // <- your jetsky object
然后,检查setAsBox
方法:
public void setAsBox(float hx, float hy)
Parameters:
hx - the half-width.
hy - the half-height.
(强调)
因此,对于您的水,您正在创建 5120 x 400
的静态 body,对于您的摩托艇 400 x 200
,这个值太高了。
我建议尝试使用 official wiki but then check sites like this and read the manual 中出现的示例来了解 Box2D 的工作原理。我可以提取这个:
In particular, Box2D has been tuned to work well with moving objects between 0.1 and 10 meters. So this means objects between soup cans and buses in size should work well. Static objects may be up to 50 meters big without too much trouble.
Being a 2D physics engine, it is tempting to use pixels as your units. Unfortunately this will lead to a poor simulation and possibly weird behavior. An object of length 200 pixels would be seen by Box2D as the size of a 45 story building.
另一件事,我不知道这是否会影响某些方面,但我总是先执行 world.step(...)
,然后再执行 debugRenderer.render(...)
,在您的代码中,您将此倒置(也许这就是你的摩托艇没有被移动的原因。
您应该尝试为静态体使用链形而不是多边形。这样动体就会留在里面而不是"teleporting"出来。动态主体在创建时不得与静态主体相交。希望有用!
在我尝试编写代码的游戏中,我必须有两个身体。一个 StaticBody 和一个 DynamicBody。我想在 StaticBody 之上放置 DynamicBody。不知何故,我得到的是:
有没有可能视口左下角不在 0,0?为什么 DynamicBody 不能超越 StaticBody?
Gamescreen.java
package com.joelbrun.jetskirider.screens;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.Sprite;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.utils.Scaling;
import com.badlogic.gdx.utils.viewport.ScalingViewport;
import com.badlogic.gdx.utils.viewport.Viewport;
public class Gamescreen implements Screen {
private static final float TIMESTEP = 1 / 60;
private static final int VELOCITY_ITERATIONS = 8;
private static final int POSITION_ITERATIONS = 3;
public static final int GAMESCREEN_WIDTH = 1920;
public static final int GAMESCREEN_HEIGHT = 720;
public static final int OBSTACLE_TYPES = 5;
private static final int WATER_HEIGHT = 200;
private static final float JETSKI_BOX_X = 200;
private static final float JETSKI_BOX_Y = 100;
private World world;
private Box2DDebugRenderer debugRenderer;
public Texture jetski, wave;
public Sprite background;
public SpriteBatch batch;
public OrthographicCamera camera;
public Label score;
Viewport viewport;
@Override
public void show() {
world = new World(new Vector2(0, -9.81f), true);
debugRenderer = new Box2DDebugRenderer();
Texture[] texture = new Texture[OBSTACLE_TYPES];
//Textures
for (int i=0; i<OBSTACLE_TYPES; i++){
texture[i] = new Texture(Gdx.files.internal("game/obstacles/obstacle" + Integer.toString(i+1)+".png"));
}
background = new Sprite(new Texture("game/background.png"));
jetski = new Texture("game/jetski.png");
wave = new Texture("game/water1.png");
batch = new SpriteBatch();
//Camera & Viewport
camera = new OrthographicCamera();
viewport = new ScalingViewport(Scaling.fillY, GAMESCREEN_WIDTH, GAMESCREEN_HEIGHT, camera);
viewport.apply();
camera.position.set(GAMESCREEN_WIDTH / 2, GAMESCREEN_HEIGHT / 2, 0);
//body definition Water
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.StaticBody;
bodyDef.position.set(0, 0);
Body body = world.createBody(bodyDef);
//shape
PolygonShape box = new PolygonShape();
box.setAsBox(2560, WATER_HEIGHT);
//fixture definition
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = box;
fixtureDef.density = 1000;
fixtureDef.friction = .25f;
fixtureDef.restitution = .1f;
Fixture fixture = body.createFixture(fixtureDef);
box.dispose();
//Jetski
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(1280,WATER_HEIGHT + 100);
Body jetskiObject = world.createBody(bodyDef);
PolygonShape jetskiBox = new PolygonShape();
jetskiBox.setAsBox(JETSKI_BOX_X, JETSKI_BOX_Y);
fixtureDef.shape = jetskiBox;
fixtureDef.density = 100;
fixtureDef.friction = 0;
Fixture jetskiFixture = body.createFixture(fixtureDef);
jetskiBox.dispose();
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
debugRenderer.render(world, camera.combined);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.end();
camera.update();
world.step(TIMESTEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
}
@Override
public void resize(int width, int height) {
int SCREEN_WIDTH = width;
int SCREEN_HEIGHT = height;
viewport.setWorldSize(GAMESCREEN_WIDTH, GAMESCREEN_HEIGHT);
viewport.update(SCREEN_WIDTH, SCREEN_HEIGHT,true);
camera.update();
}
@Override
public void pause() {
}
@Override
public void resume() {
}
@Override
public void hide() {
dispose();
}
@Override
public void dispose() {
batch.dispose();
background.getTexture().dispose();
jetski.dispose();
wave.dispose();
world.dispose();
debugRenderer.dispose();
}
}
是的,对于 Box2D,原点是视口的左下角。
您可以在设置 BodyDef :
时设置身体的位置bodyDef.position.set(x, y);
并且不要忘记,在 Box2D 中,您的 body 的位置是 Body 的中心。因此,当您将 PolygonShape 设置为这样的框时:
polygonShape.setAsBox(width, height);
您的实际框宽为width*2,实际框高为height*2
你用错了Box2D。你应该将 Box2D 缩小到一个小世界,因为如果不这样做,物理相互作用将是 1px = 1m 并且 1920 x 720 太大(这将反映为你的身体移动太慢,因为它们太大)。
检查您的代码:
PolygonShape box = new PolygonShape();
box.setAsBox(2560, WATER_HEIGHT); // <- your water object dimensions
和
PolygonShape jetskiBox = new PolygonShape();dimensions
jetskiBox.setAsBox(JETSKI_BOX_X, JETSKI_BOX_Y); // <- your jetsky object
然后,检查setAsBox
方法:
public void setAsBox(float hx, float hy)
Parameters:
hx - the half-width.
hy - the half-height.
(强调)
因此,对于您的水,您正在创建 5120 x 400
的静态 body,对于您的摩托艇 400 x 200
,这个值太高了。
我建议尝试使用 official wiki but then check sites like this and read the manual 中出现的示例来了解 Box2D 的工作原理。我可以提取这个:
In particular, Box2D has been tuned to work well with moving objects between 0.1 and 10 meters. So this means objects between soup cans and buses in size should work well. Static objects may be up to 50 meters big without too much trouble.
Being a 2D physics engine, it is tempting to use pixels as your units. Unfortunately this will lead to a poor simulation and possibly weird behavior. An object of length 200 pixels would be seen by Box2D as the size of a 45 story building.
另一件事,我不知道这是否会影响某些方面,但我总是先执行 world.step(...)
,然后再执行 debugRenderer.render(...)
,在您的代码中,您将此倒置(也许这就是你的摩托艇没有被移动的原因。
您应该尝试为静态体使用链形而不是多边形。这样动体就会留在里面而不是"teleporting"出来。动态主体在创建时不得与静态主体相交。希望有用!