Last active
August 29, 2015 14:04
-
-
Save Happsson/03f27886785fb162d111 to your computer and use it in GitHub Desktop.
fungerande rep i box2d
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.mygdx.game; | |
import com.badlogic.gdx.ApplicationAdapter; | |
import com.badlogic.gdx.Gdx; | |
import com.badlogic.gdx.InputAdapter; | |
import com.badlogic.gdx.InputMultiplexer; | |
import com.badlogic.gdx.graphics.GL20; | |
import com.badlogic.gdx.graphics.OrthographicCamera; | |
import com.badlogic.gdx.graphics.g2d.Sprite; | |
import com.badlogic.gdx.graphics.g2d.SpriteBatch; | |
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.BodyDef; | |
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType; | |
import com.badlogic.gdx.physics.box2d.Box2DDebugRenderer; | |
import com.badlogic.gdx.physics.box2d.CircleShape; | |
import com.badlogic.gdx.physics.box2d.FixtureDef; | |
import com.badlogic.gdx.physics.box2d.World; | |
import com.badlogic.gdx.physics.box2d.joints.RevoluteJoint; | |
import com.badlogic.gdx.physics.box2d.joints.RevoluteJointDef; | |
public class Test4500 extends ApplicationAdapter{ | |
private final int PPM = 50; //Ändra här för att ändra hur mycket gravitationen påverkar repet. | |
private Box2DDebugRenderer rend; | |
private Body startBody; | |
private Body[] b; | |
private OrthographicCamera cam; | |
private World world; | |
private float circleRadius = 7f / PPM; //ändra 7f för att göra större eller mindre bollar i repet. | |
private boolean anyActiveBalls = false; | |
@Override | |
public void create() { | |
//initerar stuff. | |
rend = new Box2DDebugRenderer(); | |
cam = new OrthographicCamera(Gdx.graphics.getWidth()/PPM, Gdx.graphics.getHeight()/PPM); | |
cam.position.set(0,0,0); | |
world = new World(new Vector2(0,-2f), true); | |
Vector2 startPosition = new Vector2(0 / PPM ,0 / PPM); //Var knytpunkten för repet ska vara. | |
createStartPoint(startPosition); //Skapa startpunkten. | |
Gdx.input.setInputProcessor(new InputMultiplexer(new InputAdapter() { | |
@Override | |
public boolean touchDragged(int screenX, int screenY, int pointer) { | |
//tar fram var på skärmen man klickar. | |
Vector3 screenCords = new Vector3(screenX, screenY, 0); | |
Vector3 worldCoords = new Vector3(); | |
worldCoords.set(screenCords); | |
cam.unproject(worldCoords); | |
//gör om från vector3 (3D) till vector2 (som jag använder i createBodies()) | |
Vector2 mousePos = new Vector2(worldCoords.x, worldCoords.y); | |
//om tidigare bollar har gjorts tas de bort. | |
if(anyActiveBalls) destroyBalls(); | |
//hittar avståndet mellan muspositionen och startpunkten. | |
Vector2 delta = getDelta(startBody.getPosition(), mousePos); | |
int numBalls = Math.round(delta.len() / circleRadius) ; | |
//Skapar bollarna. | |
createBodies(numBalls, mousePos, startBody.getPosition()); | |
//Sätter första och sista bollen till statisk, bara just nu för att repet alltid ska fästa. | |
b[0].setType(BodyType.StaticBody); | |
b[b.length-1].setType(BodyType.StaticBody); | |
return true; | |
} | |
})); | |
} | |
private void createStartPoint(Vector2 startPosition) { | |
//skapar startpositionen. | |
CircleShape pshape = new CircleShape(); | |
pshape.setRadius(circleRadius); | |
BodyDef bdef = new BodyDef(); | |
FixtureDef fdef = new FixtureDef(); | |
bdef.position.set(startPosition); | |
bdef.type = BodyType.StaticBody; | |
fdef.shape = pshape; | |
fdef.isSensor = true; | |
startBody = world.createBody(bdef); | |
startBody.createFixture(fdef); | |
fdef.isSensor = false; | |
pshape.dispose(); | |
} | |
public Body[] createBodies(int numBalls, Vector2 baPos, Vector2 bbPos){ | |
anyActiveBalls = true; | |
//vektorn delta innehåller i praktiken vektorn mellan de två kropparna. | |
Vector2 delta = getDelta(baPos, bbPos); | |
//positionen används för att veta var på bollarna vi ska sätta jointarna. | |
Vector2 posA = new Vector2(); | |
Vector2 posB = new Vector2(); | |
//tar fram x, k och m (från y = kx + m), alltså lutningen på vektorn. Behövs för att beräkna positionerna på bollarna. | |
float x = bbPos.x; | |
float y = bbPos.y; | |
float k = getK(baPos, bbPos); | |
float m = getM(baPos, k); | |
//avståndet mellan bollarna. | |
float distBetweenBalls; | |
if(delta.x != 0){ | |
distBetweenBalls = delta.x / numBalls; | |
}else{ | |
distBetweenBalls = delta.y / numBalls; | |
} | |
// System.out.println("y=kx+m: " + delta.y +"=" + k +"*" + delta.x + "+" + m); | |
//vektorräkning, enhetsvektorn av den inkommande vektorn mellan de två kropparna, gånger cirkelns radie, delat på två. | |
//detta används för att veta var på bollarna vi ska placera jointarna. Skapar först en enhetsvektor med samma riktning som | |
//vektorn mellan de två huvudkropparna, gör sedan om den till längden av radien av våra bollar, och delar på två (för att få | |
//överlappande bollar). Vi får då en x- och y-punkt på varje boll som ligger i linje med vektorn mellan kropparna. | |
posA.x = (float) ((1/ (Math.sqrt((delta.x * delta.x + delta.y * delta.y))) * delta.x)) * circleRadius / 2; | |
posA.y = (float) ((1/ (Math.sqrt((delta.x * delta.x + delta.y * delta.y))) * delta.y)) * circleRadius / 2; | |
//posB är på motsatt sida från bollens mitt jämfört med posA. | |
posB.x = -posA.x; | |
posB.y = -posA.y; | |
//array med alla bollar, antalet redan beräknat. | |
b = new Body[numBalls]; | |
//jointar, alltid en mindre än antalet bollar. | |
RevoluteJoint[] joints = new RevoluteJoint[numBalls - 1]; | |
CircleShape pshape = new CircleShape(); | |
pshape.setRadius(circleRadius); | |
FixtureDef fdef = new FixtureDef(); | |
fdef.density = 0; | |
fdef.shape = pshape; | |
BodyDef bdef = new BodyDef(); | |
bdef.type = BodyType.DynamicBody; | |
for(int i = 0; i<numBalls; i++){ | |
if(delta.x != 0){ | |
//linjens ekvation. | |
bdef.position.set(x,k * x + m); | |
}else{ | |
bdef.position.set((y-m)/k,y); | |
} | |
//itererar till nästa bolls position. | |
x = x + distBetweenBalls; | |
y = y + distBetweenBalls; | |
b[i] = world.createBody(bdef); | |
b[i].createFixture(fdef); | |
} | |
//skapar jointarna på bollarna. | |
RevoluteJointDef rjd = new RevoluteJointDef(); | |
rjd.localAnchorA.set(posA); | |
rjd.localAnchorB.set(posB); | |
rjd.collideConnected = false; | |
for(int i = 0; i<numBalls - 1; i++){ | |
rjd.bodyA = b[i]; | |
rjd.bodyB = b[i+1]; | |
joints[i] = (RevoluteJoint) world.createJoint(rjd); | |
} | |
pshape.dispose(); | |
return b; | |
} | |
@Override | |
public void render() { | |
Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT); | |
rend.render(world, cam.combined); | |
world.step(1 / 60f, 1, 1); | |
} | |
public float getM(Vector2 bodyPos, float k){ | |
//hittar m i y = kx + m | |
float m = bodyPos.y - k*bodyPos.x; | |
return m; | |
} | |
public Vector2 getDelta(Vector2 ba, Vector2 bb){ | |
Vector2 delta = new Vector2(); | |
delta.x = ba.x - bb.x; | |
delta.y = ba.y - bb.y; | |
return delta; | |
} | |
public float getK(Vector2 ba, Vector2 bb){ | |
float deltaX = ba.x - bb.x; | |
float deltaY = ba.y - bb.y; | |
if(deltaX != 0) { | |
return deltaY / deltaX; | |
}else{ | |
return 0; | |
} | |
} | |
public void destroyBalls(){ | |
for(int i = 0; i < b.length; i++){ | |
world.destroyBody(b[i]); | |
b[i] = null; | |
} | |
} | |
@Override | |
public void resize(int width, int height) { | |
// TODO Auto-generated method stub | |
super.resize(width, height); | |
} | |
@Override | |
public void pause() { | |
// TODO Auto-generated method stub | |
super.pause(); | |
} | |
@Override | |
public void resume() { | |
// TODO Auto-generated method stub | |
super.resume(); | |
} | |
@Override | |
public void dispose() { | |
// TODO Auto-generated method stub | |
super.dispose(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment