Skip to content

Instantly share code, notes, and snippets.

@Happsson
Last active August 29, 2015 14:04
Show Gist options
  • Save Happsson/03f27886785fb162d111 to your computer and use it in GitHub Desktop.
Save Happsson/03f27886785fb162d111 to your computer and use it in GitHub Desktop.
fungerande rep i box2d
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