Created
July 14, 2014 18:45
-
-
Save schleary/dca69ea832eabdedeb3d to your computer and use it in GitHub Desktop.
Caterpillar Game
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Point; | |
import uwcse.graphics.*; | |
import java.awt.Point; | |
import java.util.ArrayList; | |
import javax.swing.JOptionPane; | |
import uwcse.graphics.*; | |
public class BadCabbage extends Cabbage { | |
Oval circle; | |
private ArrayList<Point> body = new ArrayList<Point>(); | |
private ArrayList<Rectangle> bodyUnits; | |
/** | |
* Creates a cabbage in the graphics window | |
* | |
* @param window | |
* the GWindow this Cabbage belongs to | |
* @param center | |
* the center Point of this Cabbage | |
*/ | |
public BadCabbage(GWindow window, Point center) { | |
super(window, center); | |
draw(); | |
} | |
/** | |
* Displays this Cabbage in the graphics window | |
*/ | |
protected void draw() { | |
int x = (int) center.getX(); | |
int y = (int) center.getY(); | |
// Make sure cabbage does not already exist here | |
getLocation(); | |
this.circle = new Oval(x - CABBAGE_RADIUS, y - CABBAGE_RADIUS, | |
CABBAGE_RADIUS * 2, CABBAGE_RADIUS * 2, Color.RED, true); | |
window.add(circle); | |
} | |
/** | |
* Checks for overlapping cabbages | |
* | |
* @param Point | |
* p | |
* @return boolean is cabbage overlapping | |
* | |
*/ | |
public boolean isCabbageInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS * 2); | |
} | |
/** | |
* This cabbage is eaten by a caterpillar | |
* | |
* @param cp | |
* the caterpillar that is eating this cabbage | |
*/ | |
public void isEatenBy(Caterpillar cp, ArrayList<Point> body, | |
ArrayList<Rectangle> bodyUnits) { | |
// Remove cabbages | |
window.remove(this.circle); | |
window.stopTimerEvents(); | |
int n = JOptionPane.showConfirmDialog(null, | |
"You ate a bad Cabbage! Would you like to play again?", | |
"GAME OVER", JOptionPane.YES_NO_OPTION); | |
if (n == 0) { | |
window.setExitOnClose(); | |
new CaterpillarGame(); | |
} else { | |
// exit game | |
System.exit(0); | |
} | |
} | |
/** | |
* Is this Point in this Cabbage? | |
* | |
* @param p | |
* the Point to check | |
* @return true if p in within the cabbage and false otherwise. | |
* | |
*/ | |
public boolean isPointInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS); | |
} | |
public double distance(Cabbage c) { | |
return Math.sqrt((c.center.x - center.x) * (c.center.x - center.x) | |
+ (c.center.y - center.y) * (c.center.y - center.y)); | |
} | |
/** | |
* Returns the location of this Cabbage | |
* | |
* @return the location of this Cabbage. | |
*/ | |
public Point getLocation() { | |
return new Point(center); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import uwcse.graphics.*; | |
import java.awt.Point; | |
import java.util.ArrayList; | |
/** | |
* An abstract class that contains all of the basic features of a cabbage. It | |
* should be derived by any class that represents a cabbage. (complete, but you | |
* can add other methods if you want) | |
*/ | |
public abstract class Cabbage implements CaterpillarGameConstants { | |
// The graphics window this Cabbage belongs to | |
protected GWindow window; | |
// The location of the center of this Cabbage in the graphics window | |
protected Point center; | |
/** | |
* Creates a cabbage in the graphics window | |
* | |
* @param window | |
* the GWindow this Cabbage belongs to | |
* @param center | |
* the center Point of this Cabbage | |
*/ | |
public Cabbage(GWindow window, Point center) { | |
this.window = window; | |
this.center = new Point(center); | |
} | |
/** | |
* Displays this Cabbage in the graphics window | |
*/ | |
protected abstract void draw(); | |
/** | |
* This cabbage is eaten by a caterpillar | |
* | |
* @param cp | |
* the caterpillar that is eating this cabbage | |
*/ | |
public abstract void isEatenBy(Caterpillar cp, ArrayList<Point> body, | |
ArrayList<Rectangle> bodyUnits); | |
/** | |
* Is this Point in this Cabbage? | |
* | |
* @param p | |
* the Point to check | |
* @return true if p in within the cabbage and false otherwise. | |
*/ | |
public boolean isPointInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS); | |
} | |
public boolean isCabbageInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS * 2); | |
} | |
public double distance(Cabbage c) { | |
return Math.sqrt((c.center.x - center.x) * (c.center.x - center.x) | |
+ (c.center.y - center.y) * (c.center.y - center.y)); | |
} | |
/** | |
* Returns the location of this Cabbage | |
* | |
* @return the location of this Cabbage. | |
*/ | |
public Point getLocation() { | |
return new Point(center); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import uwcse.graphics.*; | |
import java.awt.Point; | |
import java.util.*; | |
//import java.util.concurrent.RecursiveTask; | |
import java.awt.Color; | |
import javax.swing.JOptionPane; | |
import org.w3c.dom.css.Rect; | |
/** | |
* 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<Point> body = new ArrayList<Point>(); | |
// Store the graphical elements of the caterpillar body | |
// Useful to erase the body of the caterpillar on the screen | |
private ArrayList<Rectangle> bodyUnits = new ArrayList<Rectangle>(); | |
// 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; | |
private ArrayList<Cabbage> cabbages; | |
/** | |
* Constructs a caterpillar | |
* | |
* @param window | |
* the graphics where to draw the caterpillar. | |
*/ | |
public Caterpillar(GWindow window, ArrayList<Cabbage> cabbages) { | |
this.cabbages = cabbages; | |
// 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; | |
} | |
// Show the caterpillar | |
draw(); | |
} | |
/** | |
* Draw the caterpillar in the graphics window | |
*/ | |
private void draw() { | |
// Connect with Rectangles the points of the body | |
Point p = body.get(0); | |
for (int i = 1; i < body.size(); i++) { | |
Point q = body.get(i); | |
// add a body unit between p and q | |
addBodyUnit(p, q, bodyUnits.size(), Color.RED); | |
p = q; | |
} | |
window.doRepaint(); | |
} | |
/** | |
* Moves the caterpillar in the current direction (complete) | |
*/ | |
public void move() { | |
move(dir); | |
} | |
/** | |
* Move the caterpillar in the direction newDir. <br> | |
* If the new direction is illegal, select randomly a legal direction of | |
* motion and move in that direction.<br> | |
* | |
* @param newDir | |
* the new direction. | |
*/ | |
public void move(int newDir) { | |
// while caterpillar is trying to do anything invalid | |
while (!isPointInTheWindow(newDir) || isApproachingFence(newDir) | |
|| !validDirection(newDir) || isCrawlingOverItself(newDir)) { | |
// if point is not in window | |
if (!isPointInTheWindow(newDir)) { | |
int[] directions = { NORTH, SOUTH, WEST, EAST }; | |
newDir = directions[(int) (Math.random() * directions.length)]; | |
} | |
// if about to run into fence | |
if (isApproachingFence(newDir)) { | |
if (newDir == NORTH || newDir == SOUTH) { | |
int[] direction = { WEST, EAST }; | |
newDir = direction[(int) (Math.random() * direction.length)]; | |
} else if (newDir == EAST || newDir == WEST) { | |
int[] direction = { NORTH, SOUTH }; | |
newDir = direction[(int) (Math.random() * direction.length)]; | |
} | |
} | |
// if attempting to go backwards | |
if (!validDirection(newDir)) { | |
// keep caterpillar moving in same direction | |
newDir = dir; | |
} | |
// if eats self | |
if (isCrawlingOverItself(newDir)) { | |
// You lose!; | |
} | |
} | |
// If caterpillar eats all good cabbages and leaves window | |
if (isOutsideGarden() && this.cabbages.size() < 11) { | |
window.stopTimerEvents(); | |
int n = JOptionPane.showConfirmDialog(null, | |
"You won the game! Would you like to play again?", | |
"YOU WIN!", JOptionPane.YES_NO_OPTION); | |
if (n == 0) { | |
window.setExitOnClose(); | |
new CaterpillarGame(); | |
} else { | |
// exit game | |
System.exit(0); | |
} | |
} | |
// If caterpillar eats cabbages | |
Point head = getHead(); | |
for (int i = 0; i < cabbages.size(); i++) { | |
Cabbage c = cabbages.get(i); | |
boolean eaten = c.isPointInCabbage(head); | |
if (eaten) { | |
c.isEatenBy(this, body, bodyUnits); | |
cabbages.remove(c); | |
} | |
} | |
// new position of the head | |
head = new Point(body.get(body.size() - 1)); | |
switch (newDir) { | |
case NORTH: | |
head.y -= STEP; | |
break; | |
case EAST: | |
head.x += STEP; | |
break; | |
case SOUTH: | |
head.y += STEP; | |
break; | |
case WEST: | |
head.x -= STEP; | |
break; | |
} | |
// Is the new position in the window? | |
if (isPointInTheWindow(newDir)) { | |
// update the position of the caterpillar | |
body.add(head); | |
body.remove(0); | |
} | |
// 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 | |
Rectangle r = bodyUnits.remove(0); | |
window.remove(r); | |
// Add a new body unit at the head | |
Point p = body.get(body.size() - 1); | |
Point q = body.get(body.size() - 2); | |
addBodyUnit(p, q, bodyUnits.size(), Color.RED); | |
// show it | |
window.doRepaint(); | |
} | |
/** | |
* Add a body unit to the caterpillar. The body unit connects Point p and | |
* Point q.<br> | |
* Insert this body unit at position index in bodyUnits.<br> | |
* e.g. 0 to insert at the tail and bodyUnits.size() to insert at the head. | |
*/ | |
public void addBodyUnit(Point p, Point q, int index, Color c) { | |
// 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) - CATERPILLAR_WIDTH / 2; | |
int y = Math.min(q.y, p.y) - CATERPILLAR_WIDTH / 2; | |
// Width and height of the rectangle (vertical or horizontal rectangle?) | |
int width = ((q.y == p.y) ? (STEP + CATERPILLAR_WIDTH) | |
: CATERPILLAR_WIDTH); | |
int height = ((q.x == p.x) ? (STEP + CATERPILLAR_WIDTH) | |
: CATERPILLAR_WIDTH); | |
// Create the rectangle and place it in the window | |
Rectangle r = new Rectangle(x, y, width, height, c, true); | |
window.add(r); | |
// keep track of that rectangle (we will erase it at some point) | |
bodyUnits.add(index, r); | |
} | |
/** | |
* Is the caterpillar crawling over itself? | |
* | |
* @return true if the caterpillar is crawling over itself and false | |
* otherwise. | |
*/ | |
public boolean isCrawlingOverItself(int newDir) { | |
// Is the head point equal to any other point of the caterpillar? | |
Point head = getHead(); | |
int x = (int) head.getX(); | |
int y = (int) head.getY(); | |
if (newDir == NORTH) { | |
y -= STEP; | |
} else if (newDir == EAST) { | |
x += STEP; | |
} else if (newDir == WEST) { | |
x -= STEP; | |
} else { // SOUTH | |
y += STEP; | |
} | |
// Check each rectangle in caterpillar body; if head points are inside | |
// any rectangle, end game. | |
for (int i = 0; i < bodyUnits.size(); i++) { | |
int w = bodyUnits.get(i).getWidth(); | |
int h = bodyUnits.get(i).getHeight(); | |
int bx = bodyUnits.get(i).getX(); | |
int by = bodyUnits.get(i).getY(); | |
if ((x > bx && x < (bx + w)) && (y > by && y < (by + h))) { | |
window.stopTimerEvents(); | |
int n = JOptionPane.showConfirmDialog(null, | |
"You ate yourself! Would you like to play again?", | |
"GAME OVER", JOptionPane.YES_NO_OPTION); | |
if (n == 0) { | |
window.setExitOnClose(); | |
new CaterpillarGame(); | |
} else { | |
// exit game | |
System.exit(0); | |
} | |
return true; | |
} | |
} | |
return false; | |
} | |
/** | |
* 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 isApproachingFence(int newDir) { | |
// Get head; get direction. Find future head. | |
Point head = getHead(); | |
int x = (int) head.getX(); | |
int y = (int) head.getY(); | |
if (newDir == NORTH) { | |
y -= STEP; | |
} else if (newDir == EAST) { | |
x += STEP; | |
} else if (newDir == WEST) { | |
x -= STEP; | |
} else { // SOUTH | |
y += STEP; | |
} | |
// If future head overlaps with body | |
if ((x > 149 && x < 161) | |
&& ((y > 0 && y < 201) || (y > 299 && y < 500))) { | |
return true; | |
} | |
if (x > 491) { | |
return true; | |
} | |
if (y < 11 || y > 491) { | |
return true; | |
} | |
return false; | |
} | |
public boolean isOutsideGarden() { | |
// Check head | |
Point head = getHead(); | |
int x = (int) head.getX(); | |
// Check tail | |
Point tail = new Point(body.get(0)); | |
int x2 = (int) tail.getX(); | |
// If head and tail are outside the garden | |
if (x < 140 && x2 < 140) { | |
return true; | |
} | |
return false; | |
} | |
/** | |
* Is newDir valid? | |
*@param int newDir | |
*@returns boolean validity | |
*/ | |
public boolean validDirection(int newDir) { | |
if ((dir == NORTH && newDir == SOUTH) | |
|| (dir == SOUTH && newDir == NORTH) | |
|| (dir == EAST && newDir == WEST) | |
|| (dir == WEST && newDir == EAST)) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Is Point p in the window? | |
* @ param newDir | |
* @returns boolean | |
*/ | |
private boolean isPointInTheWindow(int newDir) { | |
Point head = getHead(); | |
int x = (int) head.getX(); | |
int y = (int) head.getY(); | |
if (newDir == NORTH) { | |
y -= STEP; | |
} else if (newDir == EAST) { | |
x += STEP; | |
} else if (newDir == WEST) { | |
x -= STEP; | |
} else { // SOUTH | |
y += STEP; | |
} | |
// Checks to see if point is in the window | |
if ((x < 1 || x > 499) || (y < 1 || y > 499)) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* 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)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import uwcse.graphics.*; | |
import java.util.*; | |
import java.awt.Color; | |
import java.awt.Point; | |
import javax.swing.JOptionPane; | |
/** | |
* A CaterpillarGame displays a garden that contains good and bad cabbages and a | |
* constantly moving caterpillar. The player directs the moves of the | |
* caterpillar. Every time the caterpillar eats a cabbage, the caterpillar | |
* grows. The player wins when all of the good cabbages are eaten and the | |
* caterpillar has left the garden. The player loses if the caterpillar eats a | |
* bad cabbage or crawls over itself. | |
*/ | |
public class CaterpillarGame extends GWindowEventAdapter implements | |
CaterpillarGameConstants | |
// The class inherits from GWindowEventAdapter so that it can handle key events | |
// (in the method keyPressed), and timer events. | |
// All of the code to make this class able to handle key events and perform | |
// some animation is already written. | |
{ | |
// Game window | |
private GWindow window; | |
// The caterpillar | |
private Caterpillar cp; | |
// Direction of motion given by the player | |
private int dirFromKeyboard; | |
// Do we have a keyboard event | |
private boolean isKeyboardEventNew = false; | |
// The list of all the cabbages | |
private ArrayList<Cabbage> cabbages; | |
private String messageGameOver; | |
/** | |
* Constructs a CaterpillarGame | |
*/ | |
public CaterpillarGame() { | |
// Create the graphics window | |
window = new GWindow("Caterpillar game", WINDOW_WIDTH, WINDOW_HEIGHT); | |
// Any key or timer event while the window is active is sent to this | |
// CaterpillarGame | |
window.addEventHandler(this); | |
// Set up the game (fence, cabbages, caterpillar) | |
initializeGame(); | |
// Display the game rules | |
// ... | |
// Rules | |
JOptionPane | |
.showMessageDialog( | |
null, | |
" WELCOME TO CATERPILLAR GAME! \n\n " | |
+ "To win, you must eat all of the white and psychedelic \n" | |
+ " cabbage heads and then exit the garden \n \n" | |
+ " Do not eat the poisonous red cabbages \n" | |
+ " Do not eat yourself \n \n" | |
+ " Use 'J' to move left \n" | |
+ " Use 'K' to move right \n" | |
+ " Use 'I' to move up \n" | |
+ " Use 'M' to move down \n \n" | |
+ " Are you ready to play? \n"); | |
// start timer events (to do the animation) | |
this.window.startTimerEvents(ANIMATION_PERIOD); | |
} | |
/** | |
* Initializes the game (draw the garden, garden fence, cabbages, | |
* caterpillar) | |
*/ | |
private void initializeGame() { | |
// Clear the window | |
window.erase(); | |
// No keyboard event yet | |
isKeyboardEventNew = false; | |
// Background (the garden) | |
window.add(new Rectangle(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, | |
Color.green, true)); | |
// Create the fence around the garden | |
Rectangle fence1 = new Rectangle(150, 0, 10, 200, Color.BLACK, true); | |
Rectangle fence2 = new Rectangle(150, 300, 10, 200, Color.BLACK, true); | |
Rectangle fence3 = new Rectangle(150, 0, 340, 10, Color.BLACK, true); | |
Rectangle fence4 = new Rectangle(490, 0, 10, 500, Color.BLACK, true); | |
Rectangle fence5 = new Rectangle(150, 490, 340, 10, Color.BLACK, true); | |
window.add(fence1); | |
window.add(fence2); | |
window.add(fence3); | |
window.add(fence4); | |
window.add(fence5); | |
// Cabbages | |
// ... | |
cabbages = new ArrayList<Cabbage>(N_GOOD_CABBAGES + N_BAD_CABBAGES); | |
// Initialize the elements of the ArrayList = cabbages | |
// (they should not overlap and be in the garden) .... | |
Point center = new Point(); | |
boolean locationIsCabbageFree; | |
for (int i = 0; i < N_BAD_CABBAGES + N_GOOD_CABBAGES; i++) { | |
locationIsCabbageFree = false; | |
while (!locationIsCabbageFree) { | |
int x = (int) (Math.random() * 310) + 170; | |
int y = (int) (Math.random() * 460) + 20; | |
center.setLocation(x, y); | |
locationIsCabbageFree = true; | |
for (Cabbage cabbage : cabbages) { | |
if (cabbage.isCabbageInCabbage(center)) { | |
locationIsCabbageFree = false; | |
} | |
} | |
} | |
if (i < N_BAD_CABBAGES) { | |
Cabbage c = new BadCabbage(window, center); | |
cabbages.add(c); | |
} else if (i < (N_BAD_CABBAGES + (N_GOOD_CABBAGES / 2))) { | |
Cabbage c = new GoodCabbage(window, center); | |
cabbages.add(c); | |
} else if (i < N_BAD_CABBAGES + N_GOOD_CABBAGES) { | |
Cabbage c = new PsychedelicCabbage(window, center); | |
cabbages.add(c); | |
} | |
} | |
// Create the caterpillar | |
cp = new Caterpillar(window, cabbages); | |
} | |
/** | |
* Moves the caterpillar within the graphics window every ANIMATION_PERIOD | |
* milliseconds. | |
* | |
* @param e | |
* the timer event | |
*/ | |
public void timerExpired(GWindowEvent e) { | |
// Did we get a new direction from the user? | |
// Use isKeyboardEventNew to take the event into account | |
// only once | |
if (isKeyboardEventNew) {// if user presses keyboard, store key that is | |
// pressed | |
isKeyboardEventNew = false; | |
cp.move(dirFromKeyboard); | |
} else | |
cp.move();// always keep moving until key is pressed | |
} | |
/** | |
* Moves the caterpillar according to the selection of the user i: NORTH, j: | |
* WEST, k: EAST, m: SOUTH | |
* | |
* @param e | |
* the keyboard event | |
*/ | |
public void keyPressed(GWindowEvent e) { | |
switch (Character.toLowerCase(e.getKey())) { | |
case 'i': | |
dirFromKeyboard = NORTH; | |
break; | |
case 'j': | |
dirFromKeyboard = WEST; | |
break; | |
case 'k': | |
dirFromKeyboard = EAST; | |
break; | |
case 'm': | |
dirFromKeyboard = SOUTH; | |
break; | |
case 'q': | |
System.exit(0); // abruptly ends the application | |
break; | |
default: | |
return; | |
} | |
// new keyboard event | |
isKeyboardEventNew = true; | |
} | |
/** | |
* The game is over. Starts a new game or ends the application | |
*/ | |
private void endTheGame() { | |
window.stopTimerEvents(); | |
// messageGameOver is an instance String that | |
// describes the outcome of the game that just ended | |
// (e.g. congratulations! you win) | |
boolean again = anotherGame(messageGameOver); | |
if (again) { | |
initializeGame(); | |
} else { | |
System.exit(0); | |
} | |
} | |
/** | |
* Does the player want to play again? | |
*/ | |
private boolean anotherGame(String s) { | |
int choice = JOptionPane.showConfirmDialog(null, s | |
+ "\nDo you want to play again?", "Game over", | |
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE); | |
if (choice == JOptionPane.YES_OPTION) | |
return true; | |
else | |
return false; | |
} | |
/** | |
* Starts the application | |
*/ | |
public static void main(String[] args) { | |
new CaterpillarGame(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Interface that lists useful constants for the caterpillar game | |
*/ | |
public interface CaterpillarGameConstants { | |
// Possible directions for the motion of the caterpillar | |
public static final int NORTH = 1; | |
public static final int EAST = 2; | |
public static final int WEST = 3; | |
public static final int SOUTH = 4; | |
// Distance covered by the caterpillar in one move | |
public static final int STEP = 10; | |
// Number of body elements added to the caterpillar when it grows | |
// (after eating a good cabbage) | |
public static final int GROWTH_SPURT = 5; | |
// Thickness of the caterpillar | |
public static final int CATERPILLAR_WIDTH = 6; | |
// Number of good cabbages | |
public static final int N_GOOD_CABBAGES = 10; | |
// Number of bad cabbages | |
public static final int N_BAD_CABBAGES = 10; | |
// Radius of a cabbage head | |
public static final int CABBAGE_RADIUS = 10; | |
// Size of the graphics window | |
public static final int WINDOW_HEIGHT = 500; | |
public static final int WINDOW_WIDTH = 500; | |
// Period of the animation (in ms) | |
public static final int ANIMATION_PERIOD = 100; // change back to 30 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Point; | |
import java.util.ArrayList; | |
import uwcse.graphics.*; | |
public class GoodCabbage extends Cabbage { | |
Oval circle; | |
private ArrayList<Point> body = new ArrayList<Point>(); | |
private ArrayList<Rectangle> bodyUnits; | |
/** | |
* Creates a cabbage in the graphics window | |
* | |
* @param window | |
* the GWindow this Cabbage belongs to | |
* @param center | |
* the center Point of this Cabbage | |
*/ | |
public GoodCabbage(GWindow window, Point center) { | |
super(window, center); | |
draw(); | |
} | |
/** | |
* Displays this Cabbage in the graphics window | |
*/ | |
protected void draw() { | |
int x = (int) center.getX(); | |
int y = (int) center.getY(); | |
ArrayList<Point> centerPoints = new ArrayList<Point>(); | |
this.circle = new Oval(x - CABBAGE_RADIUS, y - CABBAGE_RADIUS, | |
CABBAGE_RADIUS * 2, CABBAGE_RADIUS * 2, Color.WHITE, true); | |
window.add(circle); | |
centerPoints.add(center); | |
} | |
/** | |
* Checks for overlapping cabbages | |
* | |
* @param Point | |
* p | |
* @return boolean is cabbage overlapping | |
* | |
*/ | |
public boolean isCabbageInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS * 2); | |
} | |
/** | |
* This cabbage is eaten by a caterpillar | |
* | |
* @param cp | |
* the caterpillar that is eating this cabbage | |
*/ | |
public void isEatenBy(Caterpillar cp, ArrayList<Point> body, | |
ArrayList<Rectangle> bodyUnits) { | |
this.body = body; | |
this.bodyUnits = bodyUnits; | |
window.remove(this.circle); | |
Point p = body.get(body.size() - 1); | |
Point q = body.get(body.size() - 2); | |
cp.addBodyUnit(p, q, bodyUnits.size(), Color.RED); | |
} | |
/** | |
* Is this Point in this Cabbage? | |
* | |
* @param p | |
* the Point to check | |
* @return true if p in within the cabbage and false otherwise. | |
*/ | |
public boolean isPointInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS); | |
} | |
public double distance(Cabbage c) { | |
return Math.sqrt((c.center.x - center.x) * (c.center.x - center.x) | |
+ (c.center.y - center.y) * (c.center.y - center.y)); | |
} | |
/** | |
* Returns the location of this Cabbage | |
* | |
* @return the location of this Cabbage. | |
*/ | |
public Point getLocation() { | |
return new Point(center); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.Color; | |
import java.awt.Point; | |
import uwcse.graphics.*; | |
import java.awt.Point; | |
import java.util.ArrayList; | |
import uwcse.graphics.*; | |
public class PsychedelicCabbage extends GoodCabbage { | |
private ArrayList<Point> body = new ArrayList<Point>(); | |
private ArrayList<Rectangle> bodyUnits; | |
//psychedelic cabbages | |
Oval circle; | |
Oval circle2; | |
/** | |
* Creates a cabbage in the graphics window | |
* | |
* @param window | |
* the GWindow this Cabbage belongs to | |
* @param center | |
* the center Point of this Cabbage | |
*/ | |
public PsychedelicCabbage(GWindow window, Point center) { | |
super(window, center); | |
} | |
/** | |
* Displays this Cabbage in the graphics window | |
*/ | |
protected void draw() { | |
int x = (int) center.getX(); | |
int y = (int) center.getY(); | |
// Create and draw cabbage points | |
ArrayList<Point> centerPoints = new ArrayList<Point>(); | |
this.circle = new Oval(x - CABBAGE_RADIUS, y - CABBAGE_RADIUS, | |
CABBAGE_RADIUS * 2, CABBAGE_RADIUS * 2, Color.PINK, true); | |
this.circle2 = new Oval(x - CABBAGE_RADIUS / 2, y - CABBAGE_RADIUS / 2, | |
CABBAGE_RADIUS * 1, CABBAGE_RADIUS * 1, Color.BLUE, true); | |
this.window.add(this.circle); | |
this.window.add(this.circle2); | |
centerPoints.add(center); | |
} | |
/** | |
* Checks for overlapping cabbages | |
* | |
* @param Point | |
* p | |
* @return boolean is cabbage overlapping | |
* | |
*/ | |
public boolean isCabbageInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS * 2); | |
} | |
/** | |
* This cabbage is eaten by a caterpillar | |
* | |
* @param cp | |
* the caterpillar that is eating this cabbage | |
*/ | |
public void isEatenBy(Caterpillar cp, ArrayList<Point> body, | |
ArrayList<Rectangle> bodyUnits) { | |
// Remove cabbages | |
this.window.remove(this.circle2); | |
this.window.remove(this.circle); | |
this.body = body; | |
this.bodyUnits = bodyUnits; | |
Point p = body.get(body.size() - 1); | |
Point q = body.get(body.size() - 2); | |
// Make psychedelic colors | |
for (int i = 0; i < bodyUnits.size(); i++) { | |
Color c = new Color((float) Math.random(), (float) Math.random(), | |
(float) Math.random()); | |
bodyUnits.get(i).setColor(c); | |
} | |
cp.addBodyUnit(p, q, bodyUnits.size(), Color.WHITE); // color | |
} | |
/** | |
* Is this Point in this Cabbage? | |
* | |
* @param p | |
* the Point to check | |
* @return true if p in within the cabbage and false otherwise. | |
*/ | |
public boolean isPointInCabbage(Point p) { | |
return (p.distance(center) <= CABBAGE_RADIUS); | |
} | |
public double distance(Cabbage c) { | |
return Math.sqrt((c.center.x - center.x) * (c.center.x - center.x) | |
+ (c.center.y - center.y) * (c.center.y - center.y)); | |
} | |
/** | |
* Returns the location of this Cabbage | |
* | |
* @return the location of this Cabbage. | |
*/ | |
public Point getLocation() { | |
return new Point(center); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment