342 97 8MB
English Pages 364 Year 2002
JavaScript
Programming
ANDY HARRIS
© 2001 by Prima Publishing. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording, or by any information storage or retrieval system without written permission from Prima Publishing, except for the inclusion of brief quotations in a review. A Division of Prima Publishing Prima Publishing and colophon are registered trademarks of Prima Communications, Inc. PRIMA TECH is a trademark of Prima Communications, Inc., Roseville, California 95661. Microsoft, Windows, Windows NT, and Internet Explorer are trademarks or registered trademarks of Microsoft Corporation in the U.S. and other countries. Netscape, Netscape Navigator, and JavaScript are trademarks or registered trademarks of Netscape Communications Corporation in the U.S. and other countries. All other trademarks are the property of their respective owners.
Important: Prima Publishing cannot provide software support. Please contact the appropriate software manufacturer’s technical support line or Web site for assistance. Prima Publishing and the author have attempted throughout this book to distinguish proprietary trademarks from descriptive terms by following the capitalization style used by the manufacturer. Information contained in this book has been obtained by Prima Publishing from sources believed to be reliable. However, because of the possibility of human or mechanical error by our sources, Prima Publishing, or others, the Publisher does not guarantee the accuracy, adequacy, or completeness of any information and is not responsible for any errors or omissions or the results obtained from use of such information. Readers should be particularly aware of the fact that the Internet is an ever-changing entity. Some facts might have changed since this book went to press.
Publisher: Stacy L. Hiquet Associate Marketing Manager: Heather Buzzingham Managing Editor: Sandy Doell Series Editor: Andy Harris Acquisitions Editor: Melody Layne Project Editors: Melody Layne and Kim Spilker Technical Reviewer: Michael Vine Copy Editor: Andrew Saff Proofreader: Lorraine Gunter Interior Layout: Danielle Foster Cover Design: Prima Design Team Indexer: Sharon Hilgenberg
ISBN: 0-7615-3410-5 Library of Congress Catalog Card Number: 2001086 Printed in the United States of America 01 02 03 04 05 BB 10 9 8 7 6 5 4 3 2 1
Send Us Your Comments: To comment on this book or any other PRIMA TECH title, visit our reader response page on the Web at http://www.prima-tech.com/comments.
How to Order: For information on quantity discounts, contact the publisher: Prima Publishing, P.O. Box 1260BK, Rocklin, CA 95677-1260; (916) 787-7000. On your letterhead, include information concerning the intended use of the books and the number of books you want to purchase.
To Heather, Elizabeth, and Matthew
Acknowledgments
I
first acknowledge Him from whom all flows. Thank you again, Heather, for listening to the keyboard clicking all those late nights. You are the sun and the stars to me.
Thanks to Melody Layne for being a good friend and a good editor (at the same time, even!). Thank you to Kim Spilker for your encouragement on this project, and to all the folks at Prima for being nice people to work with. A special thank you to Andy Saff for copyediting. If this book makes any sense at all, it’s because of you. Thank you also to Michael Vine for technical editing. I appreciate your efforts very much. A very special thank you goes to Scott Porter for his excellent game development library. His clever programming and selfless generosity make JavaScript game programming much more accessible than it has ever been before. I especially want to thank all my students, present and past. You have taught me so much more than I was ever able to teach you.
About the Author
A
ndy Harris began his teaching career as a high school special education teacher. During that time, he taught himself enough computing to do part-time computer consulting and database work. He began teaching computing at the university level in the late 1980s as a part-time job. Since 1995, he has been a full-time lecturer in the Computer Science Department of Indiana University/ Purdue University—Indianapolis. He manages the IUPUI Streaming Media Lab for the department and teaches classes in several programming languages. His main interests are Java, Visual Basic, Perl, JavaScript/dynamic HTML, virtual reality, programming on portable devices, and streaming media.
Contents at a Glance CHAPTER
1
Variables, Input, and Output
1
CHAPTER
2
The Fortune Teller: Random Numbers and the if Statement
21
CHAPTER
3
The Number Guesser: for and while Loops
45
CHAPTER
4
The Basic Mad Lib Program and Object-Based Programming
63
Advanced Mad Lib: Using the Other Form Elements
89
CHAPTER
5
CHAPTER
6
Petals around the Rose: Dynamic Output
115
CHAPTER
7
Image Swapping and Lookup Tables: The Basketball Game
139
CHAPTER
8
Dynamic HTML: The Stealth Submarine
171
CHAPTER
9
Sprite Animation: The Racer
203
Using Other gameLib Features: The Dogfight Game
235
CHAPTER
10
CHAPTER
11
Cookies and the Mouse: The Jigsaw Puzzle
261
CHAPTER
12
The Game Creation Process: The Brick Game
289
Syntax Reference
321
Index
335
APPENDIX A
Contents Introduction ................................................................................ xiii
1
CHAPTER
2
CHAPTER
3
CHAPTER
Variables, Input, and Output
1
The Project: Name Game ............................................................. 2 Adding Code to HTML .................................................................. 3 Using Variables .............................................................................. 5 Getting Input from the User ......................................................... 8 Building More Complicated Text ............................................... 10 Working with Numbers ............................................................... 11 Using String Methods ................................................................. 16 Summary ..................................................................................... 19
The Fortune Teller: Random Numbers and the if Statement
21
The Project: The Fortune Teller .................................................. 22 Getting Random Numbers ......................................................... 22 Making Specialized Random Numbers ..................................... 24 Making Decisions with the if Statement ................................... 28 Using the else Structure ............................................................. 32 Using Nested if Structures ......................................................... 34 Using the switch Structure ......................................................... 38 Returning to the Fortune Program ............................................ 42 Summary ..................................................................................... 44
The Number Guesser: for and while Loops
45
The Project: The Number Guesser ............................................ 46 Counting Forward ....................................................................... 46
viii Contents
Skipping Values ........................................................................... 50 Counting Backward ..................................................................... 52 Using the while Loop .................................................................. 53 Returning to the Number Guesser ............................................ 57 Summary ..................................................................................... 62
4
CHAPTER
5
CHAPTER
6
CHAPTER
The Basic Mad Lib Program and Object-Based Programming
63
The Project: Mad Lib ................................................................... 64 Objects and HTML ....................................................................... 65 Reading the Properties of an Object .......................................... 68 Methods ....................................................................................... 71 Events ........................................................................................... 74 The Purpose of Functions ........................................................... 78 Event-Driven Input and Output .................................................. 79 Back to the Mad Lib Program ..................................................... 84 Summary ..................................................................................... 88
Advanced Mad Lib: Using the Other Form Elements 89 The Project: the Advanced Mad Lib ........................................... 90 Working with Textlike Objects .................................................... 90 Using Check Boxes ..................................................................... 93 Using Radio Buttons ................................................................... 97 Using the select Object ............................................................. 102 Using Multiline Select Boxes ................................................... 105 Returning to the Advanced Mad Lib Program ........................ 107 Summary ................................................................................... 114
Petals around the Rose: Dynamic Output
115
The Project: Petals around the Rose ........................................ 116 Generating Output in Frames .................................................. 118 Displaying Output in Separate Windows ................................ 122 Designing the Petals around the Rose Game ......................... 127
7
CHAPTER
8
CHAPTER
9
CHAPTER
Image Swapping and Lookup Tables: The Basketball Game
139
The Project: The Basketball Game ........................................... 140 Swapping Images ..................................................................... 141 Using the MouseOver Events .................................................. 145 Creating Simple Arrays ............................................................ 149 Creating Arrays with Images .................................................... 152 Using Lookup Tables ................................................................. 155 Putting Together the Basketball Game .................................... 160 Summary ................................................................................... 168
Dynamic HTML: The Stealth Submarine
171
The Project: The Stealth Submarine Program ........................ 172 Dealing with Browser Dependency ......................................... 173 Using Cascading Style Sheets ................................................. 176 Working with Positionable CSS Elements .............................. 179 Changing the Text in a Positionable Element ......................... 185 Adding Cross-Platform Sound ................................................. 189 Putting It Together in the Stealth Sub Game .......................... 192 Summary ................................................................................... 200
Sprite Animation: The Racer
203
The Project: The Racer Program .............................................. 204 Introducing the Sprite ............................................................... 206 Moving Sprites Around ............................................................ 211 Using Frame Animation in Sprites .......................................... 214 Detecting Collision .................................................................... 218 Creating a Race Timer ............................................................... 221 Returning to the Racer Program .............................................. 224 Summary ................................................................................... 233
ix Contents
Creating Graphics for JavaScript Games ................................ 129 Generating the Dice-Rolling Routine ....................................... 133 Summary ................................................................................... 137
Contents
x
10 CHAPTER
11 CHAPTER
12 CHAPTER
Using Other gameLib Features: The Dogfight Game 235 The Project: The Dogfight Game ............................................. 236 Using Layers and the Keyboard ............................................... 237 Adding Sound ........................................................................... 242 Improving Sprite Management ................................................ 244 Adding Missiles ......................................................................... 250 Returning to the Dogfight Game.............................................. 252 Summary ................................................................................... 260
Cookies and the Mouse: The Jigsaw Puzzle
261
The Project: The Jigsaw Puzzle Program ................................ 262 Using the Mouse to Drag and Drop ......................................... 264 Responding to Button Presses ................................................. 268 Following the Mouse and Sprites ............................................ 272 Storing Information in Cookies ................................................ 275 Creating the Jigsaw Game ....................................................... 279 Summary ................................................................................... 288
The Game Creation Process: The Brick Game
289
The Project: The Brick Game .................................................... 290 Creating the Game Design ....................................................... 290 Setting Up the Playground ....................................................... 292 Adding the Paddle ..................................................................... 295 Bouncing the Ball off the Paddle ............................................. 296 Adding Bricks ............................................................................ 298 Adding More Bricks and Sound ............................................... 301 Adding Multiple Game Boards ................................................ 304 Changing the Bricks’ Behavior ................................................. 307 Adding Scorekeeping Functionality ........................................ 308 Using a Cookie to Track the High Score .................................. 318 Improving the Code Used at the End of Game ....................... 319 Summary ................................................................................... 320
Syntax Reference
321
xi
Index
335
Contents
A
APPENDIX
Introduction
I
n the early 1980s, my brother and I bought a computer. My mom thought we were crazy, because it didn’t do anything. She was right. There was very little software available. We spent many nights typing in programs (usually games). They almost never worked when we finished typing, so we always had to look back carefully over the code. Eventually, we were able to fix typographical mistakes and make the games work. Then, we found ourselves changing the code, so we could improve the games that we were typing in. That was a great way to learn how to program. We were working in a simple language without too many confusing options. We were writing games that were even more fun to play because we had crafted them ourselves. We were able to combine both logical thinking and our creative drives. Game programming was especially rewarding, because the results were programs that we actually wanted to use. Our skills improved because game programming provided lots of challenges. We later found that the skills we learned by developing games were very useful in more “serious” applications as well. Today it would appear difficult to learn programming in the same way that my brother and I did. Computers are much more complicated than that old machine that my brother and I used. Programming languages have become far more complex at the same time, and the programmer’s toolbox of compilers, integrated environments, and debuggers seems expensive, complex, and forbidding to somebody who just wants to get started and play around a little bit. Still, it is possible to learn to program in almost the same way. A new crop of beginnerfriendly languages is popping up. Specifically, the JavaScript language has emerged as a new programming language perfect for beginners who want to see what programming is all about, and who want to learn in a non-threatening but real way. JavaScript is embedded into popular Web browsers, so the language costs nothing. It is available on nearly every major type of computer system. The language has a reasonably straightforward syntax that provides beginners a gentle introduction to some important modern concepts, such as object-oriented and event-based programming. It also does not have so many features that it requires a degree in computer science to understand. The purpose of this book is to teach you the main principles of programming. You will learn the major concepts used in most programming languages, and you will apply them specifically in JavaScript. I will use the context of game programming to teach the concepts, but you will find that you can use the techniques for purposes far beyond game programming. If you already know JavaScript, you will still probably find some new ideas in the descriptions of game programming. If you have already done some game development, you might be surprised at the things that you can do with
Introduction
xiv
JavaScript. If both areas are new to you, you’re going to have a great time exploring some new things. Although you will probably not immediately make a million dollars selling computer games, I think that you will find this book’s approach reasonably friendly. You will also see that you can easily apply the skills that you learn more generally to other kinds of more serious programming. Besides, the addition of a game to a Web site can drastically improve its popularity, making game programming a very practical skill for any Webmaster. I am not presuming that you have any programming experience at all. I do expect that you are comfortable with HTML and that you know how to build Web pages with a plain text editor. You should have a good text editor, a graphics editor, and a sound editor. The CD-ROM that accompanies this book has examples of all these programs. Of course, you will need access to a computer that can run these programs. You will be running your programs in a Web browser, so you should have access to recent versions of Netscape Navigator (4.0+) and Internet Explorer (5.0+). Some of the later examples in this book take advantage of gameLib, a special programming library. The CD-ROM includes a copy of gameLib. Finally, if you wish to publish your pages, you will need access to some sort of Web server.
How to Use This Book To learn how to program a computer, you must acquire a complex progression of skills. If you have never done any programming at all, you will probably find it easiest to go through the chapters in order. Of course, if you are already an experienced programmer, it might not be necessary to do any more than skim the earliest chapters. In either case, programming is not a skill you can learn by reading. You’ll have to write programs to learn. This book has been designed to make the process reasonably painless. Each chapter begins with a complete program that demonstrates some key ideas for the chapter. Then, you’ll look at a series of smaller programs that illustrate each of the major points of the chapter. Finally, you’ll put these concepts together to build the larger program that you saw at the opening of the chapter. You’ll be able to see important ideas in simple, straightforward code, and you’ll also see more involved programs that put multiple ideas together. All the programs are short enough that you can type them in yourself (which is a great way to look closely at code), but they are also available on the CD-ROM. Throughout the book, I’ll throw in a few other tidbits, notably the following: HINT
P TRA
These are good ideas that experienced programmers like to pass on.
There are a few areas where it’s easy to make a mistake. I’ll point them out to you as you go.
IN
THE
R EAL W ORLD
As you examine the games in this book, I’ll show you how the concepts are used for purposes beyond game development.
K TRIC
These will suggest techniques and shortcuts that will make your life as a programmer easier.
At the end of each chapter, I’ll suggest some programs that you can write with the skills you’ve learned so far. This should help you start writing your own programs.
Introduction
EXERCISES
xv
1
C H A P T E R
Variables, Input, and Output
P
rogramming is nothing more than controlling in a more direct way what you want your computer to do. You prob-
ably already use a computer in a number of ways, and you control it to some extent by the programs you use and the way that you use them. Still, without programming, you are always at the mercy of the programs designed by others. In this chapter, you will look at how you can begin to influence the computer’s behavior. Specifically, you will: • Examine how you can put code inside a HyperText Markup Language (HTML) page • Use dialog boxes to interact with the user • Learn how computers store data in variables • Learn how to get data from the user • Perform basic operations on data
JavaScript Programming for the Absolute Beginner
2
The Project: Name Game In Figure 1.1, a special box pops up in a normal Web page that asks the user for his or her name. Then, a series of other boxes pop up, asking for a last name and then finding other ways to manipulate the name.
FIGURE 1.1
By the end of this chapter, you will be able to create this simple name game.
Adding Code to HTML Web pages provide a rich background for programming. With the knowledge of HTML that you already have, you can generate pages that look pretty good. For example, you can control how text looks and add images. You might even have some experience with the finer-grained control of cascading style sheets. Still, plain HTML pages lack true interactivity. The only way that the user can really exert any control over the page is by clicking on links. This is interesting, but that fun takes the user only so far.
Creating the Hello, World! Application It would be interesting to make the page a little more dynamic. Both of the major browsers, Netscape Navigator and Microsoft Internet Explorer, support JavaScript, a scripting language that is perfect for adding interactive features to a Web page. Take a look at the following snippet of code:
If you save this code as a Web page, then load that page into a browser, it generates the screen shown in Figure 1.2. This code snippet consists of normal (if very abbreviated) HTML, but it uses some features you might not have seen before. The tag set specifies to the browser that any code between the tags is not written in HTML, but in a scripting language. Both the Netscape Navigator and Microsoft Internet Explorer browsers use JavaScript, their default language, unless you specify another language. (Technically, Microsoft Internet Explorer runs a variant called Jscript, but the code works the same as either JavaScript or Jscript.) You can place script tags anywhere in an HTML document. All of the code between is written according to the rules of JavaScript. JavaScript is a different language than HTML, and its rules are different.
The // characters denote a comment. The interpreter ignores anything that follows on a line that begins with these characters. However, the information that programmers provide in comments is still critical. Comments are mainly for the benefit of the programmer. It’s a great idea to add lots of comments to your programs, because good comments can make your code much easier to repair. This particular program has lots of comments. They explain what the program is intended to do. Such comments are always a good way to begin documenting your program. You’ll look at some other useful places to put comments as the code becomes more complex later in this book.
Sending a Message to the User Only one line of the code fragment does anything particularly interesting: alert("hello world");
You use the alert statement to send a special kind of message. The message pops up in its own box, called a dialog box. The dialog box is pretty insistent. If you try to click on the page before you close the dialog box, it will ding at you with a sound, but it will refuse to do anything else. The box will not close, and the other programs on your desktop will not receive the focus. It will insist that you respond to it in some way before you go on to other things in the browser. You might have noticed the semicolon character (;) at the end of the alert line. This character indicates the end of the alert statement. Most lines of JavaScript code end with the semicolon. The comments did not need a semicolon, because the compiler ignores them. You’ll see some other places later where a semicolon is not needed at the end of a line, but for now it’s fine simply to assume that most lines require this character at the end.
Using Variables
Creating the Hello, Joe! Application Take a look at the program shown in Figure 1.3. It shows an example of output with a new twist: This time, the computer generates a message already stored in the computer’s memory. This program’s code looks like this:
Hello Joe
Hello, Joe
Essentially, this program stores the text “Hi there, Joe,” then displays the message to the user as soon as the Web page is loaded into the browser. This program illustrates how the computer can store information for later retrieval. A special kind of element called a variable is the secret. Computers essentially work with information. It’s important to understand how computers store the information. Think of it this way: If you carry a lunch to work or school, you probably don’t just grab a handful of last night’s leftovers and carry them around in your hands until lunchtime. Instead, you probably use some kind of container, such as a sack. You put the lunch in the container, which you then carry around until it’s time to eat. You don’t actually deal with the food until lunch, because it’s easier to work with the container than the actual food (that is, you would rather carry the sack containing the food than carry the various items of your lunch individually). Variables fulfill a similar function for the computer. They hold information until the computer needs to work with it.
Chapter 1 Variables, Input, and Output
One of the most important aspects of programming to learn is how the computer uses data. Data is defined as the information that the computer collects and manipulates. In your first few programs, the data will be text, such as names or phrases. Later in this chapter, you will learn how to use other kinds of data, such as numbers. Programming languages use something called variables as a tool for managing data. In the next section, you will see how variables are used to store information.
5
JavaScript Programming for the Absolute Beginner
6
FIGURE 1.3
A greeting to Joe pops up.
You’ll learn a lot more about variables later. For now, you simply need to understand that whenever you want the computer to have some information, such as a user’s name, a message, or a rate, you’ll need to use a variable.
Using the var Statement Every computer language provides some kind of support for variables. In JavaScript, programmers use the var statement to create a new variable. When you create a variable, you need to give it a name. This is just like putting labels on the food containers in your refrigerator. When you look at the label, you can see what is inside without having to open the container. Take another look at this statement, which occurs in the preceding Hello Joe program: var greeting;
The term var indicates that the computer should create a variable. The word greeting is the name that I gave the variable. This line ends with a semicolon, as most lines do. After interpreting this line of code, the computer generates in memory a chunk of space named greeting. Thereafter, you can write code that writes new values to the memory chunk, and write code that reads the values from the chunk.
Guidelines for Naming Variables Computer programmers get to name a lot of things. Experienced programmers have established a few naming conventions. You might want to keep these guidelines in mind: Be careful about case. In many languages (including JavaScript), username, userName, and USERNAME are all completely different variable names.
Don’t use spaces or punctuation. Most languages don’t allow multiword variable names. Many programmers use capitalization (taxRate) or underscore characters (tax_rate) to make multiple word variable names easier to read. (I’ll use the capitalization convention in this book.) Many of the punctuation characters have special meanings, so it’s not a good idea to put these in a variable name. Don’t make your variable names so long that they are impossible to type correctly. Many programmers prefer variable names from 5 to 15 characters long.
Assigning a Value to a Variable Take a look at this line from the Hello Joe program: greeting = "Hi there, Joe";
Essentially, this line assigns the text “Hi there, Joe” to the variable greeting. Everything between the quotation marks is called a string literal. (Computer programmers love to give complicated names to simple ideas. Get used to it!) String is the term that computer programmers use for text, because computers handle text as a string of characters. Literal means that you are actually specifying the literal value "Hi there, Joe". The equals sign (=) indicates assignment. It might make more sense to read this statement as follows: greeting gets the string literal "Hi there, Joe". P TRA
It would not be exactly correct to say that greeting equals "Hi there, Joe". Equality is an entirely different issue, which I will deal with in the next chapter.
Finally, the word "Hi there, Joe".
greeting
is the name of a variable that gets the string value
If you want to give a variable a particular value, you can do so by using a similar assignment statement. Coding a variable assignment statement is like putting leftovers in a container.
Using the Contents of a Variable You carry a lunch bag to keep all your food items neatly in one place. If you pull your lunch bag out of the refrigerator, you are in effect pulling out the entire lunch. In a similar way, you specify a variable’s name to refer to a variable. Take another look at this line: alert(greeting);
When the user runs this Web page, he or she does not see the term “greeting” pop up. Instead, he or she sees “Hi there, Joe,” which is the content of the greeting variable. It doesn’t matter what the value of greeting is, as long as it is some kind of text. This line of code can output any value stored in the variable greeting.
7 Chapter 1 Variables, Input, and Output
Make names descriptive. You probably shouldn’t use a name such as r or x, because later it will be hard to remember exactly what the variable is supposed to contain. Names such as taxRate or greeting will make your code much easier to follow.
JavaScript Programming for the Absolute Beginner
8
Getting Input from the User In addition to sending information to the user, computers can also retrieve information from the user. This kind of exchange is called input. HINT
Sometimes people get confused about whether something is input or output. For example, suppose that you are reading a text message on a computer screen. As you read the message, you input it to your brain; however, from the computer’s perspective, that message is output to the screen. The convention in programming is that when you talk about either input or output, you are speaking from the point of view of the computer.
Creating the Hello User! Application Take a look at this program, which illustrates a simple kind of input: This time, the computer asks the user his or her name and uses that information in another statement. Here’s the code that made this happen:
Hello User
Hello, User
This program has a variable, but this time a value embedded in the program does not determine the variable. Instead, the user gets an opportunity to enter a value into a special dialog box, and the program copies whatever the user types to the variable. Now that you can get values from the user, you can create programs that are much more flexible. For example, you can create a program that calls the user by name, even if you have no idea what that name will be when you write the program (see Figure 1.4).
9
This program asks the user for his or her name, then returns that input in another dialog box.
Using the prompt Statement The secret weapon that makes it possible to let the user enter data into a variable is the prompt statement. It is used in this line: userName = prompt("What is your name?");
As you can see, the line starts out much like the assignment statement in the Joe program, but this time, the value that the program is sending to userName is not a literal value, but the result of some kind of operation. The prompt statement causes a dialog box much like the alert box to pop up. This dialog box is different, however, because it not only sends a message to the user, it also provides a place for the user to type a response. The primary purpose of a prompt statement is to get a value back. Every prompt statement includes some sort of variable, ready to catch the value. Think of eating your lunch at a cafeteria. You have to get a tray to hold your lunch, but then you have some choices. You tell the person behind the counter what item of food you want, and he or she then places that selection on your tray. Much like a tray holds your food selection, your variable provides a place in which to input a value. An input statement, such as the prompt statement you have seen in this example, is used when you are going to fill up a variable with the answer to some kind of question. In later chapters you will see some other forms of input. The prompt statement calls up a dialog box that presents the user with a question and a place to type an answer. It is almost always used as part of an assignment statement to assign the user’s answer to some variable. K TRIC
When you generate a prompt dialog box, you need to determine the question that you want to ask, and you also need to have a variable ready in which to store the answer.
Chapter 1 Variables, Input, and Output
FIGURE 1.4
JavaScript Programming for the Absolute Beginner
10
Saying Hi to the User Now that you have a variable that contains the user’s name, it is a reasonably simple task to return that value to the user. The following line does the trick: alert(userName);
Because userName is not in quotes, the computer interprets it as a variable name and displays to the user the contents of the userName variable. Of course, the contents provide a pretty limited greeting, but you’ll fix that in the next section. If you did put quotes around userName, the actual value “userName” is what the user would see, rather than the value associated with the userName variable.
Building More Complicated Text It would be much nicer if the greeting could be friendlier. If the user’s name is Susan, maybe the program should say “Hi, Susan!!” Figure 1.5 shows the enhanced program’s output.
Creating the Concatenation Program To create the screen shown in Figure 1.5, you must combine string literals (the “Hi,” part and the “!!” part) with the value of a variable. Specifically, you will create userName and give it a value just as you did in the previous example. The only difference is the output. The earlier program’s only output was the value of the variable, without any other text around it. In this program, you’ll figure out a way to include the value of a variable inside other text.
Concatenating Strings Creating this program requires a process that is another instance in which programmers have given a simple idea a complicated name: String Concatenation: The combination of two or more text strings. They can be string literals or string variables (or the values of string expressions, which you will learn about later). In JavaScript, you concatenate strings by using the plus sign (+).
FIGURE 1.5
Now the greeting integrates the user’s name into another string.
String concatenation is a lot simpler than it sounds. Here’s how the code looks:
concatenation
Concatenation
K TRIC
If you are testing a page and you want to see it again after it’s finished, just click the browser’s Refresh button.
Joining Variables and Literals The concatenation program uses two variables: userName is meant to hold the user’s name, and greeting contains the text that the program will output to the user. The program obtains userName from the user through a prompt statement, just as in the previous program. This is the only new line: greeting = "Hi, " + userName + "!!";
By now you should recognize that the program assigns a value to greeting. To form that value, the program concatenates the string literal “Hi,” with the contents of the userName variable and joins another string literal (“!!”) to the end of that one. You can use string concatenation to make really long, complex text strings. The great thing is that the user won’t ever know that you did any manipulations. He or she will just see that the program used his or her name.
Working with Numbers Computers are pretty good at working with text values. They are even better at working with numbers. Deep inside the computer, text and numbers are stored the same way, but programmers use many schemes and conventions to encode data. (If you really want the details, consult your neighborhood computer scientist.) JavaScript is pretty good at hiding this complexity from users and even programmers. It generally guesses
Chapter 1 Variables, Input, and Output
11
JavaScript Programming for the Absolute Beginner
12
whether you are talking about numbers or text. Still, sometimes you’ll need to do some special tricks to help JavaScript guess correctly.
Creating the Adder Application The program shown in Figure 1.6 provides a handy service. It looks at the cost of a meal, adds a 15 percent tip, and calculates the total bill. This program does its work with variables, as you can see from the code:
Adder
The Adder
FIGURE 1.6
The Adder program displays the cost of a meal, the tip amount, and the total cost.
K TRIC
Using Numeric Variables The Adder program has variables, but their values are not text. In this program, you want the computer to do mathematical computations on the data, so the variables must be numeric. Notice that there are no quotation marks around the value 22.50. Also, you can combine the var statement with an assignment statement, so the variable immediately has some kind of value. The following line calculates the value of the variable tip by multiplying meal by .15 (or 15 percent): var tip = meal * .15;
In computing, the asterisk (*) usually means multiplication. The following line creates the total variable: var total = meal + tip;
This statement adds up the contents of meal and tip, then places the sum in the total variable. The alert statements work just as you would expect. The program automatically converts all the numbers to text when generating the output.
Diagnosing the Bad Adder Application This program would be more useful if it allowed the user to enter the cost of the meal. Look at this variant of the Adder code:
BadAdd
The BadAdd
The program looks reasonable, but the results, as shown in Figure 1.7, are definitely not what you wanted. Something went wrong somewhere. Before reading on, see whether you can figure out the problem.
Interpreting Numbers and Text Here’s what happened: The prompt statement returns a string value. The computer stores this value as text, which is no problem until you try to do math on it. In the following line, meal gets a string value, because that’s what the prompt statement returns: meal = prompt("How much was the meal?");
The following line multiplies the value of meal by .15: var tip = meal * .15;
FIGURE 1.7
This time the user gets to enter the cost of the meal, but the program’s calculations are incorrect.
var total = meal + tip;
The computer still interprets meal as a string and tip as a number. The problem is the plus sign (+), which is an operator that tells the computer to add up numbers. If the plus sign is used in the context of string variables, it will concatenate the strings. In this statement, the plus sign has a number on one side and a string on the other, so it confuses the computer. In this case, the computer decides to treat both values as strings and concatenate them. So, the result of concatenating “22.50” and “3.375” is another string value, “22.503.375”.
Creating the Good Adder Application JavaScript provides a number of ways to solve this problem, but the easiest is the eval() function. Take a look at this version of the code:
GoodAdd
The GoodAdd
15 Chapter 1 Variables, Input, and Output
It doesn’t make sense to multiply by a string value, so JavaScript simply converts the string meal to a number, and the multiplication works. The next line is where the problems begin:
JavaScript Programming for the Absolute Beginner
16
FIGURE 1.8
The user enters the cost of the meal, and the program calculates everything correctly.
There’s only one new thing in the code. That is this line: meal = eval(meal);
This statement simply evaluates the string value that the user entered. The program reassigns that result to the meal variable. In this case, the program returns a numeric value. Look at the results shown in Figure 1.8, and you’ll see that the program now works correctly.
Using String Methods In addition to enabling you to manipulate numbers, most programming languages allow you to manipulate text inside string variables. Most languages have features that you can use to change a variable to uppercase or lowercase, commands that allow you to determine the length of a string, and techniques for concatenating strings. You can combine all these feature, commands, and techniques, along with input and output, to generate your old friend, the Name Game program, from the beginning of the chapter. First, however, Table 1.1 reviews the new syntax you’ve learned in this chapter.
17
TABLE 1.1 SYNTAX SUMMARY Description
Example
var varName
Create a variable called varName.
var userName;
var varName = value
Create a variable called varName with a starting value of value.
var userName = "";
alert(msg)
Send the string msg to the user in a dialog box.
alert("Hi there");
Send a dialog box with the string and a text box. Then return the value to varName.
userName =
eval(string)
Evaluate the string expression. If it’s a number, return the number.
number = eval("3");
stringVar.
Convert stringVar to all uppercase letters.
bigName =
varName = prompt (question)
toUpperCase()
question
prompt("What is your name");
userName. toUpperCase()
stringVar.length
Return the number of characters in the stringVar variable.
nameSize = userName.length
Returning to the Name Game Remember the Name Game program that you learned about at the very beginning of the chapter? Take another look at that program. You should now recognize that the program’s code demonstrates many of the concepts that you’ve learned in this chapter. You’ll also spot a few new things.
The Name Game
The Name Game
You have seen most of this code before. Basically it is nothing more than some input and output statements and a few new string manipulation tricks.
Writing the Variable Creation Lines The first few lines simply create all the variables you will need: var firstName = ""; var lastName = ""; var numLetters = 0;
Programs typically begin with some comments followed by statements that create the variables for your code. Most other statements depend on variables, so it’s sensible to create them all first. It’s also nice to place them somewhere easy to find. Then, when your code gets longer, it’s easy to spot which variables you have working. Note that when creating variables, I give them a default value. JavaScript doesn’t require that you choose whether a variable will contain text or a number, but it still matters. I like to initialize those variables that I intend to be strings with the "" value, and if I expect a variable to be a number, I initialize it with 0.
Converting to Uppercase After the program obtains the user’s first name, it does some manipulation: alert ("I think I'll shout it:
" + firstName.toUpperCase());
In JavaScript, sometimes variables have special powers. Strings have a bunch of things they can do, called methods. You’ll spend much more time with them later, but for now it’s fun to explore a few and see what they do. The command firstName.toUpperCase() converts the value of the firstName variable to all uppercase letters. The command then concatenates that value to the end of the string "I think I'll shout it: ".
Concatenating Complex Strings in Input and Output
lastName = prompt("So what's your last name, " + firstName + "?");
Such complex string concatenation is completely legal, and often a good idea.
Counting the Letters in Strings The last alert statement tells how many letters are in the user’s name. Here’s how that works: numLetters = firstName.length + lastName.length; numLetters is a numeric variable. firstName.length returns the number of characters
in the firstName variable. Likewise, lastName.length returns the number of characters in lastName. The program adds these values together and stores the total in the numeric variable numLetters. HINT
You might be curious why stringName.toUpperCase() has parentheses at the end of the command whereas stringName.length does not. This is because length is technically not a method of string variables, but a property. The distinction will be much more important later in this book. For now, it’s enough to just recognize the pattern.
Combining Numbers and Text At this point, you might be very anxious about when something is a number and when it’s a string. Don’t panic. JavaScript is a very friendly language. It tries to guess what you mean, and it is often correct. Test your programs, and if you see a concatenation happen when you are expecting an addition, use the eval statement on the variables that JavaScript should interpret as numbers. If you have numbers that your program needs to concatenate to a string, that concatenation generally happens automatically, as in this line: alert ("Did you know there are " + numLetters + " letters in your name?");
Summary In just one chapter, you have learned a lot. You have seen how you can embed JavaScript programs inside Web pages. You’ve looked at output with the alert statement, and input with the prompt statement. You’ve learned about variables and literal values. You have begun to explore some of the operations you can do with numbers and strings. In the next chapter, you’ll begin to see how computers can make choices based on the value of variables. You will also look at how to generate random numbers. These skills, along with those you’ve already learned, form the foundation for all game programming.
Chapter 1 Variables, Input, and Output
You can see in this code that complex string concatenation is common in input and output statements. The following prompt statement includes two literal values and a variable in the question:
19
20 JavaScript Programming for the Absolute Beginner
EXERCISES 1. Write a JavaScript program that will ask the user for his or her first name, last name, and middle initial. Return them back in the order of last name, first name, and middle initial, then in first name, middle initial, and last name format. 2. Write a program that asks the user for two numbers, adds them up, and returns the result to the user. 3. Improve the preceding program so that it also does subtraction, multiplication, and division on the two numbers. (Hint: Division uses the / symbol, and multiplication uses *.) 4. Have a program ask the user his or her name and shoe size. Determine the user’s “lucky number” by multiplying the number of letters in his or her name by the shoe size. Return the results. 5. Create a program that asks the user for the height and width of a rectangle and then returns the area (h * w) and perimeter (2*(h+w)).
2
C H A P T E R
The Fortune Teller: Random Numbers and the if Statement
I
n the last chapter, you learned how to get data from the user, how to manipulate that data, and how to send output
back to the user. In this chapter, you’ll learn how to do even more with data. Specifically, you’ll learn how to: • Generate random numbers • Manipulate those numbers to be within a specific range • Build a condition • Use conditions to branch program logic • Build more complex conditional structures
JavaScript Programming for the Absolute Beginner
22
The Project: The Fortune Teller Figure 2.1 shows the Fortune Teller program, which generates a random fortune for the user every time that the page is loaded.
Getting Random Numbers Games are most interesting when they are not completely predictable. Game programmers frequently use random numbers to simulate the unpredictability of the real world. The ability to generate random numbers in any specified range is an important skill for game programmers.
Creating the Number Maker Program The Number Maker program (see Figure 2.2) is very limited, yet it gives you the foundation of many games. Every time that you load the page, you will get a new random number between 0 and 1. Although such numbers aren’t entirely useful by themselves,
FIGURE 2.1
The Fortune Teller program generates a random fortune for the user each time that the page is loaded.
FIGURE 2.2
The Number Maker program generates a random number between zero and one.
they do turn out to be very flexible. As you’ll see shortly, you can do some clever tricks to use random numbers for other, more practical applications, such as dice.
numberMaker
numberMaker
Hit the Reload key to see a new number!
As you can see, this code includes very little that is new, except for one line. Clearly, number is a variable that gets a value, but this value is neither acquired from the user nor directly coded by the programmer. The value of the number variable comes from the Math.random() line.
Using the Math Object JavaScript is referred to as an object-based language. The exact implications of this will become far more important in later chapters, but you have already begun to see the importance of objects. Recall from the last chapter that string variables are objects that have methods attached to them. An object is some sort of entity, and a method is something that the object can do. JavaScript supplies the Math object. This object just holds a bunch of interesting (if you like math) methods and properties. Any time you are looking for some kind of math function (such as calculating the cosine of an angle, or figuring out a logarithm or power), you might check in the Math object for a useful function. Table 2.1 describes many of these functions.
Chapter 2 The Fortune Teller: Random Numbers and the if Statement
Take a look at the code for the Number Maker, to see how it works:
23
JavaScript Programming for the Absolute Beginner
24
TABLE 2.1 USEFUL METHODS
AND
PROPERTIES
OF THE
MATH OBJECT
Method
Description
Example
Result
abs()
Calculates the absolute value.
Math.abs(-3)
3
ceil()
Returns the next higher integer.
Math.ceil(3.5)
4
cos()
Returns the cosine of an angle (in radians).
cos(Math.PI/2)
0
floor()
Returns the lower integer.
Math.floor(3.5)
3
max()
Returns the larger of two values.
Math.max(3,5)
5
min()
Returns the smaller of two values.
Math.min(3,5)
3
pow()
Returns the first number raised to power of second.
Math.pow(2,3)
8
random()
Returns a random value between 0 and 1.
Math.random()
0.348557233 (the result varies)
round()
Rounds to the nearest integer.
Math.round
3
(3.2)
Returns the sine of an angle (in radians).
sin()
Math.sin
1
(Math.PI/2) sqrt()
Returns the square root of a number.
Math.sqrt(16)
4
tan()
Returns the tangent of an angle (in radians).
Math.tan
1
(Math.PI/4)
Using the Math.random() Method The Math.random() method is of particular interest to game developers, because it generates a random number. The number will be some value between 0 and 1. Most languages have some form of random number generation, and it is very common for such functions to return this kind of zero-to-one value. Specifically, the following line gets a random value and copies it to the number variable: number = Math.random(); HINT
Technically, the values are only pseudorandom, because they are derived by a complex mathematical formula based on the current time. That’s not usually a problem, because they are close enough to truly random for game development.
Making Specialized Random Numbers Now you can generate a zero-to-one value, but such values aren’t terribly interesting. Usually, you will need numbers to be within some other kind of range. If you are creating a dice game, for example, you might want the values to be between 1 and 6.
25
Two dialog boxes generated by the Die Roller program.
Creating the Die Roller Take a gander at the Die Roller program, which simulates rolling one six-sided die. Figure 2.3 shows a couple of runs of the program, just so you can see how it works. The program generates a value between 0 and 1, then does various manipulations on that value to turn it into an integer between 1 and 6. This particular program prints the intermediate steps, although the user usually would not be concerned about how the program generated the number. The code for the Die Roller program is as follows:
dieRoller
dieRoller
The program starts, as usual, with a number of variable creation statements. I made a bunch of variables to handle the various steps of the number conversion process. Although having so many variables is not absolutely necessary, it does sometimes make the code a little more clear. The result variable is intended as a string, but all the other variables are numeric. Although JavaScript isn’t fussy about variable types, my convention is to indicate at least what type of data I expect the variable to hold.
Getting the Raw Value The first step in the process is to get the raw (zero-to-one real number) value. You saw this done in the last project, and you see in this code a now-familiar line: rollRaw = Math.random();
This line of code generates a zero-to-one random value and assigns it to the variable rollRaw.
Making Larger Numbers You now have a zero-to-one value with a lot of digits behind the decimal point stored in rollRaw. You’re looking for a value between 1 and 6, with no decimal point, because that range includes the legal values of standard dice. You’ll need to go through a few steps to get such a value. The first thing that you’ll need to do is get a number in the zero-to-five range. (You’ll see why I chose this range in just a moment.) The following line performs the trick: rollBigger = rollRaw * 6;
This command multiplies the value in rollRaw by 6. This results in a value larger than 0 and less than 6, but still with a huge number of decimal values. To prove this, run the program a few times and take a careful look at the relationship between rollRaw and rollBigger. Although you’re getting closer to your goal, the decimal values are still a problem.
Converting to an Integer
Deep in the hardware of the computer, integers and floating point numbers are stored and manipulated in completely different ways. Although you might not care much about the difference, it’s quite important to the computer. Most languages give you ways to translate numbers between the different types of variables. Going from a floating point number to an integer is reasonably easy. JavaScript actually gives you three different ways to do it. Take a look at this line of code, and you’ll see how I did it in this program: rollInt = Math.floor(rollBigger);
The Math object has a floor() method, which simply lops off the decimal value. The program takes rollBigger (a value with decimal points between 0 and 6) and just chops off everything after the decimal point. The program then copies the resulting integer value to the rollInt variable. rollInt is now an integer. Its value will be 0, 1, 2, 3, 4, or 5. HINT
Earlier I mentioned that there are three ways to get an integer. The Math object also supplies the ceil() method and the round() method. You can use either of these alternatives, although they would give you slightly different results. ceil() always rounds up, and round() rounds according to normal conventions. Not every language supports these functions, but almost every programming language has some form of the floor method (although it might have a very different name, such as parseInt or intValue). If you learn how to generate random numbers with the floor() method, you’ll have a strategy that you can easily transport to other programming languages.
It’s a good idea to look again at the program running a few times. Examine the relationship between rollBigger and rollInt.
Getting Values Larger Than 0 The rollInt variable gets pretty close to what you’re looking for, but it still has one big problem. Although it generates six different values, they are not in exactly the correct range. A typical die has values from 1 to 6, not 0 to 5. This line takes care of that problem: rollFinal = rollInt + 1;
This line simply increases the value of rollInt by one. Now, every time the program runs, it generates a number in the range 1 through 6. Try the program a few times and see how it works. It’s also instructive to look at the results of this program and examine the relationships between the variables, so you understand how this code works.
Chapter 2 The Fortune Teller: Random Numbers and the if Statement
You might remember from grade school math that positive and negative numbers without decimal values are commonly referred to as integers. Numbers with decimal values are frequently called real numbers. Specifically, computers use a form of real numbers called floating point notation.
27
JavaScript Programming for the Absolute Beginner
28
Developing an Algorithm for Random Numbers Getting random numbers in a certain range is a very common problem in game programming. Here’s a summary of my solution for making random integers between low and high: 1. 2. 3. 4.
Get a random floating point value. Multiply the value by high. Convert the value to an integer. Add the value of low.
You will use this technique often when you write games. Even when you write programs in other languages, the same strategy will apply. Such generic strategies are called algorithms. Algorithms are proven strategies for solving specific problems. Once you have a good algorithm, it is generally pretty easy to implement it in code.
Making Decisions with the if Statement So far, all of my programs have been sequential. They have simply been a list of instructions for the computer to carry out. This is a completely legitimate form of programming, but in other cases you might want the computer to perform different tasks in different situations. The way that you get computers to make decisions requires much the same process that you use when making decisions yourself, although a computer must rely on a much more formulated process. When you got up this morning, you probably listened to the radio. Most people like to know what the weather will be like before they get dressed in the morning. They say to themselves something like “If it’s cool out today, I’ll wear a sweater.” Although you probably did not have to concentrate very hard on this thought process, it more than likely did occur at some level. This is an example of logic in action. It relies on a very important construct, called a condition. A condition is an expression that can be evaluated as true or false. In the weather problem, the condition is “It will be cool today.” That statement will be either true or false. As you can see, in human terms, conditions are a lot like yes/no questions. When you are designing algorithms, you will often need to think about your logic so that you can turn it into this kind of yes/no question. You can usually turn such questions into conditions easily, then use those conditions in a number of interesting ways.
Creating the Low Temp Program Figures 2.4, 2.5, and 2.6 show a few runs of the Low Temp program. This game generates a random number to indicate the current temperature, then recommends dress appropriate for the weather if the temperature is under a threshold temperature of 65 degrees.
FIGURE 2.4
FIGURE 2.5
The program suggests attire appropriate for the current weather conditions. FIGURE 2.6
This run of the program generates a random temperature that is above the threshold of 65 degrees. No “Wear a Sweater” message appears.
The code for this program is as follows:
lowTemp
lowTemp
Hit Reload to see another temperature
Generating the Temperature The temperature-generation line looks intimidating: temp = Math.floor(Math.random() * 100) + 1;
If you look at the line closely, you will see that it is really just another way of stating the algorithm that you developed in the last section. The parentheses denote the order of operation, just as in math, so the program executes Math.random() first. The program then multiplies the resulting random value by 100. The computer then adds 1 to the floor of that value, resulting in a number between 1 and 100. This is a reasonable range for temperatures.
Making Decisions with Conditions Of course, the computer is never as flexible as the human mind. Consider all these statements: It will be cool. It is cool. Today will be cool. It will be a little brisk today. Temperatures will be in the low 60s. Today will be a lot like yesterday. Your mind is flexible enough that you might correctly interpret all these statements (and many more) as meaning the same thing. Humans are blessed with the ability to understand many different kinds of syntax (the basic structure of the statement) and determine the correct semantics (meaning). Computer languages do not handle subtleties well. Most of the time, there are very few ways to say something that the computer will understand. The art of programming is refining the expressive language of humans to a more restrictive computer language such as JavaScript without losing too much of the meaning.
TABLE 2.2 COMPARISON OPERATORS Meaning
Greater than
==
Is equal to
!=
Is not equal to
=
Greater than or equal to
JAVASCRIPT
To express this kind of condition in JavaScript, you need a condition construct. Usually, a condition compares some variable to a value or another variable. For example, the weather statement might be as follows: temperature < 65
Take a careful look at how this works: Temperature is a variable. The programmer has presumably already created it and given it a starting value. You can use any type of variable in a condition (usually) but you must be careful not to compare different types of values. (More on that later.) The less-than sign ( 85){ alert("Wear a bathing suit!!"); } else { alert("Wear short sleeves!!"); } // end 85 if
Finally, the program closes the outermost if statement with this line: } // end 70 if
It is lined up vertically with the if (temp < 70) statement and the corresponding } else { line to help clarify which structure it is ending. I also commented the line to clarify even further what is going on.
37 Chapter 2 The Fortune Teller: Random Numbers and the if Statement
This second if statement is nested inside the first one. It now checks for temperatures above 30 degrees. Any code placed between this line and its right brace will execute only when the temperature is less than 30 degrees. (Of course, because of the first if statement, the program has already determined that the temperature is less than 70 degrees.) The code that executes under these conditions is as follows:
JavaScript Programming for the Absolute Beginner
38
K TRIC
If you’re still confused about how these nested statements work, run the program while you’re looking at the code. When the computer first outputs the number, see whether you can figure out which line of code will execute next. This technique is very useful, because it helps you find difficult bugs in your programs.
Using the switch Structure JavaScript supplies one more structure that can be very useful when you have one variable that might have a lot of different values. To illustrate, I wrote a program that adds a very crude graphical interface to the Die Roller program from earlier in this chapter:
Creating the Fuzzy Dice Program Figure 2.13 shows a fancier die-rolling program. Appropriately enough, I call it the Fuzzy Dice program. You’ll get to make even better graphics later, but this program demonstrates how you can at least generate crude images. As you can see, the program generates a random number, then draws a text-based image of the die on the alert box. Here’s the code that does the work. Although it looks kind of long, it’s really very repetitive, so don’t let the length of the listing intimidate you.
FIGURE 2.13
Several rolls of the Fuzzy Dice program.
39
fuzzyDice
reload to see another die
The code begins in a now-familiar way: var roll = 0; var die = "";
roll = Math.floor(Math.random() * 6) + 1;
These first few lines set up a variable for the numeric die roll, and roll the die using the technique that you learned earlier in this chapter. (Generating a zero-to-one number, multiplying it by six, and adding one). The die variable contains characters that together create a crude image representing the side of the die that the program rolled.
Using the switch Statement The new stuff begins with the switch statement: switch (roll){
This statement accepts the name of a variable. It tells the computer to start thinking about the value of roll. It ends with a right brace, signifying the beginning of a logical structure. As usual, the code between the braces is indented. The rest of the structure will look at various possible values for the variable: case 1:
This line checks whether roll’s value is equal to ()1. The code between this line and the next case statement will execute if roll is equal to 1.
die = "|--------|\n";
This line assigns a value for the top of the die. The \n part is a special placeholder called newline. This placeholder represents pressing the carriage return. I include this newline so that the die image takes up more than one line on the alert dialog box. The other lines are all pretty similar: die +="| die +="|
|\n"; *
|\n";
die +="|
|\n";
die +="|--------|\n";
The only significant difference between these lines and the first line in the case statement is the += operator. This operator is simply a shortcut for concatenation. die +="|
|\n";
is exactly the same as die = die + "|
|\n";
Using the break Statement At the end of each case statement, you will see a line such as the following: break;
The break statement tells the computer to move on to the end of the switch structure. P TRA
Don’t forget to put a break statement at the end of each case block. If you don’t put a break statement there, the computer will also evaluate the next case block. This is a very common mistake, especially for people who have programmed using languages based on BASIC, which does not require anything like the break command.
Using the default Clause You can add a default clause to a switch structure. The computer executes a default clause only when none of the other conditions are true. I added a default clause to this switch structure, although the computer should never execute the clause. If I designed my algorithm correctly, the value will never be anything other than an integer between 1 and 6. Still, I often include a default clause even when I do not expect the program to need it. Then, the program will be ready for the unexpected. You’ve learned a lot of new syntax in this chapter. Here’s a table of what has been covered so far.
Chapter 2 The Fortune Teller: Random Numbers and the if Statement
The actual code is simply a bunch of assignment statements that add to the die string variable:
41
JavaScript Programming for the Absolute Beginner
42
TABLE 2.3 DISPLAYING DYNAMIC CONTENT Statement
Description
Example
Math.random()
Generates a random number between 0 and 1.
MyVar=Math.random();
Math.floor(varName)
Lops off trailing decimal values, converting a real number to its next lowest integer.
newVar = Math.floor(oldVar);
Branches program logic based on the value of a condition.
if (score > 50) {
}
if (condition){
alert("Winner!");
Denotes code within an structure to execute when the condition is false.
} else {
if
} //end if
switch(varName){
Sets up one variable to check against multiple values.
switch (year){
case value:
Denotes a value for a variable within a switch structure.
case 1964:
break;
Moves execution directly to the end of the current structure. The break statement is used most frequently with switch statements.
break;
default:
Catches any case clauses not caught by case statements within a switch structure.
default:
} else {
expression
alert ("Loser");
alert("Correct");
alert("Incorrect");
Returning to the Fortune Teller Program Finally you are ready to examine the Fortune Teller program from the beginning of this chapter. It turns out to be incredibly simple after everything you’ve learned. In fact, it’s just like the Die Roller program, except I’ve used messages instead of images. Here’s the code:
fortune
43
fortune
reload for another fortune
Chapter 2 The Fortune Teller: Random Numbers and the if Statement
// fortune
JavaScript Programming for the Absolute Beginner
44
Summary In this chapter, you learned how to generate random numbers and refine them so that they fit within a specific range. You also learned how to make the computer’s logic branch. The chapter showed you examples of conditions and explained how programmers use them in if statements. You looked at more advanced variants of the if statement, including the else clause, nested if statements, and the switch structure. In the next chapter, you’ll learn how to use conditions to make the computer repeat certain actions.
EXERCISES 1. Modify the Fortune Teller program so that it contains your own set of fortunes. 2. Write a program that greets the user and asks his or her name. If the user enters your name, compliment him or her on being such a fine programmer. 3. Write a simple quiz program that asks the user five questions. Keep track of how often the user answers correctly, and give the user a score at the end of the quiz. 4. Write a program that randomly pops up a saying as your Web page begins. 5. Write a die program with a “loaded” die. Have the die roll a one half the time and a random number the rest of the time. 6. Certain types of games use multisided dice. Write a program that asks the user how many sides he or she wants, then rolls a die with that many sides and returns the result.
3
C H A P T E R
The Number Guesser: for and while Loops
Y
ou are starting to learn all the important tasks involved in programming. So far, you have learned how to store informa-
tion in variables, send messages to the user, retrieve information from the user, and make your program branch. Now you’ll add another critical element, which is the ability to make your program repeat itself. Specifically, you will learn how to do the following: • Use for loops to repeat a given number of times
• Modify for loops to skip values • Make for loops go backward • Use code tracing to verify your understanding of the code’s behavior • Create while loops • Prevent endless loops • Plan complex programs with pseudocode
JavaScript Programming for the Absolute Beginner
46
Project: The Number Guesser As usual, you’ll start by looking at an example. By the end of this chapter, you will be able to write this program. It’s a classic guessing game. The computer will think of a number between 1 and 100 (see Figure 3.1). The user will try to guess the computer’s number (see Figure 3.2). After each guess, the computer tells the user whether the user’s guess is high, low, or correct (see Figures 3.3 and 3.4). The computer keeps track of the number of turns it takes the user to guess the number. As you can see, this program repeatedly asks the user for a number until the user guesses correctly. Clearly this program relies on the branching behavior that you learned about in the last chapter. After all, the user gets a different message if he or she guessed high or low. In addition to branching, the program also repeats. It repeats the same set of instructions over and over until the user gets the answer right. This repeating behavior is called looping.
Counting Forward Most programming languages offer a couple of types of loops. The first kind you’ll examine is useful for those times when you want something to happen a certain number of times. It’s called a for loop, and the following program, the Racer, shows it in action.
FIGURE 3.1
Here’s the opening screen of the Number Guesser.
FIGURE 3.2
This screen enables the user to input a number.
FIGURE 3.3
The user’s guess was too high.
FIGURE 3.4
The user finally guessed correctly.
Creating the Racer Program
Although you could write this program as a series of alert statements, the program actually has only one alert statement. I got the program to repeat by putting that alert statement inside a for loop. Here’s how the code looks:
Racer
Racer
The program has one variable, called lap, and one alert statement. I nested the statement inside a set of braces. The for statement causes the alert statement to execute 10 times. The advantage of using a loop rather than a number of alert statements is flexibility. If I want the race to be five or 100 laps, all I have to do is change one statement in the code.
FIGURE 3.5
A few of the dialog boxes that pop up as the Racer program runs.
Chapter 3 The Number Guesser: for and while Loops
The Racer program is a silly simulation of a 10-lap race. All it does is present an alert box that tells the user which lap the driver is on. Figure 3.5 shows the program.
47
JavaScript Programming for the Absolute Beginner
48
Using the for Statement The for statement sets up a loop. It is especially useful when you know exactly how many times you want something to repeat. Take another look at this line from the Racer program: for (lap = 1; lap " onClick = "moveSub(EAST)">
As you can see, the HTML code defines the positionable elements and embeds all the sounds as hidden sounds for Netscape. It also provides a bgSound object for IE. When the body of the page loads, it calls the init() function to do some initializing. All four buttons call the moveSub() function, but with a different value indicating which direction to move the submarine.
Making the Global Variables When you are examining a new program, one of the best ways to get an overview is to look at the variables that are defined outside the functions. These should give you some idea of the data that is used in the program. Here’s the code that generates these variables: var isNav = false; var isIE = false; var NORTH = 0; var EAST = 1; var SOUTH = 2; var WEST = 3;
var rows = 10; var cols = 10; var currentRow = 5; var currentCol = 1; var numHits = 0;
var grid = new Array();
The rows and cols variables specify how many rows and columns are in the grid structure. HINT
The actual white grid that the user sees is simply a graphic background, and it has no real relationship to the program. I carefully designed the graphic background so that it would have the right number of rows and columns, but all the program needs is the value of the variables. The background could be anything. My first draft of the program didn’t have a grid drawn on the screen at all, but my primary beta tester (my wife) said that the game was dumb without a visible grid. Always listen to your beta testers, especially if you are married to them!
The currentRow and currentCol variables are used to determine where the submarine currently is inside the grid structure. The numHits variable tracks how many times the player has been pinged. The most critical variable in the game is called grid. It is a two-dimensional array that keeps track of where the patrol boats are. Since the player cannot see the boats directly, it is important to have some way of tracking their position. The grid array does this. The grid variable is the key data structure underlying the program. Everything else in the game somehow relates to this two-dimensional array. Figure 8.17 shows how the grid might actually look. The playing surface is 10 by 10 cells. The program includes a function that analyzes a cell and counts the values in all its neighbors. It would be very difficult to account for all the variations around the edges, so the easiest solution is to add a border of 0s all around. The only grid spaces that you will allow as positions for the sub are in the 1–10 range; however, other cells containing the value 0 surround this range of cells, so any cell the sub is on is guaranteed to have four neighbor cells.
FIGURE 8.17
The grid is a 10×10 matrix with a border of 0s around it.
195 Chapter 8 Dynamic HTML: The Stealth Submarine
The program has variables to determine which browser is active. It also has a series of variables (NORTH, SOUTH, EAST, and WEST) to simplify working with the directions. Since the value of these variables should not change, I capitalized them to remind myself that I consider them constants.
JavaScript Programming for the Absolute Beginner
196
Creating the Functions In addition to looking at the global variables in a program, it’s a great idea to look briefly at the functions provided in a program. This can give you a useful overview of how the program will work. Once you have a wide view, you can look more carefully at the specific functions and see how they work.
checkBrowser() The checkBrowser() function checks the browser and sets isNav or isIE variables to true or false. This section doesn’t repeat the code, because you’ve seen it several times already.
init() The init() function initializes key variables in the game, calls the checkBrowser() routine, calls the grid-creation routine, and positions the sub graphic in the appropriate starting position. The function is called in the onLoad event of the body and whenever the user restarts the game. Here’s the code for the init() function: function init(){ checkBrowser(); makeGrid(); playSound("dive"); currentRow = 5; currentCol = 1; numHits = 0; //updateScore(); //move sub to starting position if (isNav){ document.sub.moveTo(22, 125); } else { document.all.sub.style.pixelLeft = 22; document.all.sub.style.pixelTop = 125; } // end if } // end init
makeGrid() This function turns the grid array into a two-dimensional array to contain the boat data. The resulting grid is actually larger than the number of rows and columns the user will see, to account for the border of 0 cells around the edges. Each element in the grid will contain a 0 (no boat present) or a 1 (there is a boat in this cell). Each square has a 30 percent chance of having a boat in it. The boats are placed randomly. The simplest way to change the difficulty of the game is to change the likelihood that each cell has a boat in it. A value less than .30 makes the game easier, and a value greater than .30 makes the game more difficult. The code for makeGrid() looks like the following: function makeGrid(){ var row = 0;
var col = 0;
grid[row] = new Array(); grid[row][0] = 0; grid[row][cols+1] = 0; } // end row for (col = 0; col 10){ playSound("dive"); alert("You Win!!!"); init(); } // end if
//check for hit if (grid[currentRow][currentCol] == 1){ playSound("ping"); numHits++; if (numHits >=3){ playSound("torp"); alert("You've been sunk!!"); init(); } // end sunk if } // end
hit if
updateScore();
} // end moveSub
For each direction, the routine updates the currentRow and currentCol variables and changes the position of the sub graphic. The moveSub() function then checks whether the sub has reached the open ocean. If so, the player wins, and the program resets the game by calling the init() function. Finally, the moveSub() function checks for a boat in the current cell. If there is one, the function plays the ping sound, then checks whether this is the third ping. If so, the game is over, so the program plays the explosion sound and resets the game with a call to init(). Table 8.2 details the new syntax I’ve covered in this chapter.
Summary This chapter took you through the somewhat frightening world of cross-platform dynamic HTML. You learned how to write code that can determine which browser the user is running. You experimented with cascading style sheet (CSS) syntax as a way to add formatting to your HTML code. You learned how you can use positionable CSS to position your HTML elements more precisely. You built programs that moved an element, changed its text, and played sounds. You have started to grapple with the intricacies of cross-platform design, and have no doubt struggled to make your code work well on either browser. In short, you have earned the right to call yourself a DHTML programmer. In the next chapter, you’ll learn an easier way to develop code that works on any modern browser, that allows you to concentrate more on your game and less on how each browser performs each particular task.
TABLE 8.2
SYNTAX SUMMARY
Description
Example
navigator.appName
Returns the browser’s name as a string. This statement is used for browser detection.
var theBrowser =
Moves a CSS element to (x, y). This statement applies to Netscape only.
document.sub.
Moves a CSS element to a specified coordinate. This statement applies to IE only.
document.all.sub.
Writes new content to a CSS element. This statement applies to Netscape only.
document.output.
Writes a new value to the element. This statement applies to IE only.
document.all.output.
Plays a sound file previously loaded into the specified embed tag. This statement applies to Netscape only.
document.ping.play();
Enables you to assign a new URL to play a sound file.
document.all.
document.layerName. moveTo(x,y)
document.all. layerName.style. pixelLeft document.
navigator.appName;
moveTo(30,100);
style.pixelLeft = 30;
all.layerName. style.pixelTop document.all.sub. style.pixelTop = 100; document.layerName.
document.open();
document.open(), document.layerName. document.write(), document.layerName. document.close(), document.output. document.write ("Hello World!");
innerHTML = "Hello World!";
document.output. document.close(); document.all. layerName.innerHTML document.embedName. play()
document.all. bgSoundName.src
soundPlayer.src = "ping.wav";
Chapter 8 Dynamic HTML: The Stealth Submarine
Statement
201
202 JavaScript Programming for the Absolute Beginner
EXERCISES 1. Modify the sub program so that it has another theme. (You are escaping from prison, sneaking into enemy headquarters, or searching for some type of treasure.) Consider adding multiple levels of difficulty. 2. Make an enhanced version of the sensor that would still return a number, but with the following difference: a boat to the north is 1 point, one to the west is 2, a boat to the south is 4, and a boat to the east is 8. If the user can figure out the code, he or she can always tell exactly where the boats are. As a bonus, this would be a fun way to teach binary notation, if you happen to be a computer science teacher or something similar. 3. The sound techniques described in this chapter can also be used to play .midi files. Build a jukebox that plays a sound file based on a particular button press. Be sure to check with the owner of a file before using it. Change the output of one of your earlier programs so that it uses a CSS element instead of a frame or text box. 4. Make a home page that the user navigates by moving some object around on the page. For example, if you have a page about turtles, let the user move a turtle around the page. When the turtle is at an appropriate place (for example, over the word “photos”), the appropriate page (a photo gallery) automatically pops up in another frame.
9
C H A P T E R
Sprite Animation: The Racer
A
s your programs have become more powerful, you have spent more effort making them function across browsers.
It would be nice to have a trick that would eliminate browser-dependency issues and let you concentrate on writing functional programs. Such a technology exists, and you will learn about it in this chapter. Specifically, you will learn: • What an API library is • How to import external JavaScript libraries • What a sprite is and how to make one • How to move sprites • How to deal with frame animation in sprites • How to react to collisions between sprites • How to determine elapsed time for scorekeeping
JavaScript Programming for the Absolute Beginner
204
The Project: The Racer Program To illustrate all these points, you will build a program that simulates a top-down view of a racing car. The user will be able to control the car through on-screen controls and will have to drive the car as quickly as possible through a series of tracks. Figures 9.1 through 9.4 show the game’s interface. The game looks interesting enough, but some of its features make the game impressive from a technical point of view. The game is designed to be very easy to customize.
FIGURE 9.1
The instruction form contains a button to launch the game.
FIGURE 9.2
You control the car with the little dashboard and the mouse.
205
Avoid the black obstacles; the car stops if you hit one of them.
FIGURE 9.4
The tracks get more difficult as you advance in the game.
It is reasonably simple to build new tracks. As long as you understand the principles, you can easily customize the tracks however you wish. In fact, you could even add a track editor and let the user design new tracks. (That will be one of the exercises at the end of the chapter.) The racing game is reasonably browser-independent; it does not appear to have a single line of browser-checking code, yet it uses positionable elements and dynamic images.
Chapter 9 Sprite Animation: The Racer
FIGURE 9.3
JavaScript Programming for the Absolute Beginner
206
Introducing the Sprite Game developers have been using graphic objects for a long time. They invented a term for a special kind of graphic used in game programming, called the sprite. In theoretical terms, a sprite is an object that can be used in a game environment. The user can move a sprite to a specific position. The sprite should be able to change its image on demand. A sprite also should be able to recognize collisions with other sprites, and it is quite useful if a sprite has some other attributes such as speed and direction. JavaScript does not directly provide the sprite element, but theoretically you can give an object all the characteristics of the sprite object through the techniques that you learned in the last chapter. It would be great if there was some kind of object you could just magically invoke that would act like a sprite. It would be even better if you could just tell the sprite object to move or change its graphic; then you wouldn’t have to worry about what kind of positionable element or layer manipulation was happening behind the scene. IN
THE
R EAL W ORLD
The ability to use APIs is one of the most important skills in modern programming. It is extremely common to have problems that extend beyond the original scope of a language. Programmers working on all kinds of projects can often find or build APIs to help solve such problems. There are APIs for creating graphics, adding special input/output devices, and working with databases and many other kinds of applications.
Fortunately, a number of reusable JavaScript objects have been invented. Several authors have been working on special libraries, called Application Programming Interfaces (APIs), that simplify the tedium of programming with positionable elements in JavaScript. Using these libraries can spare you the challenges of writing cross-platform dynamic HTML and let you focus on the interesting things, such as writing your games and other programs. Throughout the rest of this book, I will demonstrate one library that is optimized for game programming. The library, called gameLib, was written by Scott Porter. This excellent set of programs makes JavaScript game development much easier than it was just a couple of years ago. The latest version of the gameLib library and its documentation are provided on the CD-ROM that accompanies this book. Refer to that documentation for instructions on installing the library.
Creating the Sprite Program You can investigate the gameLib API by examining a very simple program that uses the library to draw a sphere on the screen. Figure 9.5 shows the program’s interface. At first the API will not seem to provide much benefit, but you soon will see how powerful sprite objects can be. Although this page could be produced using standard HTML, it was not. There are a number of interesting things happening in this program.
207
The page looks unremarkable from the user’s point of view.
Importing a Code Library The programs in this chapter all use modules from the gameLib library. Rather than copying all the code of the library, you can use a variation of the script tag to export text files with JavaScript functions. Following is the code that performs that function in the Sprite program:
Sprite
Creating an Image Map for User Input An image map is one way to get input from the user without having to use form controls. I wanted the user to interact with a steering wheel and control pedals, so I drew them in an image and created an HTML image map. If you are working with simple regions (such as rectangles), you can build image maps by hand; however, for more complex images, you may want to use an editor. The CD-ROM that accompanies this book includes The GIMP, a powerful, free image editor (see Figure 9.12). I used the image map tool that comes with The GIMP to generate the image map automatically for this program. The image map tool is available by right-clicking an image, then choosing Filters, Web, then Image Map. Note that instead of specifying a normal URL, I called the turnLeft() function by setting JavaScript:turnLeft() as the URL for this region. The image map editor creates a text file that you can copy and paste into your page.
Chapter 9 Sprite Animation: The Racer
Creating the CarStart Page
225
JavaScript Programming for the Absolute Beginner
226
FIGURE 9.12
Defining an image map in The GIMP.
Using Libraries and Variables The car program is reasonably complex, and it has a number of variables. It is also not surprising that it uses the gameLib core and sprite libraries. Here is the code that sets up the program:
I started by including the libraries for the gameLib core and the sprite library. I also set up variables for the ball background. I added an init() function, which is (as usual) tied to the onload event of the body tag. In the init() function, I set up the sprite offset variables so that the sprites will all appear to be more centered on the page. I also created the background and ball sprites. The ball is set to an initial speed and direction, and its bounces property is set to true. I set the z order of both sprites to ensure that the ball is always visible in front of the background. Finally, I invoked the Gl_start() function to ensure that the library starts up and that the ball starts to move.
295 IN
THE
R EAL W ORLD
K TRIC
Although everything in this version of the program is reasonably basic, be sure to test it as soon as you can. Make sure that it’s working before you move on, because things will break down later, and you’ll want to be sure that you know the last point at which everything was working correctly.
Adding the Paddle Once you’re sure that you have a solid foundation, you can add elements one or two at a time. I chose next to add the mouse handler, because it would involve some other gameLib elements and because it’s a pretty important part of the game.
Creating the Brick02 Program I imported the mouse library, then created a mouse object. I then made a sprite for the paddle and had the sprite follow the mouse. Figure 12.3 shows these additions.
FIGURE 12.3
The paddle moves under mouse control, but the program does not yet have any collision detection.
Chapter 12 The Game Creation Process: The Brick Game
If you are writing a program as part of a group or for some type of customer, it is important to identify several milestones, or points during the program’s development at which you will have some kind of working prototype to show. The entire project doesn’t need to be done at one time, but you have to be able to demonstrate your progress by showing working examples once in a while (or at least you need to do so if you want the customer’s money to keep flowing into your project).
JavaScript Programming for the Absolute Beginner
296
Note that I’m only concerned that the paddle is moving correctly. I actually had to manipulate the X limits and Y limits of the paddle sprite a little bit to get the behavior that I wanted. I’ll deal with the ball bouncing off the paddle or moving past the paddle later. K TRIC
Deciding which tasks you’re going to save for later is one of the hardest parts of actual programming. Have a plan and stick with it. In the case of this particular version of the program, for example, it’s okay to ignore collision detection until the paddle is moving correctly.
Adding the mouse handler was simply a matter of importing the mouse library, like this:
I also had to create a variable for the mouse handler outside the functions. var theMouse;
Finally, I initialized the mouse object in the init() function, as follows: theMouse = Ms_initmouse();
Adding the Paddle Sprite Creating the paddle sprite is reasonably straightforward. I created a suitable image in my paint program, then created a reasonably typical sprite object: //set up paddle paddle = new Sp_Sprite(); paddle.setImage("paddle.gif", 50, 10, 1, 1); paddle.setXlimits(0, 450); paddle.setYlimits(300, 300); paddle.setFrame(0); paddle.setAnimation(0); paddle.follow(theMouse, 0, 0); paddle.collides = true; paddle.switchOn();
Note that I set the paddle to follow the mouse. This was the only programming necessary to get the paddle working.
Bouncing the Ball off the Paddle Once the ball and the paddle are working independently, it is time to make them interact with each other. Remember from the original plan that the ball should bounce off the paddle, but the location of the ball on the paddle should determine the angle at which it bounces.
297
The ball now bounces off the paddle correctly. I added the arrow so you can see how the ball has bounced off the paddle.
Creating the BrickO3 Program In this version of the program, the ball bounces off the paddle. Hitting the ball near the center of the paddle causes the ball to go straight up. Hitting near the ends of the paddle causes the ball to go in a steep angle to the side. Figure 12.4 shows the ball bouncing at an appropriate angle.
Hooking Up the Main Loop The next order of business is to ensure that the game library calls a main loop function every time that the timer goes off (recall from Chapter 9, “Sprite Animation: The Racer,” that this will be 20 times per second in an ideal situation). This is done by adding the following code to the init() function. Gl_hook("mainLoop()");
Determining the Ball’s New Angle The code inside the main loop (at least for now) is dedicated to checking whether the ball is touching the paddle. Here’s the function: function mainLoop(){
//check ball hits paddle if (ball.hasHit(paddle)){ var ballLoc = ball.x - paddle.x;
Chapter 12 The Game Creation Process: The Brick Game
FIGURE 12.4
298
var ballPerc = ballLoc/paddle.width;
JavaScript Programming for the Absolute Beginner
var newX = (5 * ballPerc); newX = Math.floor(newX -1); ball.setDir(newX, 0 - ball.ydir); } // end if
} // end mainLoop
The function starts by checking whether the ball has hit the paddle. If so, the function does some work to set the ball’s new direction. There are a number of ways to do this, but here’s how I did it. I recalled that you can set a sprite’s direction directly in terms of x and y values to add each time that the timer occurs. To make the ball bounce back up, all I have to do is set the ball’s y direction to its negative value. (The ball will be moving down, so its ydir value will be positive. 0 minus the ydir value will make the ball move at exactly the same speed in the opposite direction.) Setting the x direction proved to be a little trickier. I decided to get the ball’s location on the paddle by subtracting the paddle’s x from the ball’s x. I placed the resulting value in the ballLoc variable. I then divided that value by the length of the paddle to get a percentage value. A value of 0 means that the ball was touching the absolute farthest left pixel of the paddle, and a value of 1 indicates the farthest right pixel. I then multiplied this value by 5 to get a value between 0 and 4. I next eliminated the decimal value and subtracted 1, to get values between –2 and 2. I then set the Xdir of the ball to the appropriate value. HINT
Although this algorithm might appear to be completely new, if you look at it a little more closely, you might see that it resembles the strategy used for generating dice introduced in Chapter 6, “Petals around the Rose: Dynamic Output.”
Adding Bricks Getting the paddle and ball to work together is nice, but the name of the game is Bricks, so there should be some bricks somewhere in the game.
Creating the Brick04 Program Bricks aren’t terribly tricky taken one at a time. After all, they are simply sprites. The tricky part is to determine how a group of bricks will work together. It might be easiest to start with just one brick, but I decided to make a bunch of them (see Figure 12.5). I determined to go with a simple array of bricks for now, but I suspect that I’ll need to make the data structure managing the bricks a little more complex later.
Creating the Simple Brick Array The bricks themselves are an array of sprites. I created the array outside the functions, as follows: var brick = new Array(8); var numVisible = 8;
299
This version features one row of bricks. The ball can hit and destroy them.
In addition to the array of bricks, I created another variable, which will be used to keep track of how many bricks are currently showing on the screen.
Creating the Brick Sprites As usual, an array of sprites is easiest to initialize and work with inside a for loop. Here’s the code added to the init() function for creating the array of bricks: //set up bricks for (i = 0; i < 8; i++){ brick[i] = new Sp_Sprite(); brick[i].setImage("brick.gif", 50, 20, 1, 4); brick[i].setXlimits(0, 500); brick[i].setYlimits(0, 200); brick[i].setFrame(0); brick[i].setAnimation(1); brick[i].collides = true; brick[i].bounces = false; brick[i].moveto(i * 55, 10); brick[i].switchOn(); } // end for loop
The brick is a sprite based on a reasonably simple image. I decided to create an image that would be useful in the later stages of game development, when I had multiple bricks. Figure 12.6 shows the image that I created. For this version of the program, I set all the bricks to the brown animation frame (1). I used the moveto() method to place the bricks. Each brick is 50 pixels wide, so by mul-
Chapter 12 The Game Creation Process: The Brick Game
FIGURE 12.5
JavaScript Programming for the Absolute Beginner
300
FIGURE 12.6
The brick image includes a transparent version as well as three colors of traditional bricks.
tiplying i (the for loop counter) by 55, the computer will place the bricks five pixels apart. All other settings of the brick sprites are straightforward.
Checking for Brick Collisions The ball should bounce off the brick as well as the paddle, so I had to add some code to the mainloop() function to provide this behavior: //check ball hits brick for(i = 0; i < 8; i++){ if(ball.hasHit(brick[i])){ ball.setDir(ball.xdir, 0 - ball.ydir); brick[i].switchOff(); brick[i].moveTo(-100, -100); brick[i].collides = false; brick[i].setAnimation(0);
//check for win numVisible--; if (numVisible 300){ alert("you lost the ball!"); ball.moveTo(200, 250); ball.setXYdegs(0); } // end if
The code is reasonably self-explanatory. If the ball moves past a certain y coordinate, the program informs the user that this has happened. Then the code resets the position and direction of the ball to put it back into play.
Adding More Bricks and Sound The Brick game is really coming into focus now. All the essential pieces are in place, so you can start adding some of the embellishments. The most important thing to figure out is how to make rows and columns of bricks. As you probably guessed, this involves making the brick array two-dimensional rather than the single dimension that it was in the last iteration. Also, I decided to put the sounds in at this point. (Actually, I handled the two-dimensional array and sound as two separate steps, but combined them in this explanation because they are both fairly straightforward processes.)
Chapter 12 The Game Creation Process: The Brick Game
I used a for loop to simplify the process of checking all eight bricks. Inside the loop, I looked to see whether the ball had hit the current brick. If so, I reversed the ball’s y direction, but left the x direction alone. I turned the brick off, but I have found that this does not always make the sprite disappear, so I also moved it off the playing field, set its collision property to false, then set the sprite to a blank image.
JavaScript Programming for the Absolute Beginner
302
FIGURE 12.7
The program has rows and columns of bricks. It also features sound effects.
Creating the Brick05 Program This version of the program has a more complex structure of bricks in rows and columns. Figure 12.7 shows the structure. Although you cannot tell from Figure 12.7, the program now has sound effects: When the ball hits a brick, it makes a “tick” sound. When the ball hits the paddle, you hear a “boing” noise, and the game makes a “honk” when the ball moves past the paddle.
Preparing for Two Dimensions of Bricks Converting the brick array from one- to two-dimensional was pretty easy. First, I added a few global variables to make things a little bit easier to follow: var ROWS = 3; var COLS = 8; var NUMBRICKS = ROWS * COLS;
var brick = new Array(ROWS); var numVisible = NUMBRICKS;
I assigned constants to keep track of the number of rows, columns, and bricks, and changed the brick and numVisible variables to reflect these constants. K TRIC
Using constants in this way makes your code much easier to change later. If you want to make a different size grid of bricks, you can just change the value of ROWS and COLS, and everything else is done for you.
Creating a Two-Dimensional Array of Bricks init()
function to reflect
//set up bricks for (row = 0; row < ROWS; row++){ brick[row] = new Array(COLS); for (col = 0; col < COLS; col++){ brick[row][col] = new Sp_Sprite(); brick[row][col].setImage("brick.gif", 50, 20, 1, 4); brick[row][col].setXlimits(0, 500); brick[row][col].setYlimits(0, 200); brick[row][col].setFrame(0); brick[row][col].setAnimation(1); brick[row][col].collides = true; brick[row][col].bounces = false; brick[row][col].moveto(col * 55, row * 22); brick[row][col].switchOn(); } // end 'col' for loop } // end 'row' for loop
The Brick05 program replaces the single for loop used in Brick04 with a pair of nested loops. The outside loop steps through the rows. The first thing that the loop does is to create an array for the row. It then steps through each element of this new array, creating a sprite. Since brick is now a two-dimensional array, you must use two indices to refer to any element in the data structure. All the actual properties and settings of each brick sprite remain exactly the same as in Brick04. The only change to this version is in the way that the bricks are addressed.
Checking whether the Ball Hits a Brick Because the brick data structure is now two-dimensional, you must be careful that all references to it reflect this fact. The program checks every brick in the mainloop() function, so you must also update the code in that function: //check ball hits brick for (row = 0; row < ROWS; row++){ for (col = 0; col < COLS; col++){
if(ball.hasHit(brick[row][col])){ ball.setDir(ball.xdir, 0 - ball.ydir); brick[row][col].switchOff(); brick[row][col].moveTo(-100, -100); brick[row][col].collides = false; brick[row][col].setAnimation(0); sndTick.play();
//check for win
Chapter 12 The Game Creation Process: The Brick Game
You need to update the brick initialization section of the the two-dimensional array:
303
304
numVisible--;
JavaScript Programming for the Absolute Beginner
if (numVisible 300){ sndHonk.play(); ball.moveTo(200, 250); ball.setXYdegs(0); ballsLeft--; updateScore(); } // end if
Using a Cookie to Track the High Score At this point, I was pretty satisfied with the game. However, after returning to the sketch that I drew at the beginning of the project, I decided the game needed one more feature to be complete. The only feature not in place was the ability to add a high score using a cookie (see Figure 12.14). Fortunately, the reorganization of the program that I did in the last step made modification much simpler.
Initializing the Cookie The process for using a cookie is just like the one used in Chapter 11. I added a cookie variable: //high score stuff var scoreCookie; var highScore = 0;
The scoreCookie variable will contain a reference to a cookie object. The variable will contain (you guessed it) the high score.
highScore
319
Now the program keeps track of the high score between visits to the game.
Getting the High Score I added some code to the init() function that checks the cookie for a previous highscore value and loads it into the highScore variable. //get high score scoreCookie = new Gl_cookie("brick score"); if (scoreCookie.value == null){ highScore = 0; } else { highScore = parseInt(scoreCookie.value); } // end if updateScore();
If the cookie has no previous value, the function returns null. So I trapped for that value, then instead sent the value 0 to highScore.
Improving the Code Used at the End of Game The code that handled the end of the game was pretty weak, so I spruced it up a little bit: //check for end of game if (ballsLeft highScore){ highScore = score;
Chapter 12 The Game Creation Process: The Brick Game
FIGURE 12.14
320
alert("New High Score!!");
JavaScript Programming for the Absolute Beginner
scoreCookie.setvalue(score); updateScore(); } // end 'high score' if score = 0; ballsLeft = 3; boardNum = 1; updateScore(); updateBricks(); } // end 'game over' if
Once the game is over, the program informs the user of his or her bad luck, then checks the current score against the high score. If the player achieved a new high score, the function stores the new high score in the cookie.
Summary Although this chapter didn’t introduce much code syntax that was new, you still managed to cover a lot of ground. You looked at the design and creation of a program from the ground up. You looked at the stepwise refinement technique for building programs. You learned a bit about refinement techniques and encapsulation. You saw a program grow from a simple idea to a workable, if not completely polished, game. You have come a very long way in a short time. You should be extremely proud of yourself.
EXERCISES 1. Add new boards to the Brick game. 2. Create new types of bricks with different behaviors. (Make the paddle go backward, change gravity, scramble the bricks, give the player a bomb, and so on.) 3. Design a two-player variant of the game (perhaps one in which one player uses a keyboard, the other the mouse). 4. Write a version of one of the other 1980s classics, such as Space Invaders or Missile Command. 5. Design an adventure game with a hero figure who climbs ladders, jumps, and shoots villains. 6. Use your imagination and come up with something that I can’t even dream of! Have a great time!
A
A P P E N D I X
Syntax Reference
T
he following tables document the syntax elements featured in this book. Please note that this is not a complete refer-
ence to JavaScript or gameLib. Instead, I have tried to focus on the syntax elements that are proven to work across browsers. There are more complete references available on the Web that feature platform-dependent or newer commands. You might also wish to investigate the gameLib documentation that comes on the CD-ROM for the original documentation of that library. You will find some features there that I did not have room to mention in this introductory book.
JavaScript Programming for the Absolute Beginner
322
JavaScript and Dynamic HTML Reference BASIC VARIABLES
AND
IO
Expression
Description
Example
var varName
Create a variable called varName.
var userName;
var varName = value
Create a variable called varName with a starting value of value.
var userName = "";
alert(msg)
Send the string msg to the user in a dialog box.
alert("Hi there");
varName = prompt
Send a dialog box with the string question and a text box. Then return the value to varName.
userName = prompt("What
eval(string)
Evaluate the string expression. If it’s a number, return the number.
number = eval("3");
stringVar.
Convert stringVar to all uppercase letters.
bigName = userName.
Math,random()
Generates a random number between 0 and 1.
MyVar=Math,random();
Math.floor(varName)
Lops off trailing decimal values, converting a real number to its next lowest integer.
newVar = Math.floor
(question)
toUpperCase()
is your name");
toUpperCase()
(oldVar);
DOCUMENT OBJECT PROPERTIES Property
Description
bgColor
The background color assigned to the page’s body
taglastModified
The date that the document was last changed
title
The title of the document
url
The address of the document
domain
The domain name of the document’s host
referrer
If the user got to this page via a hyperlink, this property shows the address of the page that referred to the current one.
323
BRANCHING COMMANDS Description
Example
if (condition)
Branches program logic based on the value of a condition.
if (score > 50) {
Denotes code within an if structure to execute when the condition is false.
} else {
switch(varName){
Sets up one variable to check against multiple values.
switch (year){
case value:
Denotes a value for a variable within a switch structure.
case 1964:
break;
Moves execution directly to the end of the current structure. The break statement is used most frequently with switch statements.
break;
default:
Catches any case clauses not caught by case statements within a switch structure.
default:
{
expression }
} else {
alert("Winner!");
alert
("Loser"); } //end if
alert
("Correct");
alert
("Incorrect");
LOOPING EXPRESSIONS Expression
Description
Example
for (init; condition;
Sets up a loop that executes a set number of times.
for(i=1; i