2
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Can you try the Box2DDebugRenderer? \$\endgroup\$ – ThorinII Oct 23 '13 at 11:03
  • \$\begingroup\$ @Thorinll I switched to the Slick2DJBox2DDebugDraw class found here link and it worked fine. So I guess it must be something in my Render function? \$\endgroup\$ – andy Oct 23 '13 at 20:10
  • 3
    \$\begingroup\$ Nevermind, I fixed it. I just had to take out the p.setCenterX(center.x);p.setCenterY(center.y); out of the render function \$\endgroup\$ – andy Oct 23 '13 at 20:44
  • \$\begingroup\$ @andy Add it as an answer and accept it, so future readers can learn from it. \$\endgroup\$ – Anko Jul 8 '14 at 18:28
1
\$\begingroup\$

As per Andy's comment:

Nevermind, I fixed it. I just had to take out the

p.setCenterX(center.x);p.setCenterY(center.y);

out of the render function.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.