package com.shade.entities.treasure;
import org.lwjgl.opengl.GL11;
import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Sound;
import org.newdawn.slick.SpriteSheet;
import org.newdawn.slick.geom.Circle;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
import org.newdawn.slick.state.StateBasedGame;
import com.crash.Body;
import com.shade.base.Entity;
import com.shade.base.Level;
import com.shade.base.util.StateManager;
import com.shade.crash.CrashLevel;
import com.shade.crash.Repelable;
import com.shade.entities.mushroom.Mushroom;
import com.shade.entities.util.Sparkler;
import com.shade.lighting.LuminousEntity;
import com.shade.states.MasterState;
public class Treasure extends Mushroom implements Repelable {
protected static final float SPEED = 2.2f;
private static final float RADIUS = 12f;
public static final float MAX_SCALE = 1f;
private static final float MIN_SCALE = 0.3f;
public static final int SECONDS_OF_LIFE = 1700;
public static final float SCALE_INCREMENT = (MAX_SCALE - MIN_SCALE)
/ SECONDS_OF_LIFE;
private float spawn_x;
private float spawn_y;
private boolean open;
protected boolean collect;
private Sparkler sparky;
private float sunAngle;
protected enum States {
RETURNING, NORMAL, PICKED, COLLECTED, FLYING
};
protected enum Types {
POISON, NORMAL, GOOD, RARE
};
protected StateManager manager;
protected float scale;
private Types type;
private float luminosity;
protected CrashLevel level;
private static SpriteSheet chestOpen;
private static SpriteSheet chestClosed;
protected static Sound spawning, picked, poisonPicked, collected;
static {
try {
chestOpen = new SpriteSheet("entities/treasure/TreasureOpened.png",
64, 51);
chestClosed = new SpriteSheet(
"entities/treasure/TreasureClosed.png", 39, 50);
spawning = new Sound("entities/mushroom/sprout.ogg");
picked = new Sound("entities/mushroom/picked.ogg");
poisonPicked = new Sound("entities/mushroom/poison-picked.ogg");
collected = new Sound("entities/mushroom/collected.ogg");
} catch (SlickException e) {
e.printStackTrace();
}
}
public Treasure(int x, int y, int z) throws SlickException {
type = null;
scale = MAX_SCALE;
open = false;
collect = false;
initShape(x, y);
spawn_x = shape.getX();
spawn_y = shape.getY();
initResources();
initStates();
sparky = new Sparkler(this,3);
}
private void initShape(float x, float y) {
shape = new Rectangle(x, y, chestClosed.getWidth(), chestClosed
.getHeight());
shape.setCenterX(x);
shape.setCenterY(y);
}
public void open() {
open = true;
float centx = shape.getCenterX();
float centy = shape.getCenterY();
shape = new Circle(spawn_x, spawn_y, RADIUS * scale);
shape.setCenterX(centx);
shape.setCenterY(centy);
}
public void close() {
open = false;
float centx = shape.getCenterX();
float centy = shape.getCenterY();
shape = new Rectangle(spawn_x, spawn_y, chestClosed.getWidth(),
chestClosed.getHeight());
shape.setCenterX(centx);
shape.setCenterY(centy);
scale = MAX_SCALE;
}
private void initResources() throws SlickException {
// mushroom = sheet.getSprite(type.ordinal(), 0);
}
private void initStates() {
manager = new StateManager();
manager.add(new NormalTreasure(this));
manager.add(new PickedTreasure(this));
manager.add(new CollectedTreasure(this));
manager.add(new FlyingTreasure(this));
manager.add(new ReturningTreasure(this));
}
// HACK! TODO: KILL HACK!
public void scatter() {
manager.enter(Treasure.States.FLYING);
}
public void goHome() {
nudge((spawn_x+chestClosed.getWidth()/4 - getX()) / 25,
(spawn_y+chestClosed.getHeight()/4 - getY()) / 25);
}
protected void finish() {
detach();
}
protected void kill() {
detach();
level.remove(this);
}
protected void reset() {
manager.enter(Treasure.States.NORMAL);
}
protected boolean inShadows() {
return getLuminosity() < MasterState.SHADOW_THRESHOLD;
}
protected boolean tooBig() {
return scale > MAX_SCALE;
}
protected boolean tooSmall() {
return scale < MIN_SCALE;
}
protected void unsize() {
((Circle) shape).setRadius(RADIUS * scale);
}
protected void grow(int delta) {
scale += SCALE_INCREMENT * delta;
//resize();
}
protected void shrink(int delta) {
scale -= SCALE_INCREMENT * delta;
//resize();
}
public boolean isPoison() {
return false;
}
private void resize() {
if (open) {
float x = shape.getCenterX();
float y = shape.getCenterY();
((Circle) shape).setRadius(RADIUS * scale);
shape.setCenterX(x);
shape.setCenterY(y);
}
}
protected void draw(Graphics g) {
// TODO: I could make it so that I only draw the lid when the chest
// opens and get rid of the weird unaligned nonsense that incurs these
// messy constants.
if (open) {
chestOpen.draw(spawn_x, spawn_y);
if (!collect) {
float rmin = 0.1f;
float gmin = 0.1f;
float bmin = 0.1f;
//TODO:
GL11.glAlphaFunc(GL11.GL_GREATER,0f);
g.setColor(new Color(scale*(0.85f-rmin)+rmin,
scale*(0.9f-gmin)+gmin,
bmin*(1-scale),scale));
g.fillOval(getX(), getY(), RADIUS * 2, RADIUS * 2);
if (!inShadows()) {
g.setColor(new Color(1f, 1f, 1f));
// HACK! TODO: KILL HACK! MAGIC NUMBERS SRSLY?
float hack_x = 0.6f * scale;
float hack_y = 0.6f * scale;
g.fillOval((float) (getX() + RADIUS + Math.cos(sunAngle
+ Math.PI / 2)
* RADIUS * scale / 2)
+ hack_x, (float) (getY() + RADIUS + Math
.sin(sunAngle + Math.PI / 2)
* RADIUS * scale / 2)
+ hack_y, RADIUS * scale, RADIUS * scale);
}
sparky.animate(g);
GL11.glAlphaFunc(GL11.GL_GREATER,0.95f);
}
} else {
// chestOpen.draw(spawn_x-chestClosed.getWidth()/4+3,
// spawn_y-chestClosed.getHeight()/4-2);
// TODO: FIND OUT WHY ITS NOT DRAWING ALIGNED WITH THE DAMN PEARL
// THING.
chestClosed.draw(spawn_x, spawn_y);
sparky.animate(g);
// g.setColor(new Color(0.7f, 0.7f, 0f));
// g.fillOval(getXCenter(), getYCenter(), RADIUS * 2 * scale, RADIUS
// * 2 * scale);
}
}
public Shape castShadow(float direction, float depth) {
sunAngle = direction;
return null;
}
public int getZIndex() {
return 1;
}
public float getLuminosity() {
return luminosity;
}
public void setLuminosity(float l) {
luminosity = l;
}
public void addToLevel(Level<?> l) {
level = (CrashLevel) l;
}
public void removeFromLevel(Level<?> l) {
// do nothing
}
public float getValue() {
if (type == Types.POISON) {
return -scale;
}
if (type == Types.NORMAL) {
return scale;
}
if (type == Types.GOOD) {
return scale * 2;
}
if (type == Types.RARE) {
return scale * 10;
}
return 0;
}
public int getRole() {
return manager.getRole();
}
public void onCollision(Entity obstacle) {
manager.onCollision(obstacle);
}
public void render(StateBasedGame game, Graphics g) {
manager.render(game, g);
}
public void update(StateBasedGame game, int delta) {
manager.update(game, delta);
sparky.update(delta);
testAndWrap();
}
public int compareTo(LuminousEntity l) {
return getZIndex() - l.getZIndex();
}
public void repel(Body b) {
float velx = b.getXVelocity();
float vely = b.getYVelocity();
float playerx = b.getXCenter();
float playery = b.getYCenter();
// determine overlap
float right = playerx - b.getWidth() / 2
- (getXCenter() + getWidth() / 2);
float left = playerx + b.getWidth() / 2
- (getXCenter() - getWidth() / 2);
float top = playery - b.getHeight() / 2
- (getYCenter() + getHeight() / 2);
float bottom = playery + b.getHeight() / 2
- (getYCenter() - getHeight() / 2);
float minx = Math.min(Math.abs(right), Math.abs(left));
float miny = Math.min(Math.abs(top), Math.abs(bottom));
if (minx < miny) {
// if we move, move AWAY from the block.
if (Math.abs(playerx - getXCenter() - velx) < Math.abs(playerx
- getXCenter()))
velx = -velx;
b.nudge(-velx, 0);
} else {
if (Math.abs(playery - getYCenter() - vely) < Math.abs(playery
- getYCenter())) {
vely = -vely;
}
b.nudge(0, -vely);
}
}
}