package examples;
import jgame.*;
import java.awt.*;

/** A standard object that allows the player to move in 4 directions around a
 * maze. Typical application: pac-man.  This class only defines the move()
 * method; hit() and hit_bg() are not used.  Subclass it to customize.  To
 * customize move(), call super.move() somewhere inside your move method.  You
 * are not adviced to touch x, y, xdir, ydir, xspeed, yspeed.  It is assumed
 * the object is 1x1 tile in size, and the tileBBox is set to this.

 * <p>The public fields are the configuration fields which can be changed
 * at will during the object's lifetime.

 * <p>You can make movement stop by setting the stop_moving flag.  The player
 * will move on to the next aligned position, then halt until the flag is
 * cleared.  In some games, the player should freeze when the movement keys
 * are used for firing or special actions.

 */
public class StdMazePlayer extends JGObject {
	/* config */
	/** null indicates non-directional graphic */
	public String gfx_prefix=null;
	/** don't stop animating when player stops moving */
	public boolean continuous_anim;
	/** cid mask of tiles that block */
	public int block_mask;
	/** object's speed, overrides xspeed, yspeed. */
	public double speed;
	/** movement key */
	public int key_up,key_down,key_left,key_right;
	/** set to true to disable movement (for example, for firing) */
	public boolean stop_moving;
	/* state */
	int moving=0;
	/** When initialised, the object will snap to grid to the nearest free
	 * position.  The object's graphic can be made
	 * directional by setting is_directional.  This will add the suffix "u",
	 * "d", "l", or "r" to the graphic string to indicate the direction of
	 * movement.
	* @param x  position in pixels
	* @param y  position in pixels
	* @param graphic  prefix of graphic
	* @param is_directional  true = add direction suffix to graphic
	* @param continuous_anim  don't stop animating when player stops moving
	* @param block_mask  cid mask of tiles that block
	*/
	public StdMazePlayer(String name, double x,double y, int cid,
	String graphic, boolean is_directional, boolean continuous_anim,
	int block_mask, double speed,
	int key_up,int key_down, int key_left, int key_right) {
		super(name,false, x,y, cid, graphic);
		snapToGrid(eng.pfTileWidth(),eng.pfTileHeight());
		setTileBBox(0,0,eng.pfTileWidth(),eng.pfTileHeight());
		setDir(0,1);
		if (is_directional) gfx_prefix=graphic;
		this.continuous_anim=continuous_anim;
		this.key_up=key_up;
		this.key_down=key_down;
		this.key_left=key_left;
		this.key_right=key_right;
		this.block_mask=block_mask;
		this.speed=speed;
	}

	/** Moves the object around.  If you override this, be sure to call
	 * super.move() and don't touch x, y, xspeed, yspeed, xdir, ydir. */
	public void move() {
		boolean go_left=false;
		boolean go_right=false;
		boolean go_up=false;
		boolean go_down=false;
		if (!stop_moving) {
			go_left=eng.getKey(key_left);
			go_right=eng.getKey(key_right);
			go_up=eng.getKey(key_up);
			go_down=eng.getKey(key_down);
		}
		Point cen = getCenterTile();
		if (!isXAligned(speed/2.0) || !isYAligned(speed/2.0)) {
			moving=1;
			if (!continuous_anim) startAnim();
			// see if we should reverse direction in order to move towards
			// the opening closest to us
			if (isXAligned(speed/2.0)) {
				if (go_left && !(go_up||go_down)
				&& eng.getYAlignOfs(y)*ydir > 0
				&& !and(eng.getTileCid(cen,-1,0),block_mask)) { 
					ydir = -ydir;
				}
				if (go_right && !(go_up||go_down)
				&& eng.getYAlignOfs(y)*ydir > 0
				&& !and(eng.getTileCid(cen,1,0),block_mask)) { 
					ydir = -ydir;
				}
			}
			if (isYAligned(speed/2.0)) {
				if (go_up && !(go_left||go_right)
				&& eng.getXAlignOfs(x)*xdir > 0
				&& !and(eng.getTileCid(cen,0,-1),block_mask)) { 
					xdir = -xdir;
				}
				if (go_down && !(go_left||go_right)
				&& eng.getXAlignOfs(x)*xdir > 0
				&& !and(eng.getTileCid(cen,0,1),block_mask)) { 
					xdir = -xdir;
				}
			}
		} else { // ready to change direction
			if ((go_left||go_right)&&(go_up||go_down)) {
				// multiple directions at once -> alternate direction
				if (ydir!=0) {
					go_up=false;
					go_down=false;
				}
				if (xdir!=0) {
					go_left=false;
					go_right=false;
				}
			}
			snapToGrid(speed/2.0,speed/2.0);
			moving=0;
			if (!continuous_anim) stopAnim();
			if (go_up) {
				if (!and(eng.getTileCid(cen,0,-1),block_mask)) {
					setDir(0,-1);
					if (gfx_prefix!=null) setGraphic(gfx_prefix+"u");
				}
				moving=1;
			}
			if (go_down) {
				if (!and(eng.getTileCid(cen,0,1),block_mask)) {
					setDir(0,1);
					if (gfx_prefix!=null) setGraphic(gfx_prefix+"d");
				}
				moving=1;
			}
			if (go_left) {
				if (!and(eng.getTileCid(cen,-1,0),block_mask)) {
					setDir(-1,0);
					if (gfx_prefix!=null) setGraphic(gfx_prefix+"l");
				}
				moving=1;
			}
			if (go_right) {
				if (!and(eng.getTileCid(cen,1,0),block_mask)) {
					setDir(1,0);
					if (gfx_prefix!=null) setGraphic(gfx_prefix+"r");
				}
				moving=1;
			}
			if (and(eng.getTileCid(cen,xdir,ydir),block_mask)) moving=0;
		}
		setSpeed(moving==1  ? speed : 0);
	}
}
