package javara.world;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import javara.Player;
import javara.world.effects.Explosion;
import javara.world.environment.Sky;
import javara.world.goodies.Goody;
import javara.world.logical.Incarnator;
import javara.world.physical.Ground;
import javara.world.weapons.Weapon;
import com.jme3.asset.AssetManager;
import com.jme3.audio.AudioRenderer;
import com.jme3.bullet.PhysicsSpace;
import com.jme3.bullet.collision.PhysicsCollisionGroupListener;
import com.jme3.bullet.collision.PhysicsCollisionObject;
import com.jme3.light.AmbientLight;
import com.jme3.light.Light;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
public class World {
protected String author, name;
protected Node rootNode;
protected PhysicsSpace physicsSpace;
protected AssetManager assetManager;
protected Sky sky;
protected Ground ground;
protected AmbientLight ambientLight;
protected ArrayList<Incarnator> incarnators = new ArrayList<Incarnator>();
protected ArrayList<WorldObject> deadObjects = new ArrayList<WorldObject>();
protected HashMap<String, WorldObject> worldObjects = new HashMap<String, WorldObject>();
protected Player player;
protected AudioRenderer audioRenderer;
protected static ColorRGBA DEFAULT_SKY_COLOR = new ColorRGBA(0, 0, 0.15f, 1);
protected static ColorRGBA DEFAULT_HORIZON_COLOR = new ColorRGBA(0, 0, 0.8f, 1);
protected static ColorRGBA DEFAULT_AMBIENT_COLOR = new ColorRGBA(0.4f, 0.4f, 0.4f, 1);
protected static ColorRGBA DEFAULT_GROUND_COLOR = new ColorRGBA(0, 0, 0.15f, 1);
protected static float DEFAULT_HORIZON_SCALE = 0.1f;
private PhysicsCollisionGroupListener goodyListener = new PhysicsCollisionGroupListener() {
public boolean collide(PhysicsCollisionObject obj1, PhysicsCollisionObject obj2) {
Goody goody = null;
if (obj1.getUserObject() instanceof Goody) {
goody = (Goody)obj1.getUserObject();
}
else if (obj2.getUserObject() instanceof Goody) {
goody = (Goody)obj2.getUserObject();
}
if (goody != null) {
goody.goodyCollected();
}
return false;
}
};
private PhysicsCollisionGroupListener weaponListener = new PhysicsCollisionGroupListener() {
public boolean collide(PhysicsCollisionObject obj1, PhysicsCollisionObject obj2) {
Weapon weapon = null;
PhysicalObject other = null;
if (obj1.getUserObject() instanceof Weapon) {
weapon = (Weapon)obj1.getUserObject();
if (obj2.getUserObject() instanceof PhysicalObject)
other = (PhysicalObject)obj2.getUserObject();
}
else if (obj2.getUserObject() instanceof Weapon) {
weapon = (Weapon)obj2.getUserObject();
if (obj1.getUserObject() instanceof PhysicalObject)
other = (PhysicalObject)obj1.getUserObject();
}
if (weapon != null && other != null) {
Explosion exp = new Explosion(World.this, weapon.getLocalTranslation(), 2.5f, weapon.getColor());
World.this.addWorldObject(exp);
World.this.removeObject(weapon);
}
return false;
}
};
public World(Node rootNode, PhysicsSpace physicsSpace, AssetManager assetManager) {
this.rootNode = rootNode;
this.physicsSpace = physicsSpace;
this.assetManager = assetManager;
this.sky = new Sky(assetManager, DEFAULT_SKY_COLOR, DEFAULT_HORIZON_COLOR, DEFAULT_HORIZON_SCALE, DEFAULT_GROUND_COLOR);
this.ground = new Ground(assetManager, 1000.0f, DEFAULT_GROUND_COLOR);
addWorldObject(this.sky);
addWorldObject(this.ground);
ambientLight = new AmbientLight();
ambientLight.setColor(DEFAULT_AMBIENT_COLOR);
rootNode.addLight(ambientLight);
this.rootNode.setShadowMode(ShadowMode.Off);
// physicsSpace.enableDebug(assetManager);
// Weapon collisions.
physicsSpace.addCollisionGroupListener(weaponListener, PhysicsCollisionObject.COLLISION_GROUP_02);
// Goody collisions.
physicsSpace.addCollisionGroupListener(goodyListener, PhysicsCollisionObject.COLLISION_GROUP_03);
author = "unknown";
name = "unnamed";
}
public static Vector3f toCartesian(float azimuth, float elevation, float distance) {
float x, y, z;
Vector3f coordinates;
x = FastMath.sin(azimuth) * FastMath.cos(elevation);
y = FastMath.sin(elevation);
z = FastMath.cos(azimuth) * FastMath.cos(elevation);
coordinates = new Vector3f(x, y, z).mult(distance);
return coordinates;
}
public static float compassToRadians(float angle) {
// Positive degrees in navigation correspond to
// negative radians on the scene graph.
return angle * -FastMath.DEG_TO_RAD;
}
public AssetManager getAssetManager() {
return assetManager;
}
public ColorRGBA getDiffuse(ColorRGBA base) {
ColorRGBA color = base.clone();
color.interpolate(ColorRGBA.Black, 0.1f);
return base;
}
public ColorRGBA getAmbient(ColorRGBA base) {
ColorRGBA color = base.clone();
color.interpolate(ColorRGBA.Black, 0.5f);
return color;
}
public Material materialForColor(ColorRGBA color) {
Material mat;
if (color.getAlpha() < 1.0f) {
mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", color);
mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
}
else {
mat = new Material(assetManager, "Common/MatDefs/Light/Lighting.j3md");
mat.setFloat("Shininess", Float.MAX_VALUE);
mat.setBoolean("UseMaterialColors", true);
mat.setColor("Diffuse", getDiffuse(color));
mat.setColor("Ambient", getAmbient(color));
mat.setColor("Specular", ColorRGBA.Gray);
}
return mat;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAuthor(String author) {
this.author = author;
}
public String getAuthor() {
return author;
}
public void addWorldObject(WorldObject obj) {
worldObjects.put(obj.getIdentifier(), obj);
obj.attach(this);
show(obj);
}
public void removeObject(WorldObject obj) {
hide(obj);
deadObjects.add(obj);
}
public WorldObject getWorldObject(String name) {
return worldObjects.get(name);
}
public void show(WorldObject obj) {
if (obj instanceof VisibleObject) {
VisibleObject vo = (VisibleObject)obj;
Spatial vos = vo.getSpatial();
if (vos != null)
rootNode.attachChild(vos);
Light vol = vo.getLight();
if (vol != null)
rootNode.addLight(vol);
}
if (obj instanceof PhysicalObject) {
PhysicalObject po = (PhysicalObject)obj;
if (po.physics != null) {
physicsSpace.add(po.physics);
po.getCollisionObject().setUserObject(obj);
}
}
}
public void hide(WorldObject obj) {
if (obj instanceof VisibleObject) {
VisibleObject vo = (VisibleObject)obj;
Spatial vos = vo.getSpatial();
if (vos != null)
rootNode.detachChild(vos);
Light vol = vo.getLight();
if (vol != null)
rootNode.removeLight(vol);
}
if (obj instanceof PhysicalObject) {
PhysicalObject po = (PhysicalObject)obj;
if (po.physics != null) {
physicsSpace.remove(po.physics);
}
}
}
public Player getPlayer() {
return player;
}
public Ground getGround() {
return ground;
}
public Sky getSky() {
return sky;
}
public void setAmbientColor(ColorRGBA color) {
ambientLight.setColor(color);
}
public void setPlayer(Player p) {
this.player = p;
Vector3f celestialTranslation = player.getCameraNode().getWorldTranslation();
Vector3f groundTranslation = new Vector3f(celestialTranslation);
groundTranslation.y = 0;
sky.setLocalTranslation(celestialTranslation);
ground.setLocalTranslation(groundTranslation);
rootNode.attachChild(player.getHector().getHectorNode());
physicsSpace.add(player.getCharacterControl());
}
public void addIncarnator(Vector3f location, float angle, int order) {
incarnators.add(new Incarnator(location, angle, order));
}
public int getMaximumPopulation() {
return incarnators.size();
}
public AudioRenderer getAudioRenderer() {
return audioRenderer;
}
public Incarnator getIncarnator(int playerNumber) {
int idx = (int)(Math.random() * incarnators.size());
return incarnators.get(idx);
}
public void initialize() {
Iterator<Entry<String, WorldObject>> it = worldObjects.entrySet().iterator();
while (it.hasNext())
it.next().getValue().worldInitialized();
}
public void update(float tpf) {
if (!deadObjects.isEmpty()) {
for (WorldObject obj : deadObjects) {
worldObjects.remove(obj.getIdentifier());
obj.detach();
}
deadObjects.clear();
}
Vector3f celestialTranslation = player.getCameraNode().getWorldTranslation();
Vector3f groundTranslation = new Vector3f(celestialTranslation);
groundTranslation.y = 0;
sky.setLocalTranslation(celestialTranslation);
ground.setLocalTranslation(groundTranslation);
Iterator<Entry<String, WorldObject>> it = worldObjects.entrySet().iterator();
while (it.hasNext())
it.next().getValue().update(tpf);
}
public void setAudioRenderer(AudioRenderer audioRenderer) {
this.audioRenderer = audioRenderer;
}
}