// AnimationPoint.java import javax.microedition.lcdui.Image; import javax.microedition.lcdui.Graphics; import java.util.Date; /** * This class stores animation details for a remote player to be animated * on the game screen between two points. All animation points share * image resources for their sprite since there may be many instances of * AnimationPoint. * * @author Jack Wootton * @version Last modified 11/03/05 **/ public class AnimationPoint { private static final int UP = 1; private static final int RIGHT = 2; private static final int DOWN = 3; private static final int LEFT = 4; private static final int NONE = 5; // The player needs to be painted but is not moving private static final int VELOCITY = 5; private static ImageSet playerImageSet; // Static! So that resource are shared between all AnimationPoints private int oldx, oldy; // Where they're from private int newx, newy; // Where they're going private int xInc, yInc; // Used to store velocity private int Xdirection, Ydirection; private String id; private Date lastPoll; // Used for timing out players so we don't paint disconnected players. private Sprite playerSprite; /** * AnimationPoint() used when a new remote player connects. * Note that to animate we need a start (x, y) and finish (x, y). * But since AnimationPoint() is used to add new remote players, we * only have one set of coordinates for them. So we set start and finish * to the same values, this way the player is painted but doesn't move. * * @param sx starting x coordinate * @param sy starting y coordinate * @param argId login ID of the remote player we're creating */ AnimationPoint(int sx, int sy, String argId) { newx = sx; newy = sy; oldx = sx; oldy = sy; id = argId; setDirection(); playerImageSet = new ImageSet(4); playerImageSet.addState(TheOthers.playerWalkingUp, 0); // state 0, up playerImageSet.addState(TheOthers.playerWalkingRight, 0); // state 1, right playerImageSet.addState(TheOthers.playerWalkingDown, 0); // state 2, down playerImageSet.addState(TheOthers.playerWalkingLeft, 0); // state 3, left playerSprite = new Sprite(playerImageSet, TheOthers.WALK_UP, 0); lastPoll = new Date(); } /** * updatePoints() used to update an existing remote players coordinates. * The previous destination (on last animation) now becomes the starting point. * The new coordinates are the new destination. Also updates the 'last polled' * time so the player doesn't timeout. * * @param x new x coordinate target * @param y new y coordinate target */ public void updatePoints(int x, int y) { oldx = newx; oldy = newy; newx = x; newy = y; lastPoll = new Date(); setDirection(); } /** * Return the object that stores the last polled time. * * @return last A Date object holding the most recent update time */ public Date getLastPoll() { return lastPoll; } /** * This method checks if the required movement for an AnimationPoint is * complete. We have to draw the Sprite whether it's moving or not * since we don't want the player to just disappear. * If the movement isn't complete then we also cycle through the Sprite * frames to create the walking effect. * * @param graphics The Graphics context of the off-screen-buffer that we draw onto */ public void paint(Graphics graphics) { playerSprite.draw(graphics, oldx - World.getViewX(), oldy - World.getViewY()); if (! ( isCompleteX() && isCompleteY() ) ) { playerSprite.cycle(); } recordMovement(); } /** * Used to update the AnimationPoint position after some movement has taken place. */ public void recordMovement() { if (! isCompleteY() ) { oldy += yInc; } if (! isCompleteX() ) { oldx += xInc; } } /** * Used to check if horizontal animation (in either direction) * is complete. Note we use >= rather == since the velocity means * that we may over shoot the target by a couple of pixels occasionally. * * @return boolean Have the starting coordinates reached their destination? */ public boolean isCompleteX() { switch (Xdirection) { case RIGHT: return oldx >= newx; case LEFT: return oldx <= newx; } return true; } /** * Used to check if vertical animation (in either direction) * is complete. Note we use >= rather == since the velocity means * that we may over shoot the target by a couple of pixels occasionally. * * @return boolean Have the starting coordinates reached their destination? */ public boolean isCompleteY() { switch (Ydirection) { case UP: return oldy <= newy; case DOWN: return oldy >= newy; } return true; } /** * Retrieves the Id of the remote player we're dealing with. * * @return id The Id of the player, playing the game */ public String getId() { return id; } /** * setDirection() calculates which way the remote player is moving * and sets the (x,y) increment values accordingly and also sets the global * direction value. The Sprite is also changed state depending on direction * of movement, for example: from an WALK_UP state to a WALK_RIGHT state. */ private void setDirection() { if (oldx > newx) { xInc = -VELOCITY; Xdirection = LEFT; playerSprite.setState(TheOthers.WALK_LEFT); } else if (oldx < newx) { xInc = VELOCITY; Xdirection = RIGHT; playerSprite.setState(TheOthers.WALK_RIGHT); } else { xInc = 0; Xdirection = NONE; } if (oldy > newy) { yInc = -VELOCITY; Ydirection = UP; playerSprite.setState(TheOthers.WALK_UP); } else if (oldy < newy) { yInc = VELOCITY; Ydirection = DOWN; playerSprite.setState(TheOthers.WALK_DOWN); } else { yInc = 0; Ydirection = NONE; } } }