package com.pointcliki.dizgruntled.logic;
import java.util.TreeSet;
import org.json.JSONException;
import org.json.JSONObject;
import org.newdawn.slick.Image;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
import com.pointcliki.core.AnimatedSprite;
import com.pointcliki.dizgruntled.GridLogic;
import com.pointcliki.dizgruntled.GruntzGame;
import com.pointcliki.dizgruntled.LogicProperty;
import com.pointcliki.dizgruntled.StringLogicProperty;
import com.pointcliki.dizgruntled.map.Map;
import com.pointcliki.dizgruntled.rez.MonolithANI;
import com.pointcliki.dizgruntled.rez.MonolithPID;
import com.pointcliki.dizgruntled.rez.MonolithWAV;
import com.pointcliki.dizgruntled.rez.MonolithWWD;
import com.pointcliki.event.Dispatcher;
import com.pointcliki.event.FrameEvent;
import com.pointcliki.event.Minion;
import com.pointcliki.event.PeriodicRogue;
import com.pointcliki.event.ProgressEvent;
import com.pointcliki.grid.GridCoordinate;
import com.pointcliki.movement.GridAlignedMovementOld;
import com.pointcliki.transition.LinearLerper;
public class RollingBall extends GridLogic {
/**
* Serial key
*/
private static final long serialVersionUID = 9102310743985049243L;
public static final Rectangle COLLISION_RECT = new Rectangle(5, 16, 22, 16);
private AnimatedSprite fAnimation;
private GridAlignedMovementOld<RollingBall> fMovement;
private String fSource;
private String fArea;
private int fSpeed;
private GridCoordinate fDir;
private RollingBallState fState;
private PeriodicRogue<RollingBall> fCollider;
@Override
public void importFromWWD(String logic, String image, String animation, byte[] data) {
fSnapToGrid = true;
super.importFromWWD(logic, image, animation, data);
fSource = "internal";
String[] s = image.split("/");
fArea = s[0].substring(0, 5);
String dir = s[3];
fDir = GridCoordinate.fromString(dir);
fSpeed = MonolithWWD.readSpeed(data);
if (fSpeed == 0) fSpeed = 1000;
setup();
}
@Override
public void importFromJSON(JSONObject object) {
fSnapToGrid = true;
super.importFromJSON(object);
fSource = object.optString("source");
fArea = object.optString("area", "AREA1");
fDir = GridCoordinate.fromString(object.optString("direction"));
fSpeed = object.optInt("speed", 1000);
if (fSpeed == 0) fSpeed = 1000;
setup();
}
@Override
public byte[] exportToWWD() {
// TODO Auto-generated method stub
return null;
}
@Override
public JSONObject exportToJSON() throws JSONException {
JSONObject o = super.exportToJSON();
o.putOpt("source", fSource);
if (fSource.equals("internal")) o.putOpt("area", fArea);
o.putOpt("direction", fDir.toName());
o.putOpt("speed", fSpeed);
return o;
}
private void setup() {
fState = RollingBallState.Rolling;
fMovement = new GridAlignedMovementOld<RollingBall>(this, new MovementMinion(), 0, 0) {
/**
* Serial key
*/
private static final long serialVersionUID = -1081595699813008927L;
@Override
public boolean canMove(GridCoordinate target) {
return true;
}
};
updateAnimation();
// Collision detector
fCollider = new PeriodicRogue<RollingBall>(this, null, 1, 0) {
/**
* Serial key
*/
private static final long serialVersionUID = -339957012805410993L;
@Override
public void run(RollingBall ball, long currentFrame) {
GridCoordinate xy = ball.getTile();
squashGrunt(gridManager().getFirstEntityOfTypeAt(xy, Grunt.class),xy);
for (String s: GridCoordinate.COMPASS)
squashGrunt(gridManager().getFirstEntityOfTypeAt(xy.add(GridCoordinate.fromString(s)), Grunt.class), xy);
for (String s: GridCoordinate.DIAGONAL_COMPASS)
squashGrunt(gridManager().getFirstEntityOfTypeAt(xy.add(GridCoordinate.fromString(s)), Grunt.class), xy);
}
public void squashGrunt(Grunt g, GridCoordinate xy) {
if (g == null) return;
Rectangle r = new Rectangle(Grunt.COLLISION_RECT.getX() - (fPosition.x - g.position().x), Grunt.COLLISION_RECT.getY() - (fPosition.y - g.position().y), Grunt.COLLISION_RECT.getWidth(), Grunt.COLLISION_RECT.getHeight());
if (r.intersects(COLLISION_RECT)) g.squash();
}
};
}
private void updateAnimation() {
AnimatedSprite sprite = MonolithANI.fromDirectory(fArea + "/IMAGEZ/ROLLINGBALL/" + fDir.toName());
if (fAnimation != null) fAnimation.cleanup();
fAnimation = sprite;
addChild(fAnimation);
fSpan = fAnimation.span();
if (fMap != null) fAnimation.start();
}
@Override
public void init(Map map) {
super.init(map);
fAnimation.start();
if (!map.editing()) {
fMovement.setup(fSpeed, new LinearLerper());
checkTile();
fMovement.move(fDir);
fCollider.begin();
}
}
private void checkTile() {
TreeSet<String> traits = fMap.traits(fTile);
String dieImage = null;
String dieAni = null;
String dieSound = null;
if (traits.contains("hole")) {
dieAni = fArea + "/ANIZ/ROLLINGBALLSINKHOLE";
dieImage = fArea + "/IMAGEZ/ROLLINGBALL/SINK";
dieSound = "GAME/SOUNDZ/ROLLINGBALLHOLE";
} else if (traits.contains("water")) {
dieAni = fArea + "/ANIZ/ROLLINGBALLSINKWATER";
dieImage = fArea + "/IMAGEZ/ROLLINGBALL/SINK";
dieSound = fArea + "/SOUNDZ/ROLLINGBALLWATER";
} else if (traits.contains("death")) {
dieAni = fArea + "/ANIZ/ROLLINGBALLSINKDEATH";
dieImage = fArea + "/IMAGEZ/ROLLINGBALL/SINK";
dieSound = fArea + "/SOUNDZ/ROLLINGBALLDEATH";
} else if (traits.contains("solid") || traits.contains("nogo")) {
dieAni = fArea + "/ANIZ/ROLLINGBALLEXPLOSION";
dieImage = fArea + "/IMAGEZ/ROLLINGBALL/EXPLOSION";
dieSound = fArea + "/SOUNDZ/ROLLINGBALLEXPLOSION";
}
if (dieImage != null) {
fState = RollingBallState.Dying;
fMovement.stop();
gridManager().removeObject(fTile, RollingBall.this);
AnimatedSprite sprite = new MonolithANI(GruntzGame.resourceManager().rez().file(dieAni, "ani"), dieImage).sprite();
if (fAnimation != null) fAnimation.cleanup();
fAnimation = sprite;
addChild(fAnimation);
fSpan = fAnimation.span();
if (fMap != null) fAnimation.start();
frameManager().queue(new Minion<FrameEvent>() {
public long run(Dispatcher<FrameEvent> dispatcher, String type, FrameEvent event) {
RollingBall.this.cleanup();
return Minion.FINISH;
};
}, fAnimation.frameDuration());
fCollider.cancel();
new MonolithWAV(GruntzGame.resourceManager().rez().file(dieSound, "ani")).sound().play();
return;
}
if (traits.contains("downArrow") && !fDir.equals(GridCoordinate.SOUTH)) {
fDir = GridCoordinate.SOUTH;
updateAnimation();
fMovement.move(GridCoordinate.SOUTH);
} else if (traits.contains("rightArrow") && !fDir.equals(GridCoordinate.EAST)) {
fDir = GridCoordinate.EAST;
updateAnimation();
fMovement.move(GridCoordinate.EAST);
} else if (traits.contains("leftArrow") && !fDir.equals(GridCoordinate.WEST)) {
fDir = GridCoordinate.WEST;
updateAnimation();
fMovement.move(GridCoordinate.WEST);
} else if (traits.contains("upArrow") && !fDir.equals(GridCoordinate.NORTH)) {
fDir = GridCoordinate.NORTH;
updateAnimation();
fMovement.move(GridCoordinate.NORTH);
}
}
private class MovementMinion extends Minion<ProgressEvent<RollingBall>> {
@Override
public long run(Dispatcher<ProgressEvent<RollingBall>> dispatcher, String type, ProgressEvent<RollingBall> event) {
if (type.equals(GridAlignedMovementOld.ON_BEGIN)) {
pressureManager().tileDepressure(fTile);
} else if (type.equals(GridAlignedMovementOld.ON_END) && fState == RollingBallState.Rolling) {
pressureManager().tilePressure(fTile);
checkTile();
}
return Minion.CONTINUE;
}
}
@Override
public void initProperties() {
StringLogicProperty area = new StringLogicProperty("area") {
@Override
public String description() {
return "The world which the ball comes from";
}
@Override
public String value() {
return fArea;
}
@Override
public String[] choices() {
return Map.WORLDS;
}
@Override
public void choice(int i) {
fArea = Map.AREAS[i];
updateAnimation();
}
};
StringLogicProperty direction = new StringLogicProperty("item") {
@Override
public String description() {
return "The initial direction of the ball";
}
@Override
public String value() {
return fDir.toName();
}
@Override
public String[] choices() {
return GridCoordinate.COMPASS;
}
@Override
public void choice(int i) {
fDir = GridCoordinate.fromString(GridCoordinate.COMPASS[i]);
updateAnimation();
}
};
StringLogicProperty speed = new StringLogicProperty("speed") {
@Override
public String description() {
return "The speed of the rolling ball";
}
@Override
public String value() {
return fSpeed + "";
}
@Override
public String[] choices() {
return null;
}
@Override
public void value(String val) {
try {
fSpeed = Integer.parseInt(val);
} catch (NumberFormatException e) {
System.err.println("Badly formed speed for RollingBall");
}
}
};
fProperties = new LogicProperty[] {area, direction, speed};
}
@Override
public void cleanup() {
fCollider.cleanup();
fCollider = null;
super.cleanup();
}
@Override
public String name() {
return "RollingBall";
}
public static AnimatedSprite editorIcon(JSONObject object) throws JSONException {
MonolithPID pid = GruntzGame.resourceManager().pid(object.optString("area") + "/IMAGEZ/ROLLINGBALL/EAST/FRAME001");
return new AnimatedSprite(new Image[] {pid.image()}, new Vector2f[] {pid.offset()});
}
public static enum RollingBallState {
Rolling, Dying
}
}