package pelletQuest.entities;
import java.util.ArrayList;
import pelletQuest.map.GameMap;
import org.newdawn.slick.*;
import org.newdawn.slick.geom.*;
import org.newdawn.slick.util.Log;
import pelletQuest.database.*;
public abstract class Entity {
protected GameMap map;
protected Rectangle box;
protected Voice voice;
protected int damage;
protected boolean canMoveOffWhenInvincible, canMoveThroughWhenInvincible;
protected boolean canLeaveZone;
protected boolean canLeaveMap;
protected Vector2f moveDirection;
protected Vector2f lastDirection;
public Entity (GameMap map, Rectangle boundingBox) {
this.map = map;
this.box = boundingBox;
this.voice = new Voice();
damage = 0;
this.lastDirection = this.moveDirection = new Vector2f(0,0);
canMoveOffWhenInvincible = false;
canMoveThroughWhenInvincible = false;
canLeaveZone = false;
canLeaveMap = false;
map.addEntity(this);
}
public void update (int delta) {
voice.update(delta);
}
public void renderVoice (Graphics g, int x, int y) {
voice.render(g, box.getCenterX(), box.getCenterY());
}
public void destroy() {
map.removeEntity(this);
}
public void say (String s) {
voice.say(s);
}
public void say (String s, int duration) {
voice.say(s, duration);
}
public Rectangle getBox() {
return box;
}
public GameMap getMap() {
return map;
}
public int getDamage() {
return damage;
}
public boolean canMoveOffWhenInvincible() {
return canMoveOffWhenInvincible;
}
public boolean canMoveThroughWhenInvincible() {
return canMoveThroughWhenInvincible;
}
public void setPosition (Vector2f newPos) {
box.setX(newPos.x);
box.setY(newPos.y);
}
public void setTilePosition (Vector2f newPos) {
box.setX(newPos.x*16);
box.setY(newPos.y*16);
}
public Vector2f getMoveDirection() {
return moveDirection;
}
public Vector2f getLastDirection() {
return lastDirection;
}
public void setMoveDirection (Vector2f move) {
moveDirection = move;
}
public void setLastDirection (Vector2f last) {
lastDirection = last;
}
public boolean canLeaveMap () {
return canLeaveMap;
}
public boolean teleport (String transition, int transitionTime, Vector2f targetPos, String targetName, Vector2f finalDirection) {
GameMap target = null;
try {
target = World.getMap(targetName);
} catch (Exception e){
Log.error(e);
return false;
}
if (!canLeaveZone && !target.getZone().equals(map.getZone())) {
return false;
}
ArrayList<Entity> collisions = Entity.getCollisionsAt(new Rectangle(targetPos.x*16, targetPos.y*16, box.getWidth(), box.getHeight()), target);
Entity solidCollide = null;
for (int i=0; i < collisions.size(); i++) {
if (collisions.get(i).isSolid()) {
solidCollide = collisions.get(i);
break;
}
}
if (solidCollide != null) {
return false;
}
//Teleporting...
map.removeEntity(this);
map = target;
map.addEntity(this);
setTilePosition(targetPos);
return true;
}
public ArrayList<Entity> getCollisions (Vector2f direction) {
ArrayList<Entity> result = new ArrayList<Entity>();
Rectangle movedBox = new Rectangle(box.getX()+direction.x, box.getY() + direction.y, box.getWidth(), box.getHeight());
ArrayList<Entity> ent = map.getEntities();
for (Entity e : ent) {
if (!e.equals(this)) {
if (movedBox.intersects(e.getBox())) {
result.add(e);
}
}
}
return result;
}
public boolean tryMove (Vector2f direction) {
if (!canMove(map, box, getPassableTerrains(), direction)) {
return false;
}
GameMap loggedMap = map;
Vector2f loggedPos = new Vector2f(box.getX(), box.getY());
ArrayList<Entity> ent = getCollisions(direction);
for (Entity e : ent) {
e.getBumped(this);
if (this.bump(e) && map.equals(loggedMap)) {
return false;
}
if (!map.equals(loggedMap)) { //If an onCollide event caused a teleport.
return true;
}
}
if (box.getX() == loggedPos.getX() && box.getY() == loggedPos.getY()) { //If an event caused the moving entity to move, we don't want to continute moving.
box.setX(box.getX()+direction.x);
box.setY(box.getY()+direction.y);
}
return true;
}
public boolean canMove (Vector2f direction) {
return canMove(map, box, getPassableTerrains(), direction);
}
public static boolean canMove (GameMap m, Rectangle rect, String[] passableTerrains, Vector2f direction) {
boolean result;
int x = (int)(rect.getX() + direction.x) / 16;
int y = (int)(rect.getY() + direction.y) / 16;
if (x >= 0 && x < m.getWidth() && y >= 0 && y < m.getHeight()) {
result = m.getPassableMap(passableTerrains)[y][x];
} else {
return false;
}
int w = (int)(rect.getX() + rect.getWidth() + direction.x) / 16;
int h = (int)(rect.getY() + rect.getHeight() + direction.y) / 16;
if (w >= 0 && w < m.getWidth() && h >= 0 && h < m.getHeight()) {
result = (m.getPassableMap(passableTerrains)[h][w] && result);
} else {
return false;
}
result = (m.getPassableMap(passableTerrains)[h][x] && result);
result = (m.getPassableMap(passableTerrains)[y][w] && result);
return result;
}
public void render (Graphics g, int x, int y) {}
public boolean bump(Entity other) { return other.isSolid(); }
public void getBumped (Entity other) {}
public void nextPhase() {}
public void setPhase(int phase) {}
public void onLeaveMap() {}
public void onEnterMap() {}
public void getHurt(int damage) {}
public abstract int getLayer();
public abstract String[] getPassableTerrains();
public abstract String getName();
public abstract boolean isSolid();
public static ArrayList<Entity> getCollisionsAt (Rectangle box, GameMap map) {
ArrayList<Entity> result = new ArrayList<Entity>();
ArrayList<Entity> ent = map.getEntities();
for (Entity e : ent) {
if (box.intersects(e.getBox())) {
result.add(e);
}
}
return result;
}
}