6.Libgdx扩展学习之Box2D_鼠标关节

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zqiang_55/article/details/53817558

下面一些内容定义来自《Box2D中文手册》

关于

关节用于把物体约束到世界,或约束到其它物体上。在游戏中,典型例子有木偶,跷跷板和滑轮。用不同的方式将关节结合起来使用,可以创造出有趣的运动。
有些关节提供了限制(limit),使可以控制运动的范围。有些关节还提供了马达(motor),它可以以指定的速度驱动关节一直运动,直到你指定了更大的力或扭矩来抵消这种运动。
关节马达有许多不同的用途。可以使用关节来控制位置,只要提供一个与目标之距离成正比例的关节速度即可。还可以模拟关节摩擦:将关节速度置零,并且提供一个小的、但有效的最大力或扭矩;那么马达就会努力保持关节不动,直到负载变得过大为止。

关节定义

每种关节类型都有各自的定义(definition),它们都派生自 JointDef。所有的关节都连接两个不同的物体,其中一个物体有可能是静态的。关节也可以连接两个 static 或者 kinematic 类型的物体,但这没有任何实际用途,只会浪费处理器时间。
可以为任何一种关节类型指定用户数据。还可以提供一个标记,用于防止用关节相连的物体之间发生碰撞。实际上, 这是默认行为。也可以通过设置 collideConnected,来允许相连的物体之间发生碰撞
很多关节定义需要提供一些几何数据。一个关节常常需要一个锚点(anchor point)来定义,这是固定于相接物体中的点。 Box2D 要求这些点在局部坐标系中指定,这样,即便当前物体的变化违反了关节约束(joint constraint),关节还是可以被指定–这通常会发生在游戏保存或载入进度时。
另外,有些关节定义需要知道物体之间默认的相对角度。这样才能正确地约束旋转。
初始化几何数据可能有些乏味。所以很多关节提供了初始化函数,使用当前的物体的形状,来消除大部分工作。然而,这些初始化函数通常只应用于原型,在产品代码中应该直接地定义几何数据。这能使关节行为更具健壮性。

鼠标关节

鼠标关节用于通过鼠标来操控物体,它试图将物体托向当前鼠标光标的位置,而在旋转方面就没有限制。
鼠标关节的定义需要一个目标点(target point),最大力(maximum force),频率(frequency),阻尼率(damping ratio)。目标点最开始与物体的锚点重合,最大力用于防止再多个动态物体相互作用时的激烈反应。频率和阻尼用于创造一种弹性效果。
1.com.badlogic.gdx.physics.box2d.JointDef

    /** The first attached body. **/
    public Body bodyA = null;

    /** The second attached body **/
    public Body bodyB = null;

    /** Set this flag to true if the attached bodies should collide. **/
    public boolean collideConnected = false;

2.com.badlogic.gdx.physics.box2d.joints.MouseJointDef

    /** The initial world target point. This is assumed to coincide with the body anchor initially.   锚点  */
    public final Vector2 target = new Vector2();

    /** The maximum constraint force that can be exerted to move the candidate body. Usually you will express as some multiple of
     * the weight (multiplier * mass * gravity). */
    public float maxForce = 0;

    /** The response speed. */
    public float frequencyHz = 5.0f;

    /** The damping ratio. 0 = no damping, 1 = critical damping. */
    public float dampingRatio = 0.7f;

3.com.badlogic.gdx.physics.box2d.joints.MouseJoint extends Joint
/** A mouse joint is used to make a point on a body track a specified world point. This a soft constraint with a maximum force.
** This allows the constraint to stretch and without applying huge forces. NOTE: this joint is not documented in the manual
* because it was developed to be used in the testbed. If you want to learn how to use the mouse joint, look at the testbed. /

![这里写图片描述](http://img.blog.csdn.net/20170105225558705?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenFpYW5nXzU1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
/**
 * 鼠标关节测试
 */
public class MouseJointTest extends ApplicationAdapter {

    World world;
    Box2DDebugRenderer box2DDebugRenderer;
    Body mouseJointBody, groundBody;
    Fixture fixture;

    OrthographicCamera camera;
    Vector3 point = new Vector3();

    float scene_width = 12.8f;
    float scene_height = 7.2f;
    Vector2 target = new Vector2();

    @Override
    public void create() {
        world = new World(new Vector2(0.0f, -9.8f), true);
        box2DDebugRenderer = new Box2DDebugRenderer();

        camera = new OrthographicCamera(scene_width, scene_height);
        camera.position.set(scene_width / 2, scene_height / 2, 0);
        camera.update();

        groundBody = createGroundWall();

        Gdx.input.setInputProcessor(new HandA());

        BodyDef bodyDef = new BodyDef();
        bodyDef.position.set(3.0f, 4.8f);
        bodyDef.type = BodyDef.BodyType.DynamicBody;
        mouseJointBody = world.createBody(bodyDef);

        PolygonShape polygonShape = new PolygonShape();
        polygonShape.setAsBox(0.5f, 0.5f);

        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.shape = polygonShape;
        fixtureDef.density = 1.0f;
        fixtureDef.restitution = 0.6f;

        fixture = mouseJointBody.createFixture(fixtureDef);
    }

    @Override
    public void render() {
        world.step(1 / 60f, 6, 2);

        Gdx.gl.glClearColor(0.39f, 0.58f, 0.92f, 1.0f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        box2DDebugRenderer.render(world, camera.combined);
    }

    @Override
    public void dispose() {
        world.dispose();
        box2DDebugRenderer.dispose();
    }

    public Body createGroundWall() {
        BodyDef bodyDef = new BodyDef();
        bodyDef.position.set(scene_width * 0.5f, 0.2f);
        Body body1 = world.createBody(bodyDef);

        PolygonShape polygonShape = new PolygonShape();
        polygonShape.setAsBox(scene_width * 0.5f, 0.2f);
        body1.createFixture(polygonShape, 0.0f);

        bodyDef.position.set(0.4f, scene_height * 0.5f);
        Body body2 = world.createBody(bodyDef);

        polygonShape.setAsBox(0.2f, scene_height * 0.5f);
        body2.createFixture(polygonShape, 0);

        bodyDef.position.set(12.4f, scene_height * 0.5f);
        Body body3 = world.createBody(bodyDef);

        polygonShape.setAsBox(0.2f, scene_height * 0.5f);
        body3.createFixture(polygonShape, 0);

        bodyDef.position.set(scene_width * 0.5f, 7.0f);
        Body body4 = world.createBody(bodyDef);

        polygonShape.setAsBox(scene_width * 0.5f, 0.2f);
        body4.createFixture(polygonShape, 0);
        polygonShape.dispose();

        return body1;
    }

    private void logInfo(String message) {
        Gdx.app.log("MouseJointTest", message);
    }

    class HandA extends InputAdapter {

        MouseJoint mouseJoint;

        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            logInfo("touchDragged");
            if (mouseJoint != null) {
                camera.unproject(point.set(screenX, screenY, 0));
                mouseJoint.setTarget(target.set(point.x, point.y));
            }

            return false;
        }

        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
            logInfo("touchDown");
            camera.unproject(point.set(screenX, screenY, 0));
            //  当鼠标点击到物体时才会创建鼠标关节,并绑定
            if (fixture.testPoint(point.x, point.y)) {
                if (mouseJointBody == null) return false;

                MouseJointDef mouseJointDef = new MouseJointDef();
                mouseJointDef.bodyA = groundBody;
                mouseJointDef.bodyB = mouseJointBody;
                mouseJointDef.collideConnected = true;
                mouseJointDef.target.set(point.x, point.y);
                mouseJointDef.maxForce = 1000.0f * mouseJointBody.getMass();

                mouseJoint = (MouseJoint) world.createJoint(mouseJointDef);
                mouseJointBody.setAwake(true);

            }
            return false;
        }

        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
            logInfo("touchUp");
            // 鼠标关节,不再使用时要销毁
            if (mouseJoint != null) {
                world.destroyJoint(mouseJoint);
                mouseJoint = null;
            }
            return false;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/zqiang_55/article/details/53817558