import java.awt.Component; import java.awt.Graphics2D; /** * Base class of Wedge Dude and Ghost classes. Provides common drawing and * model maintenance functions. */ public abstract class Player { public static final long MOVE_TIME = 250L; /** Current or target grid space, x-coordinate */ private int gridX; /** Current or target grid space, y-coordinate */ private int gridY; /** Facing direction */ private Direction direction; /** Origin grid space, x-coordinate */ private int fromGridX; /** Origin grid space, y-coordinate */ private int fromGridY; /** Pixel location of the center of the wedge, x-coordinate */ private int pixelX; /** Pixel location of the center of the wedge, y-coordinate */ private int pixelY; /** Next scheduled move, executed after the current move is complete */ private Direction nextMove; /** Time last move operation started, zero when no move is in progress */ private long moveReferenceTime; public Player(int gridX, int gridY, Direction direction) { this.gridX = gridX; this.fromGridX = gridX; this.gridY = gridY; this.fromGridY = gridY; this.direction = direction; } public int getGridX() { return this.gridX; } public void setGridX(int gridX) { this.gridX = gridX; } public int getGridY() { return this.gridY; } public void setGridY(int gridY) { this.gridY = gridY; } public int getFromGridX() { return this.fromGridX; } public int getFromGridY() { return this.fromGridY; } public Direction getDirection() { return this.direction; } public void setDirection(Direction direction) { this.direction = direction; } public int getPixelX() { return this.pixelX; } public int getPixelY() { return this.pixelY; } public Location getLocation() { return new Location(this.gridX, this.gridY, null); } public synchronized void move(WedgeWorld world, Direction direction) { while (this.nextMove != null) { try { wait(); } catch (InterruptedException ie) { } // Do nothing } int destX = getGridX() + direction.getDeltaX(); int destY = getGridY() + direction.getDeltaY(); Space s = world.getContents(destX, destY); if (s != Space.WALL) processMove(direction); while (this.nextMove != null) { try { wait(); } catch (InterruptedException ie) { } // Do nothing } } protected synchronized void processMove(Direction direction) { if (getGridX() != getFromGridX() || getGridY() != getFromGridY()) this.nextMove = direction; else { setGridX(getGridX() + direction.getDeltaX()); setGridY(getGridY() + direction.getDeltaY()); setDirection(direction); long now = System.currentTimeMillis(); if (this.moveReferenceTime == 0) this.moveReferenceTime = now; else while (this.moveReferenceTime + MOVE_TIME <= now) this.moveReferenceTime += MOVE_TIME; notifyAll(); } } public synchronized void updateModel() { long now = System.currentTimeMillis(); // Performing a move if (this.moveReferenceTime > 0 || this.pixelX == 0) { double phase = Math.min((now - this.moveReferenceTime) / (double)MOVE_TIME, 1.0); double gx = this.gridX + (this.fromGridX - this.gridX) * (1.0 - phase); double gy = this.gridY + (this.fromGridY - this.gridY) * (1.0 - phase); int halfCell = WedgeWorld.CELL_SIZE / 2; this.pixelX = (int)(halfCell + gx * WedgeWorld.CELL_SIZE); this.pixelY = (int)(halfCell + gy * WedgeWorld.CELL_SIZE); // Process transition if (phase == 1.0) { this.fromGridX = this.gridX; this.fromGridY = this.gridY; if (this.nextMove == null) this.moveReferenceTime = 0; else { Direction d = this.nextMove; this.nextMove = null; processMove(d); } } } } public abstract void draw(Graphics2D g2d, Component c); }