Back to project page SpaceRagdoll.
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.
/******************************************************************************* * 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; } }