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.
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.