/**
*
*/
package com.javaxyq.widget.impl;
import java.awt.Graphics;
import java.awt.Point;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.javaxyq.core.SpriteFactory;
import com.javaxyq.widget.Character;
import com.javaxyq.widget.CharacterActions;
import com.javaxyq.widget.Directions;
import com.javaxyq.widget.Sprite;
/**
* @author gongdewei
* @date 2011-7-24 create
*/
public class CharacterImpl implements Character {
private static final Logger log = Logger.getLogger(CharacterImpl.class.getName());
private Object LocationLock = new Object();
private Object UpdateLock = new Object();
private String id;
private Sprite sprite;
private int direction;
private int x;
private int y;
/** �Ƿ����ƶ� */
private boolean moving;
/** �ƶ��ٶ� */
private int speed;
/** ��ɫ���� */
private String action = CharacterActions.STAND;
/** �Ƿ�����ƶ� */
private boolean moveon;
private LinkedList<Point> footmark;
private LinkedList<Point> track;
private long elapsedTime;
private int lastFrameIndex;
public CharacterImpl(String id) {
this.id = id;
footmark = new LinkedList<Point>();
track = new LinkedList<Point>();
}
@Override
public void initialize() {
//checkCharacter(id);
refresh();
}
synchronized public void refresh() {
String resId = id+"-"+action;
if(sprite == null || !sprite.getResId().equals(resId)) {
sprite = SpriteFactory.getSprite(id, action);
}
if(sprite != null && sprite.getDirection() != direction) {
sprite.setDirection(direction);
sprite.resetFrames();
}
}
@Override
public String getId() {
return id;
}
@Override
public boolean isReady() {
return (sprite!=null);
}
@Override
public Point getLocation() {
synchronized (LocationLock) {
return new Point(x, y);
}
}
@Override
public void moveBy(int x, int y) {
synchronized (LocationLock) {
this.x += x;
this.y += y;
saveTrack();
}
}
@Override
public void moveTo(int x, int y) {
synchronized (LocationLock) {
this.x = x;
this.y = y;
saveFootmark();
}
}
@Override
synchronized public void action(String key) {
// checkAction(key);
this.action = key;
this.moving = false;
this.speed = 0;
refresh();
}
@Override
synchronized public void rush() {
this.action = CharacterActions.RUSHA;
this.moving = true;
this.speed = 2;
refresh();
saveFootmark();
}
@Override
synchronized public void stand() {
this.action = CharacterActions.STAND;
this.moving = false;
this.speed = 0;
refresh();
saveFootmark();
}
@Override
synchronized public void turn(int direction) {
if(direction > 7) {direction %= 8; }
if(direction <0 ) {direction += 8; }
this.direction = direction;
refresh();
}
@Override
public void turn() {
if(this.direction < 4) {
turn(this.direction + 4);
}else if(this.direction == 7){
turn(0);
}else {
turn(this.direction - 3);
}
}
public int getDirection() {
return direction;
}
@Override
synchronized public void walk() {
this.action = CharacterActions.WALK;
this.moving = true;
this.speed = 1;
refresh();
saveFootmark();
}
@Override
synchronized public void draw(Graphics g) {
if(isReady()) {
this.sprite.draw(g, x, y);
}
}
@Override
synchronized public void update(long elapsedTime) {
updateAnimation(elapsedTime);
updateMovement(elapsedTime);
}
private void updateMovement(long elapsedTime) {
checkMovement();
if(moving && speed>0) {
int dx=0, dy=0;
double unit = 2;
double q = 0.7;
switch (this.direction) {
case Directions.LEFT:
dx = - (int) (unit * this.speed);
break;
case Directions.UP_LEFT:
dx = - (int) (unit * this.speed * q);
dy = (int) (unit * this.speed * q);
break;
case Directions.UP:
dy = (int) (unit * this.speed);
break;
case Directions.UP_RIGHT:
dx = (int) (unit * this.speed * q);
dy = (int) (unit * this.speed * q);
break;
case Directions.RIGHT:
dx = (int) (unit * this.speed);
break;
case Directions.DOWN_RIGHT:
dx = (int) (unit * this.speed * q);
dy = - (int) (unit * this.speed * q);
break;
case Directions.DOWN:
dy = - (int) (unit * this.speed * q);
break;
case Directions.DOWN_LEFT:
dx = - (int) (unit * this.speed * q);
dy = - (int) (unit * this.speed * q);
break;
default:
break;
}
this.moveBy(dx, -dy);
}
}
private void checkMovement() {
Point last = getLastFootmark();
double distance = last.distance(getLocation());
if(distance >= 20) {
moveArrived();
}
}
private void moveArrived() {
saveFootmark();
if(!isMoveOn()) {
moving = false;
stand();
}
}
public boolean isMoveOn() {
return moveon;
}
public void setMoveon(boolean moveon) {
this.moveon = moveon;
}
private void updateAnimation(long elapsedTime) {
if(isReady()) {
this.sprite.update(elapsedTime);
if(moving && log.isLoggable(Level.INFO)) {
int findex = this.sprite.getCurrAnimation().getIndex();
if(lastFrameIndex != findex) {
//log.info("frame: "+this.direction+ " - "+findex);
}
lastFrameIndex = findex;
}
}
}
private void saveTrack() {
Point last = track.size()>0? track.getLast(): null;
Point p = new Point(x, y);
if(last==null || !last.equals(p)) {
track.add(new Point(x, y));
//log.info("Track: ("+x+","+y+")");
}
}
private void saveFootmark() {
Point last = getLastFootmark();
Point p = new Point(x, y);
if(last==null || !last.equals(p)) {
track.add(p);
footmark.add(p);
log.info("Footmark: ("+x+","+y+")");
}
}
private Point getLastFootmark() {
return footmark.size()>0? footmark.getLast(): null;
}
}