package it.marteEngine;
import it.marteEngine.entity.Entity;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.util.Log;
//TODO addAll() muss intern add() aufrufen, um korrekt nach flags in die listen einzusortieren
public class World extends BasicGameState {
public static final int BELOW = -1;
public static final int GAME = 0;
public static final int ABOVE = 1;
/** the game container this world belongs to */
public GameContainer container = null;
/** unique id for every world **/
public int id = 0;
/** width of the world, useful for horizontal wrapping entitites */
public int width = 0;
/** height of the world, useful for vertical wrapping entities */
public int height = 0;
/** internal list for entities **/
private List<Entity> entities = new ArrayList<Entity>();
private List<Entity> removable = new ArrayList<Entity>();
private List<Entity> addable = new ArrayList<Entity>();
/**
* two lists to contain objects that are rendered before and after camera
* stuff is rendered
*/
private List<Entity> belowCamera = new ArrayList<Entity>();
private List<Entity> aboveCamera = new ArrayList<Entity>();
/** current camera **/
public Camera camera;
public int renderedEntities;
/** available commands for world **/
protected Map<String, int[]> commands = new HashMap<String, int[]>();
public World(int id) {
this.id = id;
}
public World(int id, GameContainer container) {
this.id = id;
this.container = container;
}
public void init(GameContainer container, StateBasedGame game)
throws SlickException {
this.container = container;
if (width == 0)
width = container.getWidth();
if (height == 0)
height = container.getHeight();
// this.clear();
}
@Override
public void enter(GameContainer container, StateBasedGame game)
throws SlickException {
ME.world = this;
}
public void render(GameContainer container, StateBasedGame game, Graphics g)
throws SlickException {
renderedEntities = 0;
// first render entities below camera
for (Entity e : belowCamera) {
if (!e.visible)
continue;
renderEntity(e, g, container);
}
// center to camera position
if (camera != null)
g.translate(-camera.cameraX, -camera.cameraY);
// render entities
for (Entity e : entities) {
if (!e.visible)
continue; // next entity. this one stays invisible
if (camera != null) {
if (camera.contains(e)) {
renderEntity(e, g, container);
}
} else {
renderEntity(e, g, container);
}
}
// render particle system
if (ME.ps != null && ME.renderParticle) {
ME.ps.render();
}
if (ME.debugEnabled && camera != null) {
if (camera.getMoveRect() != null)
g.draw(camera.getMoveRect());
}
if (camera != null)
g.translate(camera.cameraX, camera.cameraY);
// finally render entities above camera
for (Entity e : aboveCamera) {
if (!e.visible)
continue;
renderEntity(e, g, container);
}
ME.render(container, game, g);
}
private void renderEntity(Entity e, Graphics g, GameContainer container)
throws SlickException {
renderedEntities++;
if (ME.debugEnabled && e.collidable) {
g.setColor(ME.borderColor);
Rectangle hitBox = new Rectangle(e.x + e.hitboxOffsetX, e.y
+ e.hitboxOffsetY, e.hitboxWidth, e.hitboxHeight);
g.draw(hitBox);
g.setColor(Color.white);
}
e.render(container, g);
}
public void update(GameContainer container, StateBasedGame game, int delta)
throws SlickException {
if (container == null)
throw new SlickException("no container set");
// store the current delta in ME for anyone who's interested in it.
ME.delta = delta;
// add new entities
if (addable.size() > 0) {
for (Entity entity : addable) {
entities.add(entity);
entity.addedToWorld();
}
addable.clear();
Collections.sort(entities);
}
// update entities
for (Entity e : belowCamera) {
e.updateAlarms(delta);
if (e.active)
e.update(container, delta);
}
for (Entity e : entities) {
e.updateAlarms(delta);
if (e.active)
e.update(container, delta);
// check for wrapping or out of world entities
e.checkWorldBoundaries();
}
for (Entity e : aboveCamera) {
e.updateAlarms(delta);
if (e.active)
e.update(container, delta);
// check for wrapping or out of world entities
// TODO: comment for a test
// e.checkWorldBoundaries();
}
// update particle system
if (ME.ps != null) {
ME.ps.update(delta);
}
// remove signed entities
for (Entity entity : removable) {
entities.remove(entity);
belowCamera.remove(entity);
aboveCamera.remove(entity);
entity.removedFromWorld();
}
removable.clear();
// update camera
if (camera != null) {
camera.update(container, delta);
}
ME.update(container, game, delta);
}
@Override
public int getID() {
return id;
}
/**
* Add entity to world and sort entity in z order
*
* @param e
* entity to add
*/
public void add(Entity e, int... flags) {
e.setWorld(this);
if (flags.length == 1) {
switch (flags[0]) {
case BELOW :
belowCamera.add(e);
break;
case GAME :
addable.add(e);
break;
case ABOVE :
aboveCamera.add(e);
break;
}
} else
addable.add(e);
}
public void addAll(Collection<Entity> e, int... flags) {
for (Entity entity : e) {
this.add(entity, flags);
}
}
/**
* @return List of entities currently in this world
*/
public List<Entity> getEntities() {
return entities;
}
/**
*
* @param type
* @return number of entities of the given type in this world
*/
public int getNrOfEntities(String type) {
if (entities.size() > 0) {
int number = 0;
for (Entity entity : entities) {
if (entity.isType(type))
number++;
}
return number;
}
return 0;
}
public List<Entity> getEntities(String type) {
if (entities.size() > 0) {
List<Entity> res = new ArrayList<Entity>();
for (Entity entity : entities) {
if (entity.isType(type))
res.add(entity);
}
return res;
}
return new ArrayList<Entity>();
}
/**
* @param entity
* to remove from game
* @return false if entity is already set to be remove
*/
public boolean remove(Entity entity) {
if (!removable.contains(entity)) {
return removable.add(entity);
}
return false;
}
/**
* @param name
* @return null if name is null or if no entity is found in game, entity
* otherwise
*/
public Entity find(String name) {
if (name == null)
return null;
for (Entity entity : entities) {
if (entity.name != null && entity.name.equalsIgnoreCase(name)) {
return entity;
}
}
// also look in addable list
for (Entity entity : addable) {
if (entity.name != null && entity.name.equalsIgnoreCase(name)) {
return entity;
}
}
// and look in aboveCamera and belowCamera list
for (Entity entity : aboveCamera) {
if (entity.name != null && entity.name.equalsIgnoreCase(name)) {
return entity;
}
}
for (Entity entity : belowCamera) {
if (entity.name != null && entity.name.equalsIgnoreCase(name)) {
return entity;
}
}
return null;
}
/**
* Remove all entities
*/
public void clear() {
for (Entity entity : entities) {
entity.removedFromWorld();
}
belowCamera.clear();
aboveCamera.clear();
entities.clear();
addable.clear();
removable.clear();
}
public void setCamera(Camera camera) {
this.camera = camera;
this.camera.setMyWorld(this);
}
public void setCameraOn(Entity entity) {
if (camera == null) {
this.setCamera(new Camera(this, entity, this.container.getWidth(),
this.container.getHeight()));
}
this.camera.setFollow(entity);
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public List<Entity> findEntityWithType(String type) {
if (type == null) {
Log.error("Parameter must be not null");
return new ArrayList<Entity>();
}
List<Entity> result = new ArrayList<Entity>();
for (Entity entity : entities) {
if (entity.isType(type)) {
result.add(entity);
}
}
return result;
}
/**
* @param x
* @param y
* @return true if an entity is already in position
*/
public boolean isEmpty(int x, int y, int depth) {
Rectangle rect;
for (Entity entity : entities) {
rect = new Rectangle(entity.x, entity.y, entity.width,
entity.height);
if (entity.depth == depth && rect.contains(x, y)) {
return false;
}
}
return true;
}
public Entity find(int x, int y) {
Rectangle rect;
for (Entity entity : entities) {
rect = new Rectangle(entity.x, entity.y, entity.width,
entity.height);
if (rect.contains(x, y)) {
return entity;
}
}
return null;
}
/**
* @return get number of entities in this world
*/
public int getCount() {
return entities.size();
}
/**
* define commands to handle inputs
*
* @param command
* name of the command
* @param keys
* keys or mouse input from {@link Input} class
*/
public void define(String command, int... keys) {
commands.put(command, keys);
}
/**
* Check if a command is down
*
* @param key
* @return
*/
public boolean check(String command) {
int[] checked = commands.get(command);
if (checked == null)
return false;
for (int i = 0; i < checked.length; i++) {
if (this.container.getInput().isKeyDown(checked[i])) {
return true;
} else if (checked[i] < 10) {
/**
* 10 is max number of button on a mouse
*
* @see Input
*/
if (this.container.getInput().isMousePressed(checked[i])) {
return true;
}
}
}
return false;
}
/**
* Check if a command is pressed
*
* @param key
* @return
*/
public boolean pressed(String command) {
int[] checked = commands.get(command);
if (checked == null)
return false;
for (int i = 0; i < checked.length; i++) {
if (this.container.getInput().isKeyPressed(checked[i])) {
return true;
} else if (checked[i] == Input.MOUSE_LEFT_BUTTON
|| checked[i] == Input.MOUSE_RIGHT_BUTTON) {
if (this.container.getInput().isMousePressed(checked[i])) {
return true;
}
}
}
return false;
}
}