/**
* Copyright 2011 The ForPlay Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package forplay.sample.peas.core;
import org.jbox2d.callbacks.ContactImpulse;
import org.jbox2d.callbacks.ContactListener;
import org.jbox2d.callbacks.DebugDraw;
import org.jbox2d.collision.Manifold;
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.World;
import org.jbox2d.dynamics.contacts.Contact;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
import static forplay.core.ForPlay.graphics;
import forplay.core.CanvasLayer;
import forplay.core.DebugDrawBox2D;
import forplay.core.GroupLayer;
import forplay.sample.peas.core.entities.Entity;
import forplay.sample.peas.core.entities.PhysicsEntity;
public class PeaWorld implements ContactListener {
public GroupLayer staticLayerBack;
public GroupLayer dynamicLayer;
public GroupLayer staticLayerFront;
// size of world
private static int width = 24;
private static int height = 18;
// box2d object containing physics world
protected World world;
private List<Entity> entities = new ArrayList<Entity>(0);
private HashMap<Body, PhysicsEntity> bodyEntityLUT = new HashMap<Body, PhysicsEntity>();
private Stack<Contact> contacts = new Stack<Contact>();
private static boolean showDebugDraw = false;
private DebugDrawBox2D debugDraw;
public PeaWorld(GroupLayer scaledLayer) {
staticLayerBack = graphics().createGroupLayer();
scaledLayer.add(staticLayerBack);
dynamicLayer = graphics().createGroupLayer();
scaledLayer.add(dynamicLayer);
staticLayerFront = graphics().createGroupLayer();
scaledLayer.add(staticLayerFront);
// create the physics world
Vec2 gravity = new Vec2(0.0f, 10.0f);
world = new World(gravity, true);
world.setWarmStarting(true);
world.setAutoClearForces(true);
world.setContactListener(this);
// create the ground
Body ground = world.createBody(new BodyDef());
PolygonShape groundShape = new PolygonShape();
groundShape.setAsEdge(new Vec2(0, height), new Vec2(width, height));
ground.createFixture(groundShape, 0.0f);
// create the walls
Body wallLeft = world.createBody(new BodyDef());
PolygonShape wallLeftShape = new PolygonShape();
wallLeftShape.setAsEdge(new Vec2(0, 0), new Vec2(0, height));
wallLeft.createFixture(wallLeftShape, 0.0f);
Body wallRight = world.createBody(new BodyDef());
PolygonShape wallRightShape = new PolygonShape();
wallRightShape.setAsEdge(new Vec2(width, 0), new Vec2(width, height));
wallRight.createFixture(wallRightShape, 0.0f);
if (showDebugDraw) {
CanvasLayer canvasLayer =
graphics().createCanvasLayer((int) (width / Peas.physUnitPerScreenUnit),
(int) (height / Peas.physUnitPerScreenUnit));
graphics().rootLayer().add(canvasLayer);
debugDraw = new DebugDrawBox2D();
debugDraw.setCanvas(canvasLayer);
debugDraw.setFlipY(false);
debugDraw.setStrokeAlpha(150);
debugDraw.setFillAlpha(75);
debugDraw.setStrokeWidth(2.0f);
debugDraw.setFlags(DebugDraw.e_shapeBit | DebugDraw.e_jointBit | DebugDraw.e_aabbBit);
debugDraw.setCamera(0, 0, 1f / Peas.physUnitPerScreenUnit);
world.setDebugDraw(debugDraw);
}
}
public void update(float delta) {
for (Entity e : entities) {
e.update(delta);
}
// the step delta is fixed so box2d isn't affected by framerate
world.step(0.033f, 10, 10);
processContacts();
}
public void paint(float delta) {
if (showDebugDraw) {
debugDraw.getCanvas().canvas().clear();
world.drawDebugData();
}
for (Entity e : entities) {
e.paint(delta);
}
}
public void add(Entity entity) {
entities.add(entity);
if (entity instanceof PhysicsEntity) {
PhysicsEntity physicsEntity = (PhysicsEntity) entity;
bodyEntityLUT.put(physicsEntity.getBody(), physicsEntity);
}
}
// handle contacts out of physics loop
public void processContacts() {
while (!contacts.isEmpty()) {
Contact contact = contacts.pop();
// handle collision
PhysicsEntity entityA = bodyEntityLUT.get(contact.m_fixtureA.m_body);
PhysicsEntity entityB = bodyEntityLUT.get(contact.m_fixtureB.m_body);
if (entityA != null && entityB != null) {
if (entityA instanceof PhysicsEntity.HasContactListener) {
((PhysicsEntity.HasContactListener) entityA).contact(entityB);
}
if (entityB instanceof PhysicsEntity.HasContactListener) {
((PhysicsEntity.HasContactListener) entityB).contact(entityA);
}
}
}
}
// Box2d's begin contact
@Override
public void beginContact(Contact contact) {
contacts.push(contact);
}
// Box2d's end contact
@Override
public void endContact(Contact contact) {
}
// Box2d's pre solve
@Override
public void preSolve(Contact contact, Manifold oldManifold) {
}
// Box2d's post solve
@Override
public void postSolve(Contact contact, ContactImpulse impulse) {
}
}