package robombs.game.view;
import java.awt.Color;
import java.util.*;
import robombs.game.model.*;
import robombs.clientserver.*;
import robombs.game.*;
import com.threed.jpct.*;
import com.threed.jpct.util.*;
/**
* An Object3D that represents the actual level. This example "game" only has
* one level. If you want more, you'll have to implement a kind of level
* management yourself.
*/
public class Level {
static final private long serialVersionUID = 1L;
private final static int WALL_OCTREE_SIZE = 100;
private final static int FLOOR_OCTREE_SIZE = 100;
private final static int TOP_OCTREE_SIZE = 100;
private ParticleManager parMan = null;
private SmokeCloudManager smokeMan = null;
private ExplosionManager exploMan = null;
private CrateManager crateMan = null;
private ItemManager itemMan=null;
private DebrisManager debrisMan=null;
private LocalBombManager lbm=null;
private LevelPart floor = null;
private LevelPart top = null;
private LevelPart walls = null;
private LevelPart shadows = null;
private MapMask mask = null;
private int crateCnt=0;
private ClientEventQueue eventQueue=null;
public Level(String file, String set, World world, ClientEventQueue eventQueue, DecalManager decMan, boolean botUsage) throws Exception {
this.eventQueue=eventQueue;
exploMan = new ExplosionManager(world);
crateMan = new CrateManager(world);
itemMan=new ItemManager(world);
List<?> parts = LevelLoader.loadMap(file, set);
walls = (LevelPart) parts.get(0);
top = (LevelPart) parts.get(1);
floor = (LevelPart) parts.get(2);
mask = (MapMask) parts.get(3);
shadows=(LevelPart) parts.get(6);
shadows.enableLazyTransformations();
shadows.getMesh().compress();
shadows.build();
walls.enableLazyTransformations();
walls.getMesh().compress();
walls.build();
OcTree ocw = new OcTree(walls.getMesh(), WALL_OCTREE_SIZE, OcTree.MODE_OPTIMIZED);
ocw.setCollisionUse(OcTree.COLLISION_USE);
walls.setOcTree(ocw);
walls.setCollisionOptimization(Object3D.COLLISION_DETECTION_OPTIMIZED);
walls.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
if (!botUsage) {
parMan = new ParticleManager(world, Globals.enhancedGraphics?4000:2000);
smokeMan=new SmokeCloudManager(world, Globals.enhancedGraphics?1000:400);
debrisMan=new DebrisManager(world, Globals.enhancedGraphics?80:50);
top.enableLazyTransformations();
floor.enableLazyTransformations();
top.getMesh().compress();
floor.getMesh().compress();
top.build();
floor.build();
top.setLighting(Object3D.LIGHTING_NO_LIGHTS);
top.setAdditionalColor(new java.awt.Color(50,50,50));
OcTree ocf = new OcTree(floor.getMesh(), FLOOR_OCTREE_SIZE,
OcTree.MODE_OPTIMIZED);
OcTree oct = new OcTree(top.getMesh(), TOP_OCTREE_SIZE,
OcTree.MODE_OPTIMIZED);
OcTree ocs = new OcTree(shadows.getMesh(), FLOOR_OCTREE_SIZE,
OcTree.MODE_OPTIMIZED);
ocf.setCollisionUse(OcTree.COLLISION_USE);
oct.setCollisionUse(OcTree.COLLISION_USE);
floor.setOcTree(ocf);
top.setOcTree(oct);
shadows.setOcTree(ocs);
} else {
// Levels for bots don't need this.
top=null;
floor=null;
shadows=null;
parMan = new ParticleManager(world, 500); // Some particles are needed for the water...
smokeMan=new SmokeCloudManager(world, 0);
debrisMan=new DebrisManager(world, 0);
}
createCrates(decMan, botUsage);
}
public void setLocalBombManager(LocalBombManager lbm) {
this.lbm=lbm;
}
public LocalBombManager getLocalBombManager() {
return lbm;
}
public void makeReceiver(ShadowHelper sh) {
sh.addReceiver(floor);
sh.addReceiver(walls);
if (Globals.renderWallShadows) {
if (Globals.useShadowMesh) {
sh.addCaster(shadows);
} else {
sh.addCaster(walls);
}
}
}
public ClientEventQueue getEventQueue() {
return eventQueue;
}
public void optimizeForBotUsage() {
}
public ReflectionHelper enableReflections(FrameBuffer fb) {
ReflectionHelper refHelper=new ReflectionHelper(fb, floor, 1024, TextureInfo.MODE_MODULATE);
refHelper.setClippingPlaneOffset(1);
refHelper.setClearColor(Color.WHITE);
return refHelper;
}
public void addToWorld(World world) {
world.addObject(walls);
if (floor!=null) {
world.addObject(floor);
}
if (top!=null) {
world.addObject(top);
}
if (shadows!=null) {
world.addObject(shadows);
}
}
public void shadowPolygonsVisible(boolean vis) {
if (shadows!=null) {
if (vis) {
shadows.setVisibility(true);
} else {
shadows.setVisibility(false);
}
}
}
public void addCollisionListener(CollisionListener colLis) {
walls.addCollisionListener(colLis);
}
public int getWidth() {
return mask.getWidth();
}
public int getHeight() {
return mask.getHeight();
}
public SimpleVector getCenter() {
return floor.getTransformedCenter();
}
public Camera createAllViewingCamera(SimpleVector position, FrameBuffer buffer) {
Camera cam=new Camera();
try {
cam.setFOVLimits(0, 100);
cam.setFOV(1);
cam.setYFOV(1);
SimpleVector midPoint=floor.getTransformedCenter();
//midPoint.x=(position.x+midPoint.x*(getWidth()-6))/(getWidth()-5);
//midPoint.z=(position.z+midPoint.z*(getHeight()-6))/(getHeight()-5);
midPoint.x=(position.x+midPoint.x*10f)/11f;
midPoint.z=(position.z+midPoint.z*10f)/11f;
cam.setPosition(position);
cam.lookAt(midPoint);
float[] bb=walls.getMesh().getBoundingBox();
// minX, maxX, minY, maxY, minZ, maxZ
SimpleVector c1=new SimpleVector(bb[1],bb[3],bb[4]);
SimpleVector c2=new SimpleVector(bb[1],bb[3],bb[5]);
SimpleVector c3=new SimpleVector(bb[0],bb[3],bb[4]);
SimpleVector c4=new SimpleVector(bb[0],bb[3],bb[5]);
cam.copyBackToFront();
SimpleVector c1s=Interact2D.project3D2D(cam, buffer, c1);
SimpleVector c2s=Interact2D.project3D2D(cam, buffer, c2);
SimpleVector c3s=Interact2D.project3D2D(cam, buffer, c3);
SimpleVector c4s=Interact2D.project3D2D(cam, buffer, c4);
//System.out.println(c1s.x+"/"+c1s.y+ " - "+ c2s.x+"/"+c2s.y+ " - "+c3s.x+"/"+c3s.y+ " - "+c4s.x+"/"+c4s.y);
float ymin=999999;
float ymax=-999999;
float xmin=999999;
float xmax=-999999;
if (c1s!=null) {
if (c1s.x<xmin) xmin=c1s.x;
if (c1s.x>xmax) xmax=c1s.x;
if (c1s.y<ymin) ymin=c1s.y;
if (c1s.y>ymax) ymax=c1s.y;
}
if (c2s!=null) {
if (c2s.x<xmin) xmin=c2s.x;
if (c2s.x>xmax) xmax=c2s.x;
if (c2s.y<ymin) ymin=c2s.y;
if (c2s.y>ymax) ymax=c2s.y;
}
if (c3s!=null) {
if (c3s.x<xmin) xmin=c3s.x;
if (c3s.x>xmax) xmax=c3s.x;
if (c3s.y<ymin) ymin=c3s.y;
if (c3s.y>ymax) ymax=c3s.y;
}
if (c4s!=null) {
if (c4s.x<xmin) xmin=c4s.x;
if (c4s.x>xmax) xmax=c4s.x;
if (c4s.y<ymin) ymin=c4s.y;
if (c4s.y>ymax) ymax=c4s.y;
}
xmin=(buffer.getOutputWidth()/2)-xmin;
xmax=xmax-(buffer.getOutputWidth()/2);
ymin=(buffer.getOutputHeight()/2)-ymin;
ymax=ymax-(buffer.getOutputHeight()/2);
float xd=xmin;
if (xmax>xd) {
xd=xmax;
}
float yd=ymin;
if (ymax>yd) {
yd=ymax;
}
float xfov=xd/(buffer.getOutputWidth()/2);
float yfov=yd/(buffer.getOutputHeight()/2);
cam.setFOV(xfov);
cam.setYFOV(yfov);
} catch(Exception e) {
e.printStackTrace();
}
return cam;
}
/**
* Returns a simple checksum to ensure (well, not really...) that all
* clients are using the same level. This has to be improved for "real"
* games to prevent cheating. For this example, it's fine the way it is.
*
* @return int the checksum
*/
public int getChecksum() {
return walls.getMesh().getTriangleCount()
* walls.getMesh().getUniqueVertexCount()
+ walls.getMesh().getVertexCount();
}
/**
* Returns the particle emitter if enabled. If not, it returns null.
*
* @return ParticleManager the emitter or null
*/
public ParticleManager getParticleManager() {
return parMan;
}
public SmokeCloudManager getSmokeCloudManager() {
return smokeMan;
}
public ExplosionManager getExplosionManager() {
return exploMan;
}
public CrateManager getCrateManager() {
return crateMan;
}
public ItemManager getItemManager() {
return itemMan;
}
public DebrisManager getDebrisManager() {
return debrisMan;
}
public SimpleVector[] getSpawnPoints() {
SimpleVector[] sorty=new SimpleVector[9];
List<SimpleVector> points=new ArrayList<SimpleVector>();
int x = mask.getWidth();
int y = mask.getHeight();
for (int i = 0; i < x; i++) {
for (int p = 0; p < y; p++) {
int c=mask.getMaskAt(i, p);
if (c>=10049 && c<=10057) {
SimpleVector np=new GridPosition(i,p).convertTo3D();
np.y=-10;
sorty[c-10049]=np;
mask.setMaskAt(i,p,MapMask.FLOOR);
}
}
}
for (SimpleVector s:sorty) {
if (s!=null) {
points.add(s);
}
}
return points.toArray(new SimpleVector[points.size()]);
}
public void populate(LocalBombManager bombMan, SimpleClient client, World world, ClientEventQueue eventQueue) {
int x = mask.getWidth();
int y = mask.getHeight();
for (int i = 0; i < x; i++) {
for (int p = 0; p < y; p++) {
if (!mask.isObstacle(i, p) && !mask.isBlocked(i,p)) {
LocalPlayerObject lop = new LocalPlayerObject();
SimpleVector pos = new GridPosition(i, p).convertTo3D();
pos.y = -10f;
lop.setPosition(pos);
bombMan.addBomb(client, lop, world, eventQueue);
}
}
}
}
public void populateSparse(LocalBombManager bombMan, SimpleClient client, World world, ClientEventQueue eventQueue) {
int i = (int)((float)mask.getWidth()*Math.random());
int p = (int)((float)mask.getHeight()*Math.random());
if (!mask.isObstacle(i, p) && !mask.isBlocked(i,p)) {
LocalPlayerObject lop = new LocalPlayerObject();
SimpleVector pos = new GridPosition(i, p).convertTo3D();
pos.y = -10f;
lop.setPosition(pos);
bombMan.addBomb(client, lop, world, eventQueue);
}
}
public MapMask getMask() {
return mask;
}
public boolean createItem(SimpleVector position,LocalObject lob, ShadowHelper sh) {
GridPosition pos=mask.getGrid(position.x, position.z);
int field=mask.getMaskAt(pos);
if (field==MapMask.BOMB_ITEM) {
itemMan.addItem(position, lob.getObjectID(), Types.BOMB_ITEM, sh,eventQueue);
return true;
}
if (field==MapMask.FIREPOWER_ITEM) {
itemMan.addItem(position, lob.getObjectID(), Types.FIREPOWER_ITEM, sh,eventQueue);
return true;
}
if (field==MapMask.KICK_ITEM) {
itemMan.addItem(position, lob.getObjectID(), Types.KICK_ITEM, sh,eventQueue);
return true;
}
if (field==MapMask.DISEASE_ITEM) {
itemMan.addItem(position, lob.getObjectID(), Types.DISEASE_ITEM, sh,eventQueue);
return true;
}
return false;
}
public boolean wasCollisionParticipant() {
return walls.wasTargetOfLastCollision();
}
private void createCrates(DecalManager decMan, boolean botUsage) {
int x = mask.getWidth();
int y = mask.getHeight();
for (int i = 0; i < x; i++) {
for (int p = 0; p < y; p++) {
int field=mask.getMaskAt(i, p);
if (field==MapMask.CRATE || MapMask.isItem(field)) {
SimpleVector pos = new GridPosition(i, p).convertTo3D();
crateMan.addCrate(pos, crateCnt, decMan, eventQueue, botUsage);
crateCnt++;
}
}
}
}
}