import java.awt.Color; import java.awt.Component; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; /** * Implementation of the Ghost UI. */ public class Ghost extends Player { public static final int RADIUS = 17; public static final int HEIGHT = 38; public static final int EYE_OFFSET = 4; public static final int EYE_SIZE = 5; public static final int FRINGE_DEPTH = 7; public static final int FRINGE_WIDTH = 6; public static final int DRAW_BOUNDARY = 10; private GhostBrain brain; private int phase; public Ghost(GhostBrain brain) { this(10, 4, brain); } public Ghost(int gridX, int gridY, GhostBrain brain) { super(gridX, gridY, null); this.brain = brain; } public GhostBrain getBrain() { return this.brain; } protected synchronized void processMove(Direction direction) { if (getDirection() == null || getDirection().getOpposite() != direction) super.processMove(direction); } public synchronized void updateModel() { super.updateModel(); long now = System.currentTimeMillis(); int cycle = (int)(now % 500L); this.phase = cycle / 250; } public Rectangle getBoundingBox() { int halfCell = WedgeWorld.CELL_SIZE / 2; return new Rectangle(getPixelX() - halfCell - DRAW_BOUNDARY / 2, getPixelY() - halfCell - DRAW_BOUNDARY / 2, 2 * halfCell + DRAW_BOUNDARY, 2 * halfCell + DRAW_BOUNDARY); } public void draw(Graphics2D g2d, Component c) { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setColor(this.brain.getColor().getColor()); double focusY = getPixelY() - HEIGHT / 2 + RADIUS; GeneralPath p = new GeneralPath(); p.moveTo((float)(getPixelX() - RADIUS), (float)focusY); p.quadTo((float)(getPixelX() - RADIUS), (float)(focusY - RADIUS), (float)getPixelX(), (float)(focusY - RADIUS)); p.quadTo((float)(getPixelX() + RADIUS), (float)(focusY - RADIUS), (float)(getPixelX() + RADIUS), (float)focusY); int phaseAdjust = this.phase * FRINGE_DEPTH; p.lineTo((float)(getPixelX() + RADIUS), (float)(focusY + HEIGHT - RADIUS - phaseAdjust)); for (int i = getPixelX() + RADIUS; i > getPixelX() - RADIUS - 1; i -= FRINGE_WIDTH) { p.lineTo(i, (float)(focusY + HEIGHT - RADIUS - phaseAdjust)); p.lineTo(i - FRINGE_WIDTH / 2, (float)(focusY + HEIGHT - RADIUS - (FRINGE_DEPTH - phaseAdjust))); } p.lineTo((float)(getPixelX() - RADIUS), (float)(focusY + HEIGHT - RADIUS - (FRINGE_DEPTH - phaseAdjust))); p.closePath(); g2d.fill(p); g2d.setColor(Color.WHITE); int xOffset = 0, yOffset = 0; if (getDirection() != null) { switch (getDirection()) { case NORTH: yOffset = -4; break; case EAST: xOffset = 4; break; case SOUTH: yOffset = 4; break; case WEST: yOffset = -4; break; } } Ellipse2D.Double leftEye = new Ellipse2D.Double(getPixelX() - EYE_OFFSET - EYE_SIZE + xOffset, focusY - 3 - EYE_SIZE / 2 + yOffset, EYE_SIZE, EYE_SIZE); Ellipse2D.Double rightEye = new Ellipse2D.Double(getPixelX() + EYE_OFFSET + xOffset, focusY - 3 - EYE_SIZE / 2 + yOffset, EYE_SIZE, EYE_SIZE); g2d.fill(leftEye); g2d.fill(rightEye); } }