/*
PlAr is Platform Arena: a 2D multiplayer shooting game
Copyright (c) 2010, Antonio Ragagnin <spocchio@gmail.com>
All rights reserved.
This file is licensed under the New BSD License.
*/
/**
* {@link Level} manage a set of classes {@link Element},
* interface these with the JBox2D {@link World}, and manage the collisions and the creations of the {@link Element}.
*
* @author Antonio Ragagnin
*
*/
package plar.core;
import java.util.ArrayList;
import java.util.List;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.Fixture;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.callbacks.*;
import org.jbox2d.dynamics.World;
import org.jbox2d.common.*;
import org.jbox2d.dynamics.contacts.*;
import org.jbox2d.dynamics.joints.Joint;
import org.jbox2d.collision.*;
import org.jbox2d.collision.shapes.PolygonShape;
public class Level implements Runnable {
/**
* the JBox2D world
*/
public World world;
/**
* the queue of {@link Player}s that will be recreated as soon as possible
*/
public List <ElementPlayer> respawnQueue;
/**
* the queue of {@link Element}s that have to be processed to be destroyed.
*/
public List<Element> destroyQueue;
/**
* fraction of time to evolve the World for each step.
* the evolution is managed by {@link Game}, but it is used by frames();
*/
public float Dt = 0.01f;
/**
* the size of the Level
*/
public Vec2 dim;
/**
* description of the level
*/
public String description;
/**
* gravity acceleration
*/
public Vec2 g;
/**
* counter of the elements inside the level, do not modify.
*/
public int n=0;
public Level() {
respawnQueue = new ArrayList<ElementPlayer> ();
destroyQueue = new ArrayList<Element> ();
dim = new Vec2(100, 60);
g = new Vec2(0, 10f);
description = "Level";
}
/**
* initialize the JBox2D features.
*/
public void Initialize() {
world.setDestructionListener(new DestructionListener() {
@Override
public void sayGoodbye(Joint joint) {
}
@Override
public void sayGoodbye(Fixture fixture) {
Object o = fixture.getBody().getUserData();
Common.info(2, "JBox2D.sayGoodbye() " + o);
}
});
world.setContactListener(new ContactListener() {
private void setCollision(Element e1, Element e2) {
if (e1.isRunnable) {
ArrayList<Element> cl1 = e1.collisionList;
if (cl1 == null)
cl1 = new ArrayList<Element>();
if (!cl1.contains(e2))
cl1.add(e2);
e1.collisionList = cl1;
}
}
private void unsetCollision(Element e1, Element e2) {
if (e1.isRunnable) {
ArrayList<Element> cl1 = e1.collisionList;
if (cl1 != null)
if (cl1.contains(e2))
cl1.remove(e2);
e1.collisionList = cl1;
}
}
public void beginContact(Contact contact) {
Contact point = contact;
//point.flagForFiltering();
if (point.isTouching()) {
// Common.info("collision at:"+point.position);
Element e1 = (Element) point.getFixtureA().getBody()
.getUserData();
Element e2 = (Element) point.getFixtureB().getBody()
.getUserData();
setCollision(e1, e2);
setCollision(e2, e1);
Common.info(4, "Collision detected: beetween " + e1 + " & "
+ e2);
}
}
public void endContact(Contact contact) {
Contact point = contact;
// point.flagForFiltering();
Element e1 = (Element) point.getFixtureA().getBody()
.getUserData();
Element e2 = (Element) point.getFixtureB().getBody()
.getUserData();
unsetCollision(e1, e2);
unsetCollision(e2, e1);
Common.info(4, "Collision finished from " + e1 + " and " + e2);
}
public void postSolve(Contact contact, ContactImpulse impulse) {
contact.flagForFiltering();
}
public void preSolve(Contact contact, Manifold oldManifold) {
}
});
}
/**
* add an element and initialize it
*/
public void addElement(Element e) {
e.level = this;
e.setBodyDef(e.bodydef);
Body b = world.createBody(e.bodydef);
e.body=b;
e.setBody(b);
n++;
e.id=n;
if (e.body == null)
Common.info(1, "Level: new Body is null: " + e + " " + e.body);
}
/**
* add an to the destroy queue.
*/
public void delElement(Element e) {
// Common.info(3, "Level.delElement(): deleting " + e.body.getUserData());
//e.body.setUserData(null);
destroyQueue.add(e);
}
public ArrayList<Element> getElementsByType(Common.ElementType s) {
ArrayList<Element> l = new ArrayList<Element>();
Body b = world.getBodyList();
int i = 0;
while (b != null) {
i++;
Element e = (Element) b.getUserData();
if (e != null && e.type == s)
l.add(e);
b = b.getNext();
}
return l;
}
public ArrayList<ElementPlayer> getPlayers() {
ArrayList<Element> al = getElementsByType(Common.ElementType.PLAYER);
ArrayList<ElementPlayer> ap = new ArrayList<ElementPlayer> ();
for(Element e:al)
{
ap.add((ElementPlayer)e);
}
return ap;
}
public ArrayList<Element> getRunnable() {
ArrayList<Element> l = new ArrayList<Element>();
Body b = world.getBodyList();
int i = 0;
while (b != null) {
i++;
Element e = (Element) b.getUserData();
if (e != null && e.isRunnable)
l.add(e);
b = b.getNext();
}
return l;
}
public ArrayList<Element> getScreen(Vec2 a, Vec2 b) {
AABB r = new AABB(new Vec2(a.x, a.y), new Vec2(a.x + b.x, a.y + b.y));
ArrayList<Element> al = new ArrayList<Element>();
ArrayList<Fixture> ss = Common.queryAABB(world, r);
try {
for (Fixture s : ss) {
al.add((Element) s.getBody().getUserData());
}
} catch (Exception ex) {
Common.info(1, "Level.getScreen() got exception:" + ex);
}
return al;
}
public void run() {
}
public int frames(float f) {
return (int) (f / (Dt));
}
public void reSpawn(ElementPlayer p) {
respawnQueue.add(p);
}
public String toString()
{ return description;
}
}