JBox2D Polygon Collisions Acting Strange

Posted by andy on Game Development See other posts from Game Development or by andy
Published on 2013-10-23T04:52:15Z Indexed on 2013/10/23 10:18 UTC
Read the original article Hit count: 306

Filed under:
|
|
|

I have been playing around with JBox2D and Slick2D and made a little demo with a ground object, a box object, and two different polygons. The problem I am facing is that the collision-detection for the polygons seems to be off (see picture below), but the box's collision works fine.The octagon is too low, and the other on is too high

My Code:

Main Class

package main;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.World;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

import shapes.Box;
import shapes.Polygon;


public class State1 extends BasicGameState{
World world;
int velocityIterations;
int positionIterations;
float pixelsPerMeter;
int state;

Box ground;
Box box1;

Polygon poly1;
Polygon poly2;

Renderer renderer;

public State1(int state)
{
    this.state = state;
}

@Override
public void init(GameContainer gc, StateBasedGame game) throws SlickException
{
    velocityIterations = 10;
    positionIterations = 10;
    pixelsPerMeter = 1f;

    world = new World(new Vec2(0.f, -9.8f));

    renderer = new Renderer(gc, gc.getGraphics(), pixelsPerMeter, world);

    box1 = new Box(-100f, 200f, 40, 50, BodyType.DYNAMIC, world);
    ground = new Box(-14, -275, 50, 900, BodyType.STATIC, world);

    poly1 = new Polygon(50f, 10f, new Vec2[] {
            new Vec2(-6f, -14f), 
            new Vec2(0f, -20f),
            new Vec2(6f, -14f),
            new Vec2(10f, 10f),
            new Vec2(-10f, 10f)
        }, BodyType.DYNAMIC, world);
    poly2 = new Polygon(0f, 10f, new Vec2[] {
            new Vec2(10f, 0f), 
            new Vec2(20f, 0f),
            new Vec2(30f, 10f),
            new Vec2(30f, 20f),
            new Vec2(20f, 30f),
            new Vec2(10f, 30f),
            new Vec2(0f, 20f),
            new Vec2(0f, 10f)
        }, BodyType.DYNAMIC, world);
}

@Override
public void update(GameContainer gc, StateBasedGame game, int delta) throws SlickException
{
    world.step((float)delta / 180f, velocityIterations, positionIterations);
}

@Override
public void render(GameContainer gc, StateBasedGame game, Graphics g) throws SlickException
{
    renderer.render();
}

@Override
public int getID() {
    return this.state;
}

}

Polygon Class

package shapes;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.World;
import org.newdawn.slick.Color;

public class Polygon {
public float x, y;
public Color color;
public BodyType bodyType;
org.newdawn.slick.geom.Polygon poly;
BodyDef def;
PolygonShape ps;
FixtureDef fd;
Body body;
World world;
Vec2[] verts;

public Polygon(float x, float y, Vec2[] verts, BodyType bodyType, World world)
{
    this.verts = verts;
    this.x = x;
    this.y = y;
    this.bodyType = bodyType;
    this.world = world;
    init();
}

public void init()
{
    def = new BodyDef();
    def.type = bodyType;
    def.position.set(x, y);

    ps = new PolygonShape();
    ps.set(verts, verts.length);

    fd = new FixtureDef();
    fd.shape = ps;
    fd.density = 2.0f;
    fd.friction = 0.7f;        
    fd.restitution = 0.5f;

    body = world.createBody(def);
    body.createFixture(fd);
}
}

Rendering Class

package main;

import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.collision.shapes.ShapeType;
import org.jbox2d.common.MathUtils;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.Fixture;
import org.jbox2d.dynamics.World;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.geom.Polygon;
import org.newdawn.slick.geom.Transform;

public class Renderer {

World world;
float pixelsPerMeter;
GameContainer gc;
Graphics g;

public Renderer(GameContainer gc, Graphics g, float ppm, World world)
{
    this.world = world;
    this.pixelsPerMeter = ppm;
    this.g = g;
    this.gc = gc;
}

public void render()
{
    Body current = world.getBodyList();
    Vec2 center = current.getLocalCenter();
    while(current != null)
    {
        Vec2 pos = current.getPosition();
        g.pushTransform();
        g.translate(pos.x * pixelsPerMeter + (0.5f * gc.getWidth()), 
                   -pos.y * pixelsPerMeter + (0.5f * gc.getHeight()));
        Fixture f = current.getFixtureList();
        while(f != null)
        {
            ShapeType type = f.getType();
            g.setColor(getColor(current));
            switch(type)
            {
                case POLYGON:
                {
                    PolygonShape shape = (PolygonShape)f.getShape();
                    Vec2[] verts = shape.getVertices();
                    int count = shape.getVertexCount();
                    Polygon p = new Polygon();
                    for(int i = 0; i < count; i++)
                    {
                        p.addPoint(verts[i].x, verts[i].y);
                    }
                    p.setCenterX(center.x);
                    p.setCenterY(center.y);
                    p = (Polygon)p.transform(Transform.createRotateTransform(current.getAngle() + MathUtils.PI, center.x, center.y));
                    p = (Polygon)p.transform(Transform.createScaleTransform(pixelsPerMeter, pixelsPerMeter));
                    g.draw(p);
                    break;
                }
                case CIRCLE:
                {
                    f.getShape();
                }
                default:
            }

            f = f.getNext();
        }
        g.popTransform();
        current = current.getNext();
    }
}

public Color getColor(Body b)
{
    Color c = new Color(1f, 1f, 1f);
    switch(b.m_type)
    {
    case DYNAMIC:
        if(b.isActive())
        {
            c = new Color(255, 123, 0);
        }
        else
        {
            c = new Color(99, 99, 99);
        }
        break;
    case KINEMATIC:
        break;
    case STATIC:
        c = new Color(111, 111, 111);
        break;
    default:
        break;

    }
    return c;
}
}

Any help with fixing the collisions would be greatly appreciated, and if you need any other code snippets I would be happy to provide them.

© Game Development or respective owner

Related posts about java

Related posts about collision-detection