Android Open Source - SpaceRagdoll Ragdoll






From Project

Back to project page SpaceRagdoll.

License

The source code is released under:

GNU General Public License

If you think the Android project SpaceRagdoll listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*******************************************************************************
 * Copyright (C) 2015 Tuukka Ruhanen/*from  w  ww.j  a  v a 2 s . com*/
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *******************************************************************************/
package fi.karu.spaceragdoll;

import java.util.ArrayList;

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.CircleShape;
import com.badlogic.gdx.physics.box2d.FixtureDef;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.Shape;
import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef;
import com.badlogic.gdx.physics.box2d.World;

public class Ragdoll {

    public enum State {
        GROUND, OFF, ON
    }

    public State state = State.GROUND;
    public static final float F = 6000f; // rocket force
    public static final float MAXSWINGVELOCITY = 200; // maximum angular velocity
    public static final float SWINGFORCEMULTIPLIER = 500; // maximum angular velocity

    public static final float PRESSURESEA = 0; // .008f; // air pressure at sealevel
    public static final float PRESSUREGRADIENT = .0003f; // air density gradient

    public static final float DENSITY = .4f; // bird density
    public static final float FRICTION = .4f; // bird
    public static final float RESTITUTION = .6f; // bird

    static final float r = .4f; // rocket radius
    static final float d = .3f; // jet width
    static final float l = 3f; // jet length

    static float mainBodyLength = 2f;
    static float mainBodyWidth = 1.4f;
    static float headRadius = 1f;
    static float handWidth = .6f;
    static float handLength = 1.8f;
    static float legWidth = .6f;
    static float legLength = 1.8f;

    private static float mainBodyX = 0f;
    private static float mainBodyY = 0f;

    private ArrayList<Body> bodies;

    private int swingX, swingY, swingDX, swingDY = 0;

    public Ragdoll(ArrayList<Body> bodies) {
        this.bodies = bodies;
    }

    public State getState() {
        return state;
    }

    public void setState(State newState) {
        this.state = newState;
    }

    public void setSwing(int swingX, int swingY) {
        if (this.swingX == 0) {
            this.swingX = swingX;
            this.swingY = swingY;
        } else {
            swingDX = swingX - this.swingX;
            swingDY = swingY - this.swingY;
            this.swingX = swingX;
            this.swingY = swingY;
        }
    }

    public static Ragdoll create(World world) {
        Body mainBody = createBodyPart(world, null, true, mainBodyLength, mainBodyWidth, mainBodyX, mainBodyY, 0, 0, 0, 0, 0, 0);
        Body headBody = createBodyPart(world, mainBody, false, headRadius, headRadius, mainBodyX + mainBodyLength / 2 + headRadius, mainBodyY,
                0, 0, -mainBodyLength / 2 - headRadius, 0, (float) (-Math.PI / 10), (float) (Math.PI / 10));
        Body rightHandBody = createBodyPart(world, mainBody, true, handWidth, handLength, mainBodyX + mainBodyLength / 3f, mainBodyY - mainBodyWidth / 2f - handLength / 2f,
                mainBodyLength / 3f, -mainBodyWidth / 2f, 0, handLength / 2f, (float) (-Math.PI / 3), (float) (Math.PI / 3));
        Body leftHandBody = createBodyPart(world, mainBody, true, handWidth, handLength, mainBodyX + mainBodyLength / 3f, mainBodyY + mainBodyWidth / 2f + handLength / 2f,
                mainBodyLength / 3f, mainBodyWidth / 2f, 0, -handLength / 2f, (float) (-Math.PI / 3), (float) (Math.PI / 3));
        Body rightLegBody = createBodyPart(world, mainBody, true, legLength, legWidth, mainBodyX - mainBodyLength / 2f - legLength / 2f, mainBodyY - mainBodyWidth / 2f + legWidth / 2f,
                -mainBodyLength / 2f - legWidth / 2f, -mainBodyWidth / 2f + legWidth / 2f, legLength / 2f - legWidth / 2f, 0, (float) (-Math.PI / 10), (float) (Math.PI * 2f / 3));
        Body leftLegBody = createBodyPart(world, mainBody, true, legLength, legWidth, mainBodyX - mainBodyLength / 2f - legLength / 2f, mainBodyY + mainBodyWidth / 2f - legWidth / 2f,
                -mainBodyLength / 2f - legWidth / 2f, mainBodyWidth / 2f - legWidth / 2f, legLength / 2f - legWidth / 2f, 0, (float) (-Math.PI * 2f / 3), (float) (Math.PI / 10));

        ArrayList<Body> bodies = new ArrayList<Body>();
        bodies.add(mainBody);
        bodies.add(headBody);
        bodies.add(leftHandBody);
        bodies.add(rightHandBody);
        bodies.add(leftLegBody);
        bodies.add(rightLegBody);

        return new Ragdoll(bodies);
    }

    public Body getMainBody() {
        return bodies.get(0);
    }

    public Body getLegBody() {
        return bodies.get(5);
    }

    public void applyForces() {
        applyGravity();
        applyDrag();
        if (state == Ragdoll.State.ON)
            applyRocketForce();
        else if (state == Ragdoll.State.GROUND && (swingDX != 0 || swingDY != 0))
            applySwingForce();
    }

    public void applyGravity() {
        Vector2 pos, gravity;
        for (Body body : bodies) {
            pos = body.getWorldCenter().add(0, Planet.R);
            gravity = pos.nor().scl(-Planet.M * body.getMass() / (pos.dot(pos)));
            body.applyForceToCenter(gravity, true);
        }
    }

    public void applyDrag() {
        Vector2 pos = bodies.get(0).getWorldCenter().add(0, Planet.R);
        float pressure = PRESSURESEA - PRESSUREGRADIENT * (pos.len() - Planet.R);
        // System.out.println("pressure: " + pressure);
        if (pressure > 0) {
            Vector2 vel = bodies.get(0).getLinearVelocity();
            float drag = pressure * vel.len2();
            // System.out.println("drag: " + drag);
            vel.clamp(drag, drag).rotate(180);
            Vector2 point = bodies.get(0).getPosition();
            bodies.get(0).applyForce(vel, point, true);
        }
    }

    public void applyRocketForce() {
        float a = bodies.get(0).getAngle();
        Vector2 force = new Vector2(0, Ragdoll.F).setAngleRad((float) (a));
        Vector2 point = bodies.get(0).getWorldCenter();
        bodies.get(0).applyForce(force, point, true);
    }

    public void applySwingForce() {
        if (bodies.get(0).getLinearVelocity().len() < MAXSWINGVELOCITY) {
            Vector2 force = new Vector2(swingDX, swingDY).scl(SWINGFORCEMULTIPLIER);
            Vector2 point = bodies.get(0).getWorldCenter();
            bodies.get(0).applyForce(force, point, true);
        }
    }

    public float getAngle() {
        return bodies.get(0).getAngle();
    }

    public Vector2 getPosition() {
        return bodies.get(0).getPosition();
    }

    /**
     * @param world
     * @param bodyA
     * @param isBox
     * @param width
     * @param height
     * @param x
     * @param y
     * @param anchorAX
     * @param anchorAY
     * @param anchorBX
     * @param anchorBY
     * @param minAngle
     * @param maxAngle
     * @return
     */
    public static Body createBodyPart(World world, Body bodyA, boolean isBox, float width, float height, float x, float y,
            float anchorAX, float anchorAY, float anchorBX, float anchorBY, float minAngle, float maxAngle) {
        // body
        BodyDef bodyDef = new BodyDef();
        bodyDef.type = BodyType.DynamicBody;
        bodyDef.position.set(x, y);
        Body body = world.createBody(bodyDef);
        Shape shape;
        if (isBox) {
            shape = new PolygonShape();
            ((PolygonShape) shape).setAsBox(width / 2, height / 2);
        } else {
            shape = new CircleShape();
            shape.setRadius(width); // trust that width means radius if isBox == false
        }
        FixtureDef fixtureDef = new FixtureDef();
        fixtureDef.filter.groupIndex = -1;
        fixtureDef.shape = shape;
        fixtureDef.density = DENSITY;
        fixtureDef.friction = FRICTION;
        fixtureDef.restitution = RESTITUTION;
        body.createFixture(fixtureDef);
        shape.dispose();

        if (bodyA == null)
            return body;

        // joint
        RevoluteJointDef revoluteJointDef = new RevoluteJointDef();
        revoluteJointDef.bodyA = bodyA;
        revoluteJointDef.bodyB = body;
        revoluteJointDef.localAnchorA.set(anchorAX, anchorAY);
        revoluteJointDef.localAnchorB.set(anchorBX, anchorBY);
        revoluteJointDef.referenceAngle = 0;
        revoluteJointDef.enableLimit = true;
        revoluteJointDef.lowerAngle = minAngle;
        revoluteJointDef.upperAngle = maxAngle;
        world.createJoint(revoluteJointDef);

        return body;
    }
}




Java Source Code List

fi.karu.spacebird_android.SpaceRagdollActivity.java
fi.karu.spaceragdoll.GameScreen.java
fi.karu.spaceragdoll.Planet.java
fi.karu.spaceragdoll.Ragdoll.java
fi.karu.spaceragdoll.SpaceRagdoll.java
fi.karu.spaceragdoll.SpaceRenderer.java
fi.karu.spaceragdoll.Space.java
fi.karu.spaceragdoll.controller.Controller.java
fi.karu.spaceragdoll_desktop.SpaceRagdollDesktop.java