import java.awt.*; import java.awt.geom.*; /** * The Boulder class represents an Asteroids-like boulder that has a trajectory as * well as a current position. It wraps around when it gets to the edge of the * screen -- or, at least, it will someday if it doesn't yet. It's based on the * book's Circle class, but with some extra fields and methods. * * @author Brad Richards */ public class Boulder { // These fields were all there in the Circle class private int diameter; private double xPosition; // This used to be an integer, but is now a double private double yPosition; // This used to be an integer, but is now a double private String color; private boolean isVisible; // These new fields keep track of how quickly the boulder is moving private double xVelocity; // How far it moves horizontally between steps private double yVelocity; // How far it moves vertically between steps /** * Create a new boulder at specified position with specified velocity and size. * * @param x Starting x position * @param y Starting y position * @param dx How many pixels it moves horizontally per update step * @param dy How many pixels it moves vertically per update step * @param size The diameter of the boulder, in pixels */ public Boulder(double x, double y, double dx, double dy, int size) { diameter = size; xPosition = x; yPosition = y; xVelocity = dx; yVelocity = dy; color = "black"; isVisible = false; } /** * Displays information about the Canvas object, and about our own state. Note that * the Canvas is a separate object, and to interact with it we need to use the . operator * and run a "getter" method on that object to learn about its state. When referring to * our "own" state, we can just use the names of our fields in the print statement. * (The default is that we're talking about our own fields and/or methods if we don't * say anything about who we're "bossing around".) */ public void printStatus() { System.out.println("Boulder is on a canvas that's "+Canvas.getWidth()+" by "+Canvas.getHeight()); System.out.println("It's at "+xPosition+", "+yPosition+" with velocity "+ xVelocity+", "+yVelocity); } /** * Uses the x and y velocities to calculate a new position for this boulder. */ public void updatePosition() { erase(); // Adjust the x and y positions based on velocities xPosition = xPosition + xVelocity; yPosition = yPosition + yVelocity; // If we've gone off left or right, wrap around. // I put the check for the right edge in the the ELSE // part since they can't *both* be true -- I can't be // off the left edge AND off the right edge at the same // time, so I only need to handle one or the other. if (xPosition < 0) { xPosition = xPosition + Canvas.getWidth(); } else { if (xPosition > Canvas.getWidth()) { xPosition = xPosition - Canvas.getWidth(); } } // If we've gone off the top or bottom, wrap around. Same // logic here with the ELSE, but note that this entire IF // is *outside* of the IF above. We need to run BOTH of them // each time we update the boulder's position since the two // are independent -- I always have to consider running off // the top or bottom, no matter what happened above with the // left and right edges. if (yPosition < 0) { yPosition = yPosition + Canvas.getHeight(); } else { if (yPosition > Canvas.getHeight()) { yPosition = yPosition - Canvas.getHeight(); } } // Draw us in our new position draw(); } /** * This method checks whether we overlap with another Boulder. It calculates the * distance between our center and theirs, and compares that to the sum of our * radius and their radius. * * @param other The boulder we're comparing ourselves to * @return True if we overlap with other and don't have the same parent */ public Boolean overlaps(Boulder other) { double distance; // Distance is sqrt of the x distance squared + y distance squared distance = Math.sqrt( Math.pow(xPosition-other.xPosition,2) + Math.pow(yPosition-other.yPosition,2)); return distance < (this.diameter/2 + other.diameter/2); } // ------------ Methods borrowed from Circle from here on down -------------- /** * Make this boulder visible. If it was already visible, do nothing. */ public void makeVisible() { isVisible = true; draw(); } /** * Make this boulder invisible. If it was already invisible, do nothing. */ public void makeInvisible() { erase(); isVisible = false; } /** * Change the size to the new size (in pixels). Size must be >= 0. */ public void changeSize(int newDiameter) { erase(); diameter = newDiameter; draw(); } /** * Change the color. Valid colors are "red", "yellow", "blue", "green", * "magenta" and "black". */ public void changeColor(String newColor) { color = newColor; draw(); } /** * Draw the boulder with current specifications on screen. */ private void draw() { if(isVisible) { Canvas canvas = Canvas.getCanvas(); canvas.draw(this, color, new Ellipse2D.Double(xPosition, yPosition, diameter, diameter)); } } /** * Erase the boulder on screen. */ private void erase() { if(isVisible) { Canvas canvas = Canvas.getCanvas(); canvas.erase(this); } } }