Lab 5: Working with the image library
Goals: The goals of this lab are to practice using the image library function.
You may work with your current assignment partner in this lab. Any lab quiz should still be taken individually.
Please also refer to the sample code and video posted in Assignment 5.
Problem 1: Designing a simple game
Game overview
The game we’re going to design is going to be simple, as we only have a lab to complete it. A player is going to click a point on the screen and a circle will appear. Then, it will move off the edge of the screen. The game will end once some amount of circles have left the screen.
Imports
The javalib library provides the support for the design of interactive games and creating images composed by combining geometric shapes as well as image files. See The Image Library for more information.
To use the library, download the javalib file above and add it to your project the same way you have added the tester library.
At the top of the .java file where the library is used, add the following import statements:
import tester.*; // The tester library import javalib.worldimages.*; // images, like RectangleImage or OverlayImages import javalib.funworld.*; // the abstract World class and the big-bang library import java.awt.Color; // general colors (as triples of red,green,blue values) // and predefined colors (Color.RED, Color.GRAY, etc.)
boolean testImages(Tester t) { return t.checkExpect(new RectangleImage(30, 20, OutlineMode.SOLID, Color.GRAY), new RectangleImage(30, 20, OutlineMode.SOLID, Color.GRAY)); }
boolean testFailure(Tester t) { return t.checkExpect( new ScaleImageXY(new RectangleImage(60, 40, OutlineMode.SOLID, Color.GRAY), 0.5, 0.25), new RectangleImage(30, 15, OutlineMode.SOLID, Color.GRAY)); }
Finally, you can display your images so that you can see whether you’re on the right track, as follows:
boolean testDrawTree(Tester t) { WorldCanvas c = new WorldCanvas(500, 500); WorldScene s = new WorldScene(500, 500); return c.drawScene(s.placeImageXY(myTree.draw(), 250, 250)) && c.show(); }
See The Image Library for more information.
Posns!
Remember our good friend Posn? So do we! Our libraries provide us with a Posn class, which just has two int fields, x and y, and a standard constructor.
This isn’t too useful, however, because like with all of our basic structures, we want to be able to write our own methods.
To remedy this, we’re going to create our own MyPosn class, which will act just like a Posn, but give us the freedom to do more with it.
class MyPosn extends Posn { // standard constructor MyPosn(int x, int y) { super(x, y); } // constructor to convert from a Posn to a MyPosn MyPosn(Posn p) { this(p.x, p.y); } }
Design an add method, which given another MyPosn will add its x and y values to this one and output a new MyPosn.
Design an isOffscreen method that given two numbers representing the width and height of a screen, determines if this position lies outside of it.
Circles!
Since our game is all about circles moving across the a screen, we need a Circle class to represent one. At the bare minimum, we must know its current position and velocity, so we know where to place it and where it’s going.
class Circle { MyPosn position; // in pixels MyPosn velocity; // in pixels/tick }
Complete the constructor for a Circle, and add whatever other fields you feel may be helpful.
Design a method move that outputs a Circle in its new position after one tick.
Design the ILoCircle interface and implementing classes.
Design the moveAll method that moves every Circle in the list.
Design the isOffscreen method that given two numbers representing the width and height of a screen, determines if a single circle lies outside of it. Hint: delegation.
Design the removeOffscreen method that given two numbers representing the width and height of a screen, removes every circle in a list of circles that is offscreen.
Design the draw method that outputs a WorldImage representing the circle.
Design the place method that given a WorldScene places a drawing of the circle at the appropriate position.
Design the placeAll method that places a lit of circles on a given WorldScene.
Designing The World
We now must design our class that will extend World.
Determine what your game needs to keep track of and design your class around this.
Design your default constructor as well as a convenience constructor for the player, which should only take in a number representing how many circles will go offscreen until the game is over.
Extend your class with the World class, and design the required makeScene method; this is the equivalent of to-draw.
Design your worldEnds method, which will determine when the game is over, which is when the count of circles to go offscreen is 0 or less. Refer to the documentation for the standard worldEnds pattern. You can design a custom end image if you’d like to, but it’s not required.
Design your onMouseClicked method, which will add a circle to the game where the player clicked. For now, the circle should just move straight up.
Design your onTick method. It should move the circles on screen, remove the ones off screen, and decrement the count of circles that are left to move offscreen. Hint: what standard list method that we haven’t yet implemented would make figuring out how many circles have been removed easy? Add that to your ILoCircle interface and implement it.
Play your game! Refer to the documentation to see how, and be careful to give a non-zero tick rate (1 / 28 is 0, but 1.0 / 28.0 is not).
Adding Randomness
Circles that only move up aren’t very fun! Let’s have them move left, right, up, and down.
Familiarize yourself with the section on randomness in Assignment 5.
Modify your world as needed to incorporate a Random object.
Modify your onMouseClicked method to send balloons up, down, left, or right, with uniform distribution.