我正在尝试在 libgdx 中使用 Box2D,但不幸的是我似乎无法理解它的工作方式。
以下是一些让我发疯的例子:
.1。众所周知,Box2D 与米一起工作。每个人都知道这一点。那么,为什么我会通过 Pixels 获得结果?例如,如果我定义了一些身体定义并将位置设置为 0,1,它会在屏幕的左下角绘制相关的夹具/精灵!我认为 Box2D 中的 0,0 点位于屏幕的中心。
.2. 我一直在努力理解和解决的另一个问题是形状、关节和其他东西的值。让我们从形状开始:我定义了这样的多边形形状:
shape.setAsBox(1, 2);
现在这个形状本来应该是 2米宽和 4米高,但事实并非如此。我得到的是一个超小的形状。
最后,关节的值。我定义了一个具有多边形形状的主体和一个地面主体。现在我使用 Revolute Joint 将这两个“固定”到地面主体的中心,目标是创建某种弹射器,它可以在一定范围内很好地旋转。
现在我还定义了一个鼠标关节,所以我可以很好地来回拖动弹射器(多边形形状),但似乎我需要将关节的 maxForce 设置为一个巨大的值,这样我才能真正看到运动/旋转弹射!我不明白。这一切都应该由小值来操作,关于我必须设置的值。
这是我非常基本的代码,其中包含上述所有内容。请告诉我我做错了什么,我在这里吓坏了:
游戏画面.java
package com.david.box2dpractice;
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.ChainShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;
import com.badlogic.gdx.utils.Array;
public class GameScreen implements Screen{
private Box2DDebugRenderer debugRenderer;
private Texture texture;
private Sprite sprite;
private Sprite tempSprite;
private SpriteBatch batch;
private Body arm , ground;
private World world;
public OrthographicCamera camera;
private RevoluteJointDef jointDef;
private Array<Body> tempBodies;
public GameScreen() {
debugRenderer = new Box2DDebugRenderer();
batch = new SpriteBatch();
texture = new Texture(Gdx.files.internal("catapult_arm.png"));
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
tempBodies = new Array<Body>();
}
@Override
public void render(float delta) {
// TODO Auto-generated method stub
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
world.getBodies(tempBodies);
batch.begin();
for(Body body : tempBodies) {
if(body.getUserData() != null && body.getUserData() instanceof Sprite) {
tempSprite = (Sprite) body.getUserData();
tempSprite.setPosition(body.getPosition().x-tempSprite.getWidth()/2, body.getPosition().y-tempSprite.getHeight()/2);
tempSprite.setRotation((float) Math.toDegrees(body.getAngle()));
tempSprite.draw(batch);
}
}
batch.end();
debugRenderer.render(world, camera.combined);
world.step(1/60f, 6, 2);
}
@Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
Gdx.app.log("System", "resize() was invoked");
}
@Override
public void show() {
// TODO Auto-generated method stub
Gdx.app.log("System", "show() was invoked");
world = new World(new Vector2(0,0), true);
sprite = new Sprite(texture);
BodyDef bodyDef = new BodyDef();
bodyDef.position.set(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2+sprite.getHeight()/2);
bodyDef.type = BodyType.DynamicBody;
// The shape
PolygonShape shape = new PolygonShape();
shape.setAsBox(11, 91);
// The fixture
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = .10f;
arm = world.createBody(bodyDef);
arm.createFixture(fixtureDef);
sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2);
arm.setUserData(sprite);
shape.dispose();
bodyDef = new BodyDef();
bodyDef.position.set(Gdx.graphics.getWidth()/2,Gdx.graphics.getHeight()/2);
bodyDef.type = BodyType.StaticBody;
ChainShape shape2 = new ChainShape();
shape2.createChain(new Vector2[] {new Vector2(-20*Pixels_To_Meters,0),new Vector2(20*Pixels_To_Meters,0)});
// The fixture
fixtureDef.shape = shape2;
fixtureDef.restitution = .65f;
fixtureDef.friction = .75f;
ground = world.createBody(bodyDef);
ground.createFixture(fixtureDef);
shape2.dispose();
// joint
jointDef = new RevoluteJointDef();
jointDef.bodyA = arm;
jointDef.bodyB = ground;
jointDef.localAnchorB.set(ground.getLocalCenter());
jointDef.localAnchorA.set(arm.getLocalCenter().x,arm.getLocalCenter().y-sprite.getHeight()/2);
jointDef.enableLimit = true;
jointDef.enableMotor = true;
jointDef.motorSpeed = 15;
jointDef.lowerAngle = (float) -Math.toRadians(75);
jointDef.upperAngle = (float) -Math.toRadians(9);
jointDef.maxMotorTorque = 4800;
world.createJoint(jointDef);
Gdx.input.setInputProcessor(new InputHandler(arm,ground,world,camera));
}
@Override
public void hide() {
// TODO Auto-generated method stub
Gdx.app.log("System", "hide() was invoked");
dispose();
}
@Override
public void pause() {
// TODO Auto-generated method stub
Gdx.app.log("System", "pause() was invoked");
}
@Override
public void resume() {
// TODO Auto-generated method stub
Gdx.app.log("System", "resume() was invoked");
}
@Override
public void dispose() {
// TODO Auto-generated method stub
Gdx.app.log("System", "dispose() was invoked");
texture.dispose();
batch.dispose();
world.dispose();
}
}
输入处理程序.java
package com.david.box2dpractice;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.Fixture;
import com.badlogic.gdx.physics.box2d.QueryCallback;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.joints.MouseJoint;
import com.badlogic.gdx.physics.box2d.joints.MouseJointDef;
public class InputHandler implements InputProcessor{
Body ground;
MouseJoint mouseJoint;
MouseJointDef mouseJointDef;
World world;
Vector2 target,initialPos;
Vector3 temp;
QueryCallback query;
OrthographicCamera camera;
boolean firstTime = true;
public InputHandler(Body arm, Body ground, final World world, OrthographicCamera camera) {
this.camera = camera;
this.ground = ground;
this.world = world;
mouseJointDef = new MouseJointDef();
target = new Vector2();
temp = new Vector3();
mouseJointDef.bodyA = ground;
mouseJointDef.collideConnected = true;
mouseJointDef.maxForce = 9000;
query = new QueryCallback() {
@Override
public boolean reportFixture(Fixture fixture) {
// TODO Auto-generated method stub
if(!fixture.testPoint(temp.x, temp.y))
return true;
if(firstTime) {
initialPos = new Vector2(fixture.getBody().getPosition().x,fixture.getBody().getPosition().y);
firstTime = false;
}
mouseJointDef.bodyB = fixture.getBody();
mouseJointDef.target.set(temp.x,temp.y);
mouseJoint = (MouseJoint) world.createJoint(mouseJointDef);
return false;
}
};
}
@Override
public boolean keyDown(int keycode) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean keyUp(int keycode) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean keyTyped(char character) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
// TODO Auto-generated method stub
camera.unproject(temp.set(screenX, screenY, 0));
world.QueryAABB(query, temp.x, temp.y, temp.x, temp.y);
return true;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
// TODO Auto-generated method stub
if(mouseJoint == null)
return false;
mouseJoint.setTarget(initialPos);
world.destroyJoint(mouseJoint);
mouseJoint = null;
firstTime = true;
return true;
}
@Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
// TODO Auto-generated method stub
if(mouseJoint == null)
return false;
camera.unproject(temp.set(screenX, screenY, 0));
mouseJoint.setTarget(target.set(temp.x, temp.y));
return true;
}
@Override
public boolean mouseMoved(int screenX, int screenY) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean scrolled(int amount) {
// TODO Auto-generated method stub
return false;
}
}
如果你能在这里帮助我,我真的很感激。谢谢!!