import uwcse.graphics.*; import java.awt.Point; import java.util.*; import java.awt.Color; /** * representation and display of a caterpillar */ public class Caterpillar implements CaterpillarConstants { // The body of a caterpillar is made of Points stored // in an ArrayList private ArrayList body = new ArrayList(); // Store the graphical elements of the caterpillar body // Useful to erase the body of the caterpillar on the screen private ArrayList bodyUnits = new ArrayList(); // The window the caterpillar belongs to private GWindow window; // Direction of motion of the caterpillar (NORTH initially) private int dir = NORTH; // Length of a unit of the body of the caterpillar // MUST be equal to the distance covered by the caterpillar // at every step of the animation. private final int bodyUnitLength=STEP; // Width of a unit of the body of the caterpillar private final int bodyUnitWidth=CATERPILLAR_WIDTH; /** * Construct a caterpillar */ public Caterpillar(GWindow window) { // Initialize the graphics window for this Caterpillar this.window = window; // Create the caterpillar (10 points) // First point Point p = new Point(5,WINDOW_HEIGHT/2); body.add(p); // Other points for(int i=0; i<9; i++) { Point q = new Point(p); q.x = p.x + bodyUnitLength; body.add(q); p=q; } // Show the caterpillar draw(); } /** * Draw the caterpillar in the graphics window */ private void draw() { // Connect with Rectangles the points of the body Point p=(Point)body.get(0); for(int i=1; i * If the new direction is illegal, select a * legal direction of motion and move in that direction.
*/ public void move(int newDir) { // Is the move illegal? boolean isMoveNotOK; // newDir might not be legal // Before trying a random direction, try first // the current direction of motion (if not newDir) boolean isFirstTry = true; // move the caterpillar in direction newDir do{ // new position of the head Point head = new Point((Point)body.get(body.size()-1)); switch(newDir) { case NORTH: head.y-=STEP; break; case SOUTH: head.y+=STEP; break; case EAST: head.x+=STEP; break; case WEST: head.x-=STEP; break; } // Is the new position in the window? if (isPointInTheWindow(head)) { isMoveNotOK=false; // Update the position of the caterpillar body.remove(0); body.add(head); } else { isMoveNotOK=true; // Select another direction // Try the current direction first if (newDir!=dir && isFirstTry) { newDir = dir; isFirstTry = false; } else // random direction newDir = (int)(Math.random()*4+1); } }while(isMoveNotOK); // Update the current direction of motion dir = newDir; // Show the new location of the caterpillar moveCaterpillarOnScreen(); } /** * Move the caterpillar on the screen */ private void moveCaterpillarOnScreen() { // Erase the body unit at the tail window.remove((Shape)bodyUnits.get(0)); bodyUnits.remove(0); // Add a new body unit at the head Point q = (Point)body.get(body.size()-1); Point p = (Point)body.get(body.size()-2); addBodyUnit(p,q,bodyUnits.size()); // show it window.doRepaint(); } /** * Add a body unit to the caterpillar. The body unit * connects Point p and Point q.
* Insert this body unit at position index in bodyUnits.
* e.g. 0 to insert at the tail and bodyUnits.size() to insert * at the head. */ private void addBodyUnit(Point p, Point q, int index) { // Connect p and q with a rectangle. // To allow for a smooth look of the caterpillar, p and q // are not on the edges of the Rectangle // Upper left corner of the rectangle int x = Math.min(q.x,p.x)-bodyUnitWidth/2; int y = Math.min(q.y,p.y)-bodyUnitWidth/2; // Width and height of the rectangle (vertical or horizontal rectangle?) int width = ((q.y==p.y)?(bodyUnitLength+bodyUnitWidth):bodyUnitWidth); int height = ((q.x==p.x)?(bodyUnitLength+bodyUnitWidth):bodyUnitWidth); // Create the rectangle and place it in the window Rectangle r = new Rectangle(x,y,width,height,Color.red,true); window.add(r); // keep track of that rectangle (we will erase it at some point) bodyUnits.add(index,r); } /** * Is Point p in the window? */ private boolean isPointInTheWindow(Point p) { return (p.x>=0 && p.x<=WINDOW_WIDTH && p.y>=0 && p.y<=WINDOW_HEIGHT ); } }