import uwcse.graphics.*;
import java.awt.Point;
import java.util.*;
import java.awt.Color;
/**
* A Caterpillar is the representation and the display of a caterpillar
*/
public class Caterpillar implements CaterpillarGameConstants {
// 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;
/**
* Constructs a caterpillar
*
* @param window
* the graphics where to draw the caterpillar.
*/
public Caterpillar(GWindow window) {
// Initialize the graphics window for this Caterpillar
this.window = window;
// Create the caterpillar (10 points initially)
// First point
Point p = new Point();
p.x = 5;
p.y = WINDOW_HEIGHT / 2;
body.add(p);
// Other points
for (int i = 0; i < 9; i++) {
Point q = new Point(p);
q.translate(STEP, 0);
body.add(q);
p = q;
}
// Other initializations (if you have more instance fields)
for (int i = 0; i < body.size() - 1; i++) {
Point p1 = (Point) body.get(i);
Point p2 = (Point) body.get(i + 1);
// Create a body unit between p1 and p2
createBodyUnit(p1, p2);
}
// Display the caterpillar
for (Object obj : bodyUnits) {
Shape s = (Shape) obj;
window.add(s);
}
}
/**
* Moves the caterpillar in the current direction (complete)
*/
public void move() {
move(dir);
}
/**
* Move the caterpillar in the direction newDir.
* If the new direction is illegal, select randomly a legal direction of
* motion and move in that direction.
*
* @param newDir
* the new direction.
*/
public void move(int newDir) {
Point head = (Point) body.get(body.size() - 1);
Point p;
do {
p = new Point(head);
// new location of the head
switch (newDir) {
case NORTH:
p.y -= STEP;
break;
case SOUTH:
p.y += STEP;
break;
case EAST:
p.x += STEP;
break;
case WEST:
p.x -= STEP;
break;
}
if (!isInWindow(p)) {
// select a new direction
// try the current direction first if different
if (newDir != dir) {
newDir = dir;
} else { // random
int[] directions = { NORTH, WEST, SOUTH, EAST };
newDir = directions[(int) (Math.random() * 4)];
}
}
} while (!isInWindow(p));
dir = newDir;
body.add(p);
createBodyUnit(p, head);
window.add((Shape) bodyUnits.get(bodyUnits.size() - 1));
// remove the tail point
body.remove(0);
Shape s = (Shape) bodyUnits.remove(0);
window.remove(s);
}
/**
* Is the caterpillar crawling over itself?
*
* @return true if the caterpillar is crawling over itself and false
* otherwise.
*/
public boolean isCrawlingOverItself() {
// Is the head point equal to any other point of the caterpillar?
return false; // CHANGE THIS!
}
/**
* Are all of the points of the caterpillar outside the garden
*
* @return true if the caterpillar is outside the garden and false
* otherwise.
*/
public boolean isOutsideGarden() {
return false; // CHANGE THIS!
}
/**
* Return the location of the head of the caterpillar (complete)
*
* @return the location of the head of the caterpillar.
*/
public Point getHead() {
return new Point((Point) body.get(body.size() - 1));
}
/**
* Increase the length of the caterpillar (by GROWTH_SPURT elements) Add the
* elements at the tail of the caterpillar.
*/
public void grow() {
// Get the direction of the first segment of the caterpillar
Point p = (Point) body.get(0);
Point q = (Point) body.get(1);
int deltaX = q.x - p.x;
int deltaY = q.y - p.y;
for (int i = 1; i < GROWTH_SPURT; i++) {
q = new Point(p); // copy of the tail point
// Translate the point in the opposite direction of the first
// segment of the caterpillar
q.x -= deltaX;
q.y -= deltaY;
body.add(0, q);
createBodyUnit(q, p);
p = q;
}
}
/**
* Creates a rectangle between p1 and p2
*/
private void createBodyUnit(Point p1, Point p2) {
if (p1.x == p2.x) { // vertical rectangle
int x = p1.x - CATERPILLAR_WIDTH / 2;
int y = Math.min(p1.y, p2.y) - CATERPILLAR_WIDTH / 2;
Rectangle r = new Rectangle(x, y, CATERPILLAR_WIDTH, STEP
+ CATERPILLAR_WIDTH, Color.RED, true);
bodyUnits.add(r);
} else { // horizontal rectangle
int x = Math.min(p1.x, p2.x) - CATERPILLAR_WIDTH / 2;
int y = p1.y - CATERPILLAR_WIDTH / 2;
Rectangle r = new Rectangle(x, y, STEP + CATERPILLAR_WIDTH,
CATERPILLAR_WIDTH, Color.RED, true);
bodyUnits.add(r);
}
}
// Is the point in the window?
private boolean isInWindow(Point p) {
return p.x >= 0 && p.x <= window.getWindowWidth() && p.y >= 0
&& p.y <= window.getWindowHeight();
}
}