The game you wrote in the previous lab was quite static and purely textual: nothing happened until the user typed a number into a dialog box, and the only reward was the dubious intellectual satisfaction of using binary search. This lab will build a game that is more graphical and interactive, and less cerebral (if that's the right word in this context). It's a rudimentary version of "shoot 'em up" games like Doom or Quake, though the real inspiration is my favorite arcade game, Whack a Mole. In honor of that, let's call the game WhaM.
In WhaM, an image (in my case, of a prairie dog like the ones here) jumps randomly around the screen. Your job is to hit the image with the mouse as fast as you can; after three hits, your elapsed time is reported, and you get a chance to play again.
No prairie dogs were harmed in the creation of this lab.
Image from www.animalinfo.org/species/rodent/cynomexi.htm.
In this lab, you will write Javascript code that interacts much more closely with the browser than in the previous lab.
The browser provides a library of user interface components like buttons, check boxes, option selectors, and text, and useful functions that make it possible to control what the user sees on the page. It's also possible to generate HTML on the fly and and thus create and modify web page contents under program control. In this lab, we'll investigate a few of these features:
The browser lets a Javascript program manipulate a handful of objects, of which two matter here: the window that is currently being displayed, and the document that it contains. These objects, and their sub-components, have properties like position, color, text, images, etc., that can be examined and manipulated by Javascript code. In addition, the objects can respond to external events like mouse motion and clicking, and to internally-generated events like the passage of time. By manipulating these features, it's not too hard to make a plausible game or achieve other interesting effects.
Javascript code itself is included in the web page in a couple of ways. First, it may appear anywhere between <script> and </script> tags, as in previous labs. Normally you would put all variables and functions inside a pair of script tags at the top of your page, after html and title and before body.
Second, code can be included as an "event handler" for any object on the web page. The simplest example of this is a button in a form, as seen in an earlier lab. That example used the onClick event to do an operation when the button is pressed, but you can also use onMouseover and onMouseout to perform some action when the mouse enters a region, like an image, and when it leaves. (This is often how "rollovers" are done on web pages.) There are other mouse events as well, but these are sufficient for this lab.
If you want to ask the user to provide a value for your program to use -- such as the speed at which the prairie dog moves -- you can use a prompt dialog box, or you can use a text field in a form as in Lab 3. Here's how the latter possibility might be written:
<form> Interval <input type="text" id="interval" value="1000" size="5"> msec </form>This will look like this on the web page:
We give the text field an id, that is, an identification that other components of the web page can use to refer to it; it's like the name of a variable.
The text field can subsequently be accessed through a rather long name that queries the document about an element with a specified id. You can load the value from the text field into a Javascript variable, or store a new value into the text field, as illustrated in these statements:
// get the value of interval text field into variable v var v = document.getElementById("interval").value // do some computation... // store a new interval back into the text field document.getElementById("interval").value = vKeep the names straight here: v is a Javascript variable; interval is the id of an object on the web page.
Your image is placed on the page with an img tag. The img tag will handle a variety of image encodings, most often a GIF or a JPG. You can use any image that you like -- pop stars and politicians and professors are popular -- but choose one that is not too big, perhaps using PaintShop or a similar program to crop or resize a big image into something smaller.
<img id="dog" src="dog.jpg" style="position:absolute; left:200px; top:100px">The style attribute is syntactically finicky, so when you make your own version of this kind of HTML, be sure to use exactly the same capitalization and spelling and punctuation that you see here.
Once the image has been given an id, you can use Javascript code to manipulate it, particularly to move it to some other position. For example, to move it to position (300, 200), you can set its left and top positions to new pixel values, using almost the same klunky syntax as in the example above:
document.getElementById("dog").style.left = "300px" document.getElementById("dog").style.top = "200px"If the literal positions like "300px" are replaced by with computed positions, the image will move each time these lines are executed with new values; this is illustrated below.
The statement setInterval('code', msec) sets up a timer that will execute the code every msec milliseconds. Normally the code is just a function call, and the function itself contains all the operations to be repeated; those operations, which you will put into a function called moveit(), move the image to a new random place. So your code will include statements like
setint_val = setInterval('moveit()', 1000)You'll write a function newgame that sets everything up for each new game just before it starts. If you include this assignment statement in newgame, it will cause the image to move once per second. (The quotes are important; without them, the program may not work.)
The library function clearInterval() gives you a way to stop the repeating operation; otherwise it would go on forever. The value returned by a call to setInterval is used in a call to clearInterval, like this:
clearInterval(setint_val) // stop the calls to moveitYou will have to call clearInterval to make the image stop moving, when the Stop button is pushed and when the user has whacked the mole 3 times.
Your assignment is to implement a version of WhaM. Our minimalist version looks like this before it starts:
You can make yours look more professional if you wish, by laying out the components anywhere and using any sizes, fonts, and colors that you like. For example, you could use Imagemask buttons instead of Form buttons, as you learned how to do in the graphics lab. You could add an image background with <body background="something.jpg">, and you could make the dialog at the end more expansive as well.
This is the specification of what your program must do:
|
The items are listed in the specification in the order in which it seems easiest to write the program. Do each piece and make it work before worrying about the next one.
Each component of the user interface has a name in the Javascript program; your interface doesn't have to look like the one above, but you must use the specified names for variables and functions ("hit" and "hitcount" are different!). Don't use the name "int" for a variable; it's a reserved word in some versions of Javascript.
It can be hard to keep all the pieces straight, especially when you're new to programming. Here's a template for how things will look at the end; your job is mostly to figure out what replaces the comments in the template. Try to think clearly about what operation or operations each part must do, as implied by the spec above.
Follow this template to organize your page! We've tried to make this orderly and easy to follow. Do not ignore it. Copy this part of the instructions into your HTML file lab6.html and then start replacing the commented parts by your own code, in the order suggested above. Copy and paste example code from the instructions, then modify it appropriately. This link points to the template lab6.html; you should download it directly (right click in Windows, Option click in Mac).
For calibration, my version inserts fewer than 20 lines of code into this template; each one of those lines is a simple variant of code given in these instructions and the class notes. If your code is much bigger, you are off on the wrong track. Follow the template. The logic in this program is simpler than in the previous lab, but there are more other details to get right.<html> <title> Your title goes here </title> <body> <img id="dog" src="yourimage.jpg" style="position:absolute; left:100px; top:60px" onClick='hit()'> <form> <input type=button value="Start" onClick='newgame()'> <input type=button value="Stop" onClick='clearInterval(setint_val); return true;'> <input type=text id=interval value="1000" size=5> msec </form> <script> // declare your variables here: hitcount, setint_val, starttime, ... function newgame() { // your code to set up for each new game goes here: // clearInterval(setint_val) to reset the interval set by a previous game // set hitcount to 0 // call setInterval() to set the interval from the value in the form // initialize starttime, the starting time, using new Date() } function moveit() { // your code to move your image goes here: // move the image, using the code given below } function hit() { // your code to handle each successful hit goes here: // move the image with moveit() // clearInterval(setint_val) to reset the interval // call setInterval() to set the interval again // add 1 to hitcount if (hitcount >= 3) { // clearInterval() to stop the image from moving // compute the elapsed time (make another call to new Date()) // confirm() to display time and ask about another game // if another game is to be played // newgame() } } </script> </body> </html>
Lay out the components: Start button, Stop button, initial image, and a way to set a new interval (e.g., a form or another button). You can include a background image if you like.
You will need variables for several values used by your program, including hitcount for the number of times the image has been hit so far, interval for how long the image stays in one place, and starttime for the time at which the current game started. These are used in several places in your program, so declare them at the beginning of your program, before the function definitions:
var hitcount // etc.
You have to move the image every time the user successfully hits it with the mouse, and also each time the setInterval mechanism operates. So it's best to write a function that does the move operation and call it from those two places. Write a function called moveit() that will move the image to a new random place each time the function is called. The function will look like this:
function moveit() { document.getElementById("dog").style.left = 500 * Math.random() + "px" // other statements go here }The built-in function Math.random() produces a different random number between 0 and 1 each time it is called; multiplying that by 500 scales it up to a number between 0 and 499. So this line creates a new random x value, and sets the left coordinate of the image to that many pixels. Thus this line will move the image to a new random horizontal position each time the function moveit() is called.
You have to write the analogous line for the vertical position, and put it into moveit() properly. You can also use different values than 500 to make better use of the screen area.
The function hit() has to increment the number of hits and test whether it has reached 3; if not, there's nothing more to do and it can return. If the count is 3, however, hit() should display a dialog box with the elapsed time and ask the user about another game. If the user wants to play again, then everything has to be re-initialized and the game reset to start over. Otherwise, the program is done.
This will require an if statement to compare hitcount to 3, and another if to check the response. Use confirm(), which will pop up a dialog box, then return true if the OK button is pushed and false if the Cancel button is pushed. This lets you write the if statement that will decide whether to play another game or quit, depending on the user's response; for example, it might be some variation on
if (confirm("Another game?")) { // code to play another game }
starttime = (new Date()).getTime() // the time right now, in millisecondsand something analogous later to get the stop time. The difference between those two values is the elapsed time, still in milliseconds. You have to convert that to seconds and display it.
Use the Javascript Console to warn about syntax errors. Really. We mean it. Use the Javascript Console to warn about syntax errors.
Write small sections at a time, and test as you go, as we have been suggesting above.
Use alert statements to display results as computation proceeds, or just to verify that your program is going where you think it is. These are easy to add and help narrow down problems quickly.
Add comments to your code to remind yourself of what some statement is doing, and perhaps to help the grader figure out what you had in mind as well. You can also "comment out" alert statements by sticking // at the beginning of the line; this leaves the code there for future use but it doesn't affect the program until you uncomment it.
Indent your code the way it has been shown in class, and the way it appears in the instructions. Indenting the statements helps you see quickly what's included in a function or a condition or a loop; you should always maintain consistent indentation.
When you're all done, send email to cos109@princeton.edu with the subject Lab 6 and your name and netid. Include the file lab6.html and your image(s) as attachments. If you wish, you can copy the files to your public_html directory so others can play your amazing game. If you do, please spell the file name correctly.
It is a good idea to check with one of the lab assistants to make sure that they have seen your program in its working state, that your file has been properly saved, and that you are sending the right file for grading. Mail the file to yourself as well and be sure that it arrived safely. Do all of these before you leave the lab or turn off your machine.