| CSCI A201/A597Lecture Notes 17 Spring 2000 |
Hoping that you already looked at lab notes 8 and chapter 2 in your textbook we will develop a graphical application with mouse input. We start by running a demo of the application, in class, thus making the desired functionality explicit. Then we describe in detail its design. Without careful design we have little chance of success. Then we look at the implementation aspects.
Here is the final product, the program that we we will develop today in lecture, so that you can run it and see it running.
import element.*;
import java.util.Random;
import java.awt.Color;
class Mar06 {
public static void main(String[] args) {
DrawingWindow d = new DrawingWindow();
Pt mouseClick;
Rect target;
int x0 = 10, y0 = 10, x1 = 190, y1 = 190, size = 10;
Rect border = new Rect(x0, y0, x1 - x0, y1 - y0);
d.draw(border);
boolean playGame,targetAlive;
Random gen = new Random();
long start, stop;
int rounds = 0;
double time = 0.0;
mouseClick = d.awaitMouseClick();
playGame = true;
while (playGame) {
int xValue = gen.nextInt();
xValue = Math.abs(xValue);
xValue = x0 + xValue % (x1 - size - x0);
int yValue = gen.nextInt();
yValue = Math.abs(yValue);
yValue = y0 + yValue % (y1 - size - y0);
target = new Rect(xValue, yValue, size, size);
d.draw(target); d.setForeground(Color.blue);
d.fill(target);
start = System.currentTimeMillis();
targetAlive = true;
while (targetAlive) {
mouseClick = d.awaitMouseClick();
if (target.contains(mouseClick)) {
targetAlive = false;
stop = System.currentTimeMillis();
rounds += 1;
time += (stop - start);
System.out.println("Round " + rounds +
" time: " + (stop - start));
}
}
if (rounds > 10) {
playGame = false;
} else {
d.clear(d.bounds());
d.setForeground(Color.black);
d.draw(border);
long now = System.currentTimeMillis();
int number = gen.nextInt();
number = Math.abs(number);
int seconds = 1 + number % 3;
long then = now + seconds * 1000;
while (System.currentTimeMillis() < then) {
}
}
}
System.out.println("The game is over.");
System.out.println("Total time: " + time + " milliseconds.");
System.out.println("Your average: " + time / 10 + " millis.");
System.exit(0);
}
}
Here's the diagram that describes its functionality:
The first question that we need to ask in terms of its implementation is whether we have the right language structures to implement it.
Here's the template for a loop in Java and its diagrammatic
equivalent on its right:
With this in mind we can change the first diagram to include a more
explicit loop mechanism (or implementation) for the two cyclic aspects
of the diagram (loops are restarted at points indicated by D and E). To check a condition that should tell us if we should keep generating rectangles and a condition that should tell us whether the current target has been hit or not we introduce two boolean variables: andplayGame with which we can stop (or continue) the game and mark the moment when the target was hit.targetAlive
|
|
Now we need to look at the specifics.
1. Working with a drawing window.
Essentially you obtain one this way:2. Waiting for mouse input.You need to import the element package.DrawingWindow d = new DrawingWindow();
Appendix E page 308 is useful. We need to be able to read it.import element.*;
Any drawing window can be told to wait for mouse input. You need to ask your window to wait for mouse input. We choose to ask our drawing window to wait for a click of the mouse (that is, for a press and release of the mouse).3. Working with rectangles.
The program blocks (does nothing) until mouse is pressed and then released in the window that waits for this event to happen. When this happens the program is resumed and the coordinates of the position where the mouse button was released are returned together as aPt mouseClick = d.awaitMouseClick();Ptobject.Appendix E page 312 has all about
Pt's and of course chapter 2.
Appendix E page 316 describes the4. Working with random numbers.Rectclass. There's more than one way to create a rectangle, and here we create it by specifying the location of its top left corner, together with its width and its height.
HereRect border = new Rect(x0, y0, (x1 - x0), (y1 - y0));x0,y0,x1,y1, are the coordinates of the area where we draw in our window.Rectangles can tell whether a certain
Ptis inside them or not.
evaluates totarget.contains(mouseClick)trueorfalsedepending on the actual position ofinside the rectanglePt mouseClick;target(of typeRect).To clear the whole drawing window we can invoke
to obtain aRect window = d.bounds()Rectas large as the window itself.Then we can call
clearon that:which can also be done in one step:d.clear(window)as page 51 mentions as well.d.clear(d.bounds());
You need to import a class from the5. Using color.utilpackage:Page 30 in the first chapter has more about what we do here. Here is, for example, how we obtain a random integer betweenimport java.util.Random;andx0wherex1 - sizesizeis the width of the target (10 pixels).
Taking the remainder with the width of the window makes sure that the relative distance from the left margin of the window will be random but not larger than the width. Adding the coordinate of the letf margin will position the point appropriately in the window. We use this procedure to position a new random target.Random gen = new Random(); int x = gen.nextInt(); x = Math.abs(x); x = x % (x1 - size - x0) + x0;
You need to import the6. Getting system time.Colorclass from theawtpackage.Here's how we draw the target:import java.awt.Color;Chapter 2 and pages 56-57 have more on this.Rect target = new Rect(xValue, yValue, size, size); d.setForeground(Color.blue); d.fill(target)
Pages 26-27 in chapter 1 describe the method used here.7. Waiting a random amount of time.
This takes the current system time. A few instructions later (perhaps as soon as we detect a mouse click) we set the value oflong start, stop; start = System.currentTimeMillis();stopin the same way:Now if we take the difference we obtain the number of milliseconds we waited. If we divide by 1000 we obtain the same time expressed in seconds.stop = System.currentTimeMillis();The main new aspect here is that the return type of the function is
long. This means it's also a whole number (likeint) but from a larger range.
This method is explained on pages 102-103:Simply determine how manylong now = System.currentTimeMillis(); long then = now + seconds * 1000; while (System.currentTimeMillis() < then) { }secondsyou need to wait.Then compute what the time will be in milliseconds after the number of seconds that you want to wait will have elapsed. Then keep checking the time and stay in a loop while you have to keep waiting.
In our program
secondsis set randomly to1-3seconds.