1

私は libgdx で Box2D をいじろうとしていますが、残念ながらその仕組みを理解できないようです。

私を夢中にさせるいくつかの例を次に示します。

.1. Box2D がメートルで動作することが知られています。誰もがそれを知っています。では、なぜピクセル単位で結果が得られるのでしょうか? たとえば、ボディ定義を定義し、位置を 0,1 に設定すると、関連するフィクスチャ/スプライトが画面の左下隅に描画されます! Box2D の 0,0 ポイントが画面の中心にあると思いました。

.2. 私が理解し解決するのに苦労しているもう 1 つの問題は、シェイプ、ジョイント、およびその他のものの値です。シェイプから始めましょう。次のように Polygon シェイプを定義しました。

shape.setAsBox(1, 2);

形は幅2メートル、高さ4メートルになるはずだったのですが、そうではありません。私が得たのは超小型の形状です。

最後に、ジョイントの値です。ポリゴン形状のボディとグラウンド ボディを定義しました。ここで、特定の範囲内で適切に回転するある種のカタパルトを作成することを目標として、Revolute Joint を使用してこれら 2 つを地面のボディの中心に「固定」しました。

ここで、マウス ジョイントも定義して、カタパルト (ポリゴン シェイプ) をうまく前後にドラッグできるようにしましたが、ジョイントの maxForce を非常に大きな値に設定する必要があるようです。カタパルト!理解できない。私が設定しなければならなかった値に関して、この問題はすべて小さな値で操作する必要があります。

上記のすべてを含む私の非常に基本的なコードを次に示します。私が間違っていることを教えてください、私はここでびっくりしています:

GameScreen.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();
    }
}

InputHandler.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;
    }

}

ここで私を助けていただければ、本当に感謝しています。ありがとう!!

4

1 に答える 1