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;
private boolean isGrowing;
private int count;
/**
* 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)
// Display the caterpillar (call a private method)
displayCaterpillar();
}
/**
* 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) {
// 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
if (!isGrowing) {
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
if (!isGrowing) {
window.remove((Shape) bodyUnits.get(0));
bodyUnits.remove(0);
} else {
count--;
isGrowing = (count >= 1);
}
// Add a new body unit at the head
Point q = (Point) body.get(body.size() - 1);
Point p = (Point) body.get(body.size() - 2);
createBodyUnit(p, q, bodyUnits.size());
window.add((Rectangle) bodyUnits.get(bodyUnits.size() - 1));
// show it
window.doRepaint();
}
/**
* 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);
}
/**
* 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() {
isGrowing = true;
count = 5;
// // location of the tail
// Point p = (Point) body.get(0);
// Point q = (Point) body.get(1);
// // grow the caterpillar by 5 body units
// // Add points
// for (int i = 0; i < 5; i++) {
// Point r = new Point();
// r.x = 2 * p.x - q.x;
// r.y = 2 * p.y - q.y;
// body.add(0, r);
// createBodyUnit(p, r, 0);
// window.add((Rectangle) bodyUnits.get(0));
// q = p;
// p = r;
// }
}
/**
* Displays the caterpillar
*/
private void displayCaterpillar() {
Point p = (Point) body.get(0);
for (int i = 1; i < body.size(); i++) {
Point q = (Point) body.get(i);
// draw a rectangle between p and q
createBodyUnit(p, q, bodyUnits.size());
p = q;
}
for (Object obj : bodyUnits) {
Rectangle r = (Rectangle) obj;
window.add(r);
}
}
private void createBodyUnit(Point p, Point q, int index) {
if (p.y == q.y) { // horizontal body unit
Rectangle r = new Rectangle(Math.min(p.x, q.x), p.y
- CATERPILLAR_WIDTH / 2, STEP, CATERPILLAR_WIDTH,
Color.RED, true);
bodyUnits.add(index, r);
} else { // vertical
Rectangle r = new Rectangle(p.x - CATERPILLAR_WIDTH / 2, Math.min(
p.y, q.y), CATERPILLAR_WIDTH, STEP, Color.RED, true);
bodyUnits.add(index, r);
}
}
}