/* * For this lab you will be working on writing a UFO game. The * UFO will fall from the top of the screen, the player will control * a tank at the bottom of the screen attempting to shoot it, and * the game will end if the UFO is shot or if it lands. */ /* * First of all, we need to import some classes that are built into * ProfessorJ. Posn works similarly to the Posns you saw in U211: * * Posn p = new Posn(4, 5); * p.x == 4 // The x coordinate is 4 * p.y == 5 // The y coordinate is 5 * * The World class handles all the things like drawing, events, * etc. You'll actually create a subclass of World later in this * lab. */ // We need these to get Posns and Worlds. import draw.Posn; import draw.World; /* * The Color class is an abstract class from which all the * various color classes (Blue, Red, etc.) are derived. * The color classes are created like so: * * Color c = new Blue(); */ // Here's all the colors we'll use. import draw.Color; import draw.Red; import draw.White; import draw.Green; import draw.Blue; import draw.Black; /* * You won't need to use Random directly in this lab as we'll * be giving you code that uses it. */ // We need random for the UFO's horizontal movement. import java.util.Random; /* * First you should create a couple of classes to represent UFOs * and Tanks. UFOs and Tanks both have a position in the game world, * and that's all the information they need to store. * * Each class also should have a move() method that takes the * distances to move the UFO/Tank in the x and y directions and * also the size of the world (to do checks in case the tank or * ufo is moving outside the world, in which case it should stop * moving in that direction). * * You should also write a same() method for each in order to test * the move() method (and others later) appropriately. */ /* * Once you have move(), you can stick the following code into UFO which * will handle the fact that the UFO zig-zags randomly left and right as * it falls. */ // Given n, we pick (randomly) a distance to move horizontally whose absolute // value is <= n. We also move the UFO by diffy pixels vertically. // // width and height are the dimensions of the world, which we use in move(). // // UFO moveRandom(int n, int diffy, int width, int height) { // return this.move(-n + (new Random()).nextInt(2 * n), diffy, width, height); // } /* * Now we'll start working on how to draw these onto a canvas. For each class, * write a method with the following contract: * * boolean draw(World w) * * The following methods of class World will be useful for writing these methods: * * boolean drawDisk(Posn p, int radius, Color c) * boolean drawRect(Posn p, int width, int height, Color c) * * And the following will be useful for testing them (see Examples for example usage): * * // Creates a canvas of the given dimensions and displays it * boolean start(int width, int height) * // Destroys the canvas * boolean stop() */ /* * We will also need shots in this game as the tank will be attempting to stop the * UFO from landing, so create a Shot class and a series of classes to model lists * of shots (ALoS, MTLoS, ConsLoS). Each should have move(), draw(), and same() * methods like the UFO and Tank classes. You may also want to write a method for * lists of classes that removes shots from the list once they've left the canvas, * but that's not necessary. * * Also write a method in the Tank class that creates a new Shot (which will be * useful when we make the game interactive). */ /* * Now that you can draw the UFO, Tank, and Shot(s), now we will create UFOGameWorld * (which is a subclass of World) to hold all the information about our game. * Obviously it should contain a UFO object, a Tank object and a list of shots, but * it should also contain the height and width of the world. Make it so that the * constructor has the following header: * * UFOGameWorld(int width, int height, UFO ufo, Tank tank, ALoS los) * * This way you can use the example given to you in the Examples class. * * You will want to write the following methods for UFOGameWorld: * * // Draws the world * boolean draw() * * You should use calls to the other classes' draw() methods, and you will also * want to use drawRect to "clear" the canvas before doing so by redrawing the * background. */ /* * Now you can draw the world, but it's pretty boring just sitting there, so let's * make it do something. In order to handle key events (like pressing the arrow * keys), you'll need to define the following method in your UFOGameWorld: * * World onKeyEvent(String ke) * * ke will be a string describing the key pressed. For this game, you will only * need to know about three possible values: "left" (for pressing the left arrow * key), "right" (for pressing the right arrow key) and "up" (for pressing the up * arrow key). * * The only object that responds to key events is the tank: you want to make it * so that the following happens: * * - Pressing the left arrow key moves the tank left. * - Pressing the right arrow key moves the tank right. * - Pressing the up arrow key makes the tank shoot. * * You should also insert the following method into your UFOGameWorld -- run() will * call all the methods needed to start the game. */ // run() takes the amount of time between ticks as a double and calls all the necessary // functions. // // boolean run(double tick) { // return this.start(this.width, this.height) && this.bigBang(tick); // } /* * Now we need to add a last bit of functionality so that the UFO and shots move -- * otherwise it's a very boring and pointless game! Implement the following method * in UFOGameWorld: * * World onTick() * * You should handle the shots moving upward and the UFO moving downwards here. * * If the UFO lands (i.e. gets too close to the bottom of the screen), the game * should end. In order to end the game, the following method of World (and thus * of UFOGameWorld) should be called: * * World endOfWorld() * */ /* * Everything moves now, but there's still a problem -- the UFO just goes through the * shots! In UFO and Shot, create a method that creates an appropriate BoundingBox * (which is already provided), then create a method for lists of shots which tests * to see if any of the shots in the list hits the UFO. * * Once you have that written, make sure to end the game if any of the shots hit the * UFO during gameplay and you're done! */ /* * Everything below are the classes we're giving to you -- a class that implements * all you need for bounding boxes and an Examples class with some definitions * that you can uncomment as you implement the classes. */ // We use rectangles for bounding boxes -- the main thing you // want them for is to tell when they overlap. class BoundingBox { Posn loc; // Upper left of bounding box int width; int height; BoundingBox(Posn loc, int width, int height) { this.loc = loc; this.width = width; this.height = height; } // When two bounding boxes overlap, we want to return true. // We do this by the following: // // Check the sides of the boxes. If the we have that there's // an overlap between the boxes both horizontally and vertically, // then we have an overlap. // // For each, we check the left-most (top-most) right (bottom) side // and subtract from it the right-most (bottom-most) left (top) // side. Draw it out and you'll see what I mean. boolean intersects(BoundingBox bb) { return (Math.min(this.loc.x + this.width, bb.loc.x + bb.width) - Math.max(this.loc.x, bb.loc.x) > 0) && (Math.min(this.loc.y + this.height, bb.loc.y + bb.height) - Math.max(this.loc.y, bb.loc.y) > 0); } } // Our handy-dandy examples class. class Examples { int width = 200; // How wide we want the game to be int height = 500; // How tall we want it to be Examples() {} // The UFO should start in the middle of the canvas, a little bit down from the top. // UFO ufo = new UFO(new Posn(this.width / 2, 10)); // The tank should start in the middle of the canvas, a little bit up from the bottom. // Tank tank = new Tank(new Posn(this.width / 2, this.height - 10)); // Here's a world to test drawing UFOs and Tanks with: World w = new World(); // Now to test the above out, try the following in the Interactions window: // // Examples e = new Examples(); // e.w.start(e.width, e.height) // e.ufo.draw(e.w) // e.tank.draw(e.w) // // To destroy the canvas, just call e.w.stop() or close the window. // There are no shots at the start of the game. // ALoS los = new MTLoS(); // Create a new game world with the actors defined above. // UFOGameWorld ugw = new UFOGameWorld(this.width, this.height, this.ufo, this.tank, this.los); }