Data Loading...
The Essential Guide to HTML5_ Using Games to Learn HTML5 and JavaScript ( PDFDrive ) Flipbook PDF
The Essential Guide to HTML5_ Using Games to Learn HTML5 and JavaScript ( PDFDrive )
104 Views
33 Downloads
FLIP PDF 8.05MB
The Essential Guide to HTML5 Using Games to Learn HTML5 and JavaScript — Second Edition — Jeanine Meyer
The Essential Guide to HTML5 Using Games to Learn HTML5 and JavaScript Second Edition
Jeanine Meyer
The Essential Guide to HTML5: Using Games to Learn HTML5 and JavaScript Jeanine Meyer Purchase, NY, USA ISBN-13 (pbk): 978-1-4842-4154-7 ISBN-13 (electronic): 978-1-4842-4155-4 https://doi.org/10.1007/978-1-4842-4155-4 Library of Congress Control Number: 2018962546
Copyright © 2018 by Jeanine Meyer This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the trademark. The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to proprietary rights. While the advice and information in this book are believed to be true and accurate at the date of publication, neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or omissions that may be made. The publisher makes no warranty, express or implied, with respect to the material contained herein. Managing Director, Apress Media LLC: Welmoed Spahr Acquisitions Editor: Louise Corrigan Development Editor: James Markham Coordinating Editor: Nancy Chen Cover designed by eStudioCalamar Cover image designed by Freepik (www.freepik.com) Distributed to the book trade worldwide by Springer Science+Business Media New York, 233 Spring Street, 6th Floor, New York, NY 10013. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail [email protected], or visit www.springeronline.com. Apress Media, LLC is a California LLC and the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM Finance Inc is a Delaware corporation. For information on translations, please e-mail [email protected], or visit http://www.apress.com/ rights-permissions. Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales web page at http://www.apress.com/bulk-sales. Any source code or other supplementary material referenced by the author in this book is available to readers on GitHub via the book's product page, located at www.apress.com/9781484241547. For more detailed information, please visit http://www.apress.com/source-code. Printed on acid-free paper
To Annika, Daniel, Aviva, and Anne, and to Esther and Joseph, who are still in our lives
Table of Contents About the Author����������������������������������������������������������������������������������������������������� xi About the Technical Reviewer������������������������������������������������������������������������������� xiii Acknowledgments���������������������������������������������������������������������������������������������������xv Introduction�����������������������������������������������������������������������������������������������������������xvii Chapter 1: The Basics����������������������������������������������������������������������������������������������� 1 Introduction����������������������������������������������������������������������������������������������������������������������������������� 1 Critical Requirements������������������������������������������������������������������������������������������������������������������� 4 HTML5, CSS, and JavaScript Features������������������������������������������������������������������������������������������ 4 Basic HTML Structure and Tags����������������������������������������������������������������������������������������������� 4 JavaScript Programming������������������������������������������������������������������������������������������������������� 13 Using a Text Editor���������������������������������������������������������������������������������������������������������������������� 15 Building the Applications������������������������������������������������������������������������������������������������������������ 18 Testing and Uploading the Application���������������������������������������������������������������������������������������� 25 Summary������������������������������������������������������������������������������������������������������������������������������������ 26
Chapter 2: Dice Game��������������������������������������������������������������������������������������������� 27 Introduction��������������������������������������������������������������������������������������������������������������������������������� 27 Critical Requirements����������������������������������������������������������������������������������������������������������������� 30 HTML5, CSS, and JavaScript Features���������������������������������������������������������������������������������������� 31 Pseudo-Random Processing and Mathematical Expressions����������������������������������������������� 31 Variables and Assignment Statements���������������������������������������������������������������������������������� 32 Programmer-Defined Functions�������������������������������������������������������������������������������������������� 34 Conditional Statements: if and switch����������������������������������������������������������������������������������� 36 Drawing on the Canvas���������������������������������������������������������������������������������������������������������� 39
v
Table of Contents
Building the Application and Making It Your Own����������������������������������������������������������������������� 51 Throwing a Single Die����������������������������������������������������������������������������������������������������������� 53 Throwing Two Dice���������������������������������������������������������������������������������������������������������������� 60 The Complete Game of Craps������������������������������������������������������������������������������������������������ 67 Testing and Uploading the Application���������������������������������������������������������������������������������������� 78 Summary������������������������������������������������������������������������������������������������������������������������������������ 79
Chapter 3: Bouncing Ball���������������������������������������������������������������������������������������� 81 Introduction��������������������������������������������������������������������������������������������������������������������������������� 81 Critical Requirements����������������������������������������������������������������������������������������������������������������� 85 HTML5, CSS, JavaScript Features����������������������������������������������������������������������������������������������� 86 Drawing a Ball or an Image or Images���������������������������������������������������������������������������������� 86 Building the Application and Making It Your Own��������������������������������������������������������������������� 103 Testing and Uploading the Application�������������������������������������������������������������������������������������� 121 Summary���������������������������������������������������������������������������������������������������������������������������������� 122
Chapter 4: Cannonball and Slingshot������������������������������������������������������������������� 123 Introduction������������������������������������������������������������������������������������������������������������������������������� 123 Critical Requirements��������������������������������������������������������������������������������������������������������������� 127 HTML5, CSS, and JavaScript Features�������������������������������������������������������������������������������������� 129 Arrays and Programmer-Defined Objects���������������������������������������������������������������������������� 129 Rotations and Translations for Drawing������������������������������������������������������������������������������� 132 Drawing Line Segments������������������������������������������������������������������������������������������������������ 137 Mouse Events for Pulling on the Slingshot�������������������������������������������������������������������������� 139 Changing the List of Items Displayed Using Array Splice���������������������������������������������������� 141 Distance Between Points����������������������������������������������������������������������������������������������������� 142 Building the Application and Making It Your Own��������������������������������������������������������������������� 143 Cannonball: With Cannon, Angle, and Speed����������������������������������������������������������������������� 150 Slingshot: Using a Mouse to Set Parameters of Flight�������������������������������������������������������� 160 Testing and Uploading the Application�������������������������������������������������������������������������������������� 172 Summary���������������������������������������������������������������������������������������������������������������������������������� 172
vi
Table of Contents
Chapter 5: The Memory (aka Concentration) Game���������������������������������������������� 175 Introduction������������������������������������������������������������������������������������������������������������������������������� 175 Critical Requirements��������������������������������������������������������������������������������������������������������������� 181 HTML5, CSS, JavaScript Features��������������������������������������������������������������������������������������������� 182 Representing Cards������������������������������������������������������������������������������������������������������������� 183 Using Date for Timing���������������������������������������������������������������������������������������������������������� 184 Providing a Pause���������������������������������������������������������������������������������������������������������������� 185 Drawing Text������������������������������������������������������������������������������������������������������������������������ 186 Drawing Polygons���������������������������������������������������������������������������������������������������������������� 189 Shuffling Cards�������������������������������������������������������������������������������������������������������������������� 190 Implementing Clicking on a Card���������������������������������������������������������������������������������������� 191 Preventing Certain Types of Cheating���������������������������������������������������������������������������������� 192 Building the Application and Making It Your Own��������������������������������������������������������������������� 193 Testing and Uploading the Application�������������������������������������������������������������������������������������� 215 Summary���������������������������������������������������������������������������������������������������������������������������������� 215
Chapter 6: Quiz����������������������������������������������������������������������������������������������������� 217 Introduction������������������������������������������������������������������������������������������������������������������������������� 217 Critical Requirements for a Quiz Game������������������������������������������������������������������������������������� 221 HTML5, CSS, and JavaScript Features�������������������������������������������������������������������������������������� 222 Storing and Retrieving Information in Arrays���������������������������������������������������������������������� 222 Creating HTML During Program Execution�������������������������������������������������������������������������� 225 Using CSS in the Style Element������������������������������������������������������������������������������������������� 227 Responding to Player Moves����������������������������������������������������������������������������������������������� 228 Presenting Audio and Video������������������������������������������������������������������������������������������������� 230 Checking the Player's Answer��������������������������������������������������������������������������������������������� 231 Building the Application and Making It Your Own��������������������������������������������������������������������� 232 Testing and Uploading the Application�������������������������������������������������������������������������������������� 243 Summary���������������������������������������������������������������������������������������������������������������������������������� 243
vii
Table of Contents
Chapter 7: Mazes�������������������������������������������������������������������������������������������������� 245 Introduction������������������������������������������������������������������������������������������������������������������������������� 245 Critical Requirements��������������������������������������������������������������������������������������������������������������� 253 HTML5, CSS, and JavaScript Features�������������������������������������������������������������������������������������� 254 Representation of Walls and the Token������������������������������������������������������������������������������� 254 Mouse Events to Build and Position a Wall�������������������������������������������������������������������������� 255 Detecting the Arrow Keys���������������������������������������������������������������������������������������������������� 256 Collision Detection: Token and Any Wall������������������������������������������������������������������������������ 258 Using Local Storage������������������������������������������������������������������������������������������������������������� 262 Encoding />. This particular tag will display the image held in the file home.gif. These tags are the markup. It is through the use of tags that hyperlinks, images, and other media are included in web pages. Basic HTML can include directives for formatting in a language called Cascading Style Sheets (CSS) and programs for interaction in a language called JavaScript. Browsers, such as Firefox and Chrome, interpret the HTML along with any CSS and JavaScript to produce what we experience when we visit a website. HTML holds the content of the website, with tags providing information on the nature and structure of the content as well as references to images and other media. CSS specifies the formatting. The same content can be formatted in different ways. JavaScript is a programming language that’s used to make the website dynamic and interactive. In all but the smallest working groups, different people may be responsible for the HTML, CSS,
© Jeanine Meyer 2018 J. Meyer, The Essential Guide to HTML5, https://doi.org/10.1007/978-1-4842-4155-4_1
1
Chapter 1
The Basics
and JavaScript, but it’s always a good idea to have a basic understanding of how these different tools work together. If you are already familiar with the basics of HTML and how CSS and JavaScript can be added together, you may want to skip ahead to the next chapter. Still, it may be worth casting your eye over the content in this chapter, to make sure you are up to speed on everything before we start on the first core examples. The latest version of HTML (and its associated CSS and JavaScript) is HTML5. It has generated considerable excitement because of features such as the canvas for displaying pictures and animation; support for video and audio; and tags for defining common document elements such as header, section, and footer. You can create a sophisticated, highly interactive website with HTML5. As of this writing, not all browsers accept all the features, but you can get started learning HTML5, CSS, and JavaScript now. Learning JavaScript will introduce you to general programming concepts that will be beneficial if you try to learn any other programming language or if you work with programmers as part of a team. The approach I’ll use in this book is to explain HTML5, CSS, and JavaScript concepts in the context of specific examples, most of which will be familiar games. Along the way, I’ll use small examples to demonstrate specific features. Hopefully, this will help you both understand what you want to do and appreciate how to do it. You will know where we are headed as I explain the concepts and details. The task for this chapter is to build a web page of links to other websites. In this way, you’ll get a basic understanding of the structure of an HTML document, with a small amount of CSS code and JavaScript code. For this and other examples, please think of how to make the project meaningful to you. The page could be a list of your own projects, favorite sites, or sites on a particular topic. For each site, you’ll see text and a hyperlink. The second example includes some extra formatting in the form of boxes around the text, pictures, and the day’s date and time. Figure 1-1 and Figure 1-2 show the different examples I’ve created.
2
Chapter 1
The Basics
Figure 1-1. An annotated list of games
Figure 1-2. Favorite sites, with extra formatting 3
Chapter 1
The Basics
When you reload the Favorite Sites page, the date and time will change to the current date and time according to your computer.
C ritical Requirements The requirements for the list of links application are the very fundamental requirements for building a web page containing text, links, and images. For the example shown in Figure 1-1, each entry appears as a paragraph. In the example shown in Figure 1-2, in contrast, each entry has a box around it. The second example also includes images and a way to obtain the current day, date, and time. Later applications will require more discussion, but for this one we’ll go straight to how to implement it using HTML, CSS, and JavaScript.
HTML5, CSS, and JavaScript Features As I noted, HTML documents are text, so how do we specify links, pictures, formatting, and coding? The answer is in the markup, that is, the tags. Along with the HTML that defines the content, you’ll typically find CSS styles, which can be specified either inside the HTML document or in an external document. You might also include JavaScript for interactivity, again specified in the HTML document or in an external document. We’ll start with a look at how you can build simple HTML tags, and how you can add inline CSS and JavaScript all within the same document.
Basic HTML Structure and Tags An HTML element begins with a starting tag, which is followed by the element content and an ending tag. The ending tag includes a / symbol followed by the element type, for example /head. Elements can be nested within elements. A standard HTML document looks like this:
Very simple example 4
Chapter 1
The Basics
This will appear as is.
Note that I’ve indented the nested tags here to make them more obvious, but HTML itself ignores this indentation (or whitespace, as it’s known), and you don’t need to add it to your own files. In fact, for most of the examples throughout this book, I don’t indent my code. This document consists of the html element, indicated by the starting tag and ending with the closing tag: . HTML documents typically have a head and a body element, as this one has. This head element contains one element, title. The HTML title shows up different places in different browsers. Figure 1-3 shows the title, “Very Simple Example”, on a tab in Firefox.
Figure 1-3. The HTML title on a tab in Firefox browser In most cases, you will create something within the body of the web page that you’ll think of as a title, but it won’t be the HTML title! Figure 1-3 also shows the body of the web page: the short piece of text. Notice that the words html, head, title, and body do not appear. The tags “told” the browser how to display the HTML document. We can do much more with text, but let’s go on to see how to get images to appear. This requires an img element. Unlike the html, head, and body elements that use starting and ending tags, the img element just uses one tag. It is called a singleton tag. Its element type is img (not image) and you put all the information with the tag itself using what are
5
Chapter 1
The Basics
termed attributes. What information? The most important item is the name of the file that holds the image. The tag
tells the browser to look for a file with the name frog and the file type .jpg. In this case, the browser looks in the same directory or folder as the HTML file. You can also refer to image files in other places and I’ll show this later. The src stands for source. It is termed an attribute of the element. The slash before the > indicates that this is a singleton tag. There are common attributes for different element types, but most element types have additional attributes. Another attribute for img elements is the width attribute.
This specifies that the image should be displayed with a width of 200 pixels. The height will be whatever is necessary to keep the image at its original aspect ratio. If you want specific widths and heights, even if that may distort the image, specify both width and height attributes.
Tip You’ll see examples (maybe even some of mine) in which the closing slash is missing that work just fine. It is considered good practice to include it. Similarly, you’ll see examples in which there are no quotation marks around the name of the file. HTML is more forgiving in terms of syntax (punctuation) than most other programming systems. Finally, you’ll see HTML documents that start with a tag of type!DOCTYPE and have the HTML tag include other information. At this point, we don’t need this so I will keep things as simple as I can (but no simpler, to quote Einstein). Producing hyperlinks is similar to producing images. The type of element for a hyperlink is a and the important attribute is href. Jeanine Meyer's Academic Activities As you can see, this element has a starting and ending tag. The content of the element, whatever is between the two tags—in this case, Jeanine Meyer’s Academic Activities—is what shows up in blue and underlined. The starting tag begins with a. One way to remember this is to think of it as the most important element in HTML, so 6
Chapter 1
The Basics
it uses the first letter of the alphabet. You can also think of an anchor, which is what the a actually stands for, but that isn’t as meaningful for me. The href attribute (think hypertext reference) specifies the website where the browser goes when the hyperlink is clicked. Notice that this is a full web address (called a Universal Resource Locator, or URL, for short). Web addresses can be absolute or relative. An absolute address starts with http://. A relative address is relative to the location of the HTML file. Using relative addressing makes it easier to move your project to a different website and you can indicate the folder one level up by using ../. In my example, the frog.gif file, frogface.gif file, and other image files are located in the same folder as my HTML file. They are there because I put them there! For large projects, many people put all the images in a subfolder called images and write addresses as images/postcard.gif. File management is a big part of creating web pages. We can combine a hyperlink element with an img element to produce a picture on the screen that a user can click on. Remember that elements can be nested within other elements. Instead of putting text after the starting tag, put an tag:
Let’s put these examples together now:
Second example
This will appear as is.
Jeanine Meyer's Academic Activities
7
Chapter 1
The Basics
I created the HTML file, saved it as second.html, and then opened it in the Chrome browser. Figure 1-4 shows what is displayed.
Figure 1-4. Example with images and hyperlinks This produces the text; the image in its original width and height; the image with the width fixed at 200 pixels and height proportional; a hyperlink that will take you to my web page (I promise); and another link that uses an image that will also take you to my web page. However, this isn’t quite what I had in mind. I wanted these elements spaced down the page. This demonstrates something you need to remember: HTML ignores line breaks and other whitespace. If you want a line break, you have to specify it. One way is to use the br singleton tag. I’ll show other ways later. Take a look at the following modified code. Notice that the
tags don’t need to be on a line by themselves.
Second example
This will appear as is.
Jeanine Meyer's Academic Activities
8
Chapter 1
The Basics
Figure 1-5 shows what this code produces.
Figure 1-5. Text, images, and links with line breaks There are many HTML element types: the h1 through h6 heading elements produce text of different sizes; there are various elements for lists and tables, and others for forms. CSS, as we’ll see in a moment, is also used for formatting. You can select different fonts, 9
Chapter 1
The Basics
background colors, and colors for the text, and control the layout of the document. It’s considered good practice to put formatting in CSS, interactivity in JavaScript, and keep the HTML for the content. HTML5 provides new structural elements—such as article, section, footer, and header—putting formatting into the style element and making use of the new elements, called semantic tags, facilitates working with other people. However, even when you’re working just with yourself, separating content, formatting, and behavior lets you easily change the formatting and the interactions. Formatting, including document layout, is a large topic. In this book, I stick to the basics.
Using Cascading Style Sheets CSS is a special language just for formatting. A style is essentially a rule that specifies how a particular element will be formatted. This means you can put style information in a variety of places: a separate file, a style element located in the head element, or a style within the HTML document, perhaps within the one element you want to format in a particular way. The styling information cascades, trickles down, unless a different style is specified. To put it another way, the style closest to the element is the one that’s used. For example, you might use your official company fonts as given in the style section in the head element to flow through most of the text, but include specification within the local element to style one particular piece of text. Because that style is closest to the element, it is the one that is used. The basic format includes an indicator of what is to be formatted followed by one or more directives. In the examples for this chapter, I’ll specify the formatting for elements of type section, namely a border or box around each item, margins, padding, and alignment, and a background of white. The complete HTML document in Listing 1-1 is a mixture (some would say a mess!) of features. The elements body and p (paragraph) are part of the original version of HTML. The section element is one of the new element types added in HTML5. The section element does need formatting, unlike body and p, which have default formatting that the body and each p element will start on a new line. CSS can modify the formatting of old and new element types. Notice that the background color for the text in the section is different from the background color for the text outside the section. In the code in Listing 1-1, I specify styles for the body element (there is just one) and the section element. If I had more than one section element, the styling would apply to each of them. The style for the body specifies a background color and a color for the text. In the beginning, browsers accepted a set of only 16 colors by name, including black, 10
Chapter 1
The Basics
white, red, blue, green, cyan, and pink. However, now the up-to-date browsers accept 140 colors by name. See https://www.w3schools.com/colors/colors_names.asp. You can also specify color using RGB (red green blue) hexadecimal codes, but you’ll need to use a graphics program—such as Adobe Photoshop, Corel Paint Shop Pro, or Adobe Flash Professional—to figure out the RGB values, or you can experiment. I used Paint Shop Pro to determine the RGB values for the green in the frog head picture and used that for the border as well. The text-align directives are just what they sound like: they indicate whether to center the material or align it to the left. The font-size sets the size of text in pixels. Borders are tricky and don’t appear to be consistent across browsers. Here I’ve specified a solid green border of 4 pixels. The width specification for section indicates that the browser should use 85 percent of the window, whatever that is. The specification for p sets the width of the paragraph at 250 pixels. Padding refers to the spacing between the text and the borders of the section. The margin is the spacing between the section and its surroundings.
Listing 1-1. A Complete HTML Document with Styles
CSS example
The background here is tan and the text is the totally arbitrary RED GREEN BLUE➥ value #EE1055
Within the section, the background color is white. There is text with➥ additional HTML markup, followed by a paragraph with text. Then, outside the➥ section there will be text, followed by an image, more text and then a➥ hyperlink.
The border color of the section matches the color of the➥ frog image.
As you may have noticed, I like origami. The next image represents a frog head.
If you want to learn how to fold it, go to the Meyer Family➥ Origami Page
This produces the screen shown in Figure 1-6.
12
Chapter 1
The Basics
Figure 1-6. Sample CSS styles
Tip Don’t be concerned if you don’t understand everything immediately. Modify these examples and make up your own. You’ll find lots of help on the Web. In particular, see the official source for HTML 5 at http://dev.w3.org/html5/ spec/Overview.html. There are many things you can do with CSS. You can use it to specify formatting for types of elements, as shown here; you can specify that elements are part of a class; and you can identify individual elements using the id attribute. In Chapter 6, where we create a quiz, I use CSS to position specific elements in the window and then JavaScript to move them around.
J avaScript Programming JavaScript is a programming language with built-in features for accessing parts of an HTML document, including styles in the CSS element. It is termed a scripting language to distinguish it from compiled languages, such as C++. Compiled languages are translated all at once, prior to use, while scripting languages are interpreted line by line by browsers. This text assumes no prior programming experience or knowledge of JavaScript, but it may help to consult other books, such as Getting Started with JavaScript, by Terry McNavage (friends of ED, 2010), or online sources such as http:// en.wikipedia.org/wiki/JavaScript. Each browser owns its version of JavaScript.
13
Chapter 1
The Basics
An HTML document holds JavaScript in a script element, located in the head element. To display the time and date information as shown in Figure 1-2, I put the following in the head element of the HTML document:
JavaScript, like other programming languages, is made up of statements of various types. In later chapters, I’ll show you assignment statements, compound statements such as if and switch and for statements, and statements that create what are called programmer-defined functions. A function is one or more statements that work together in a block and can be called any time you need that functionality. Functions save writing out the same code over and over. JavaScript supplies many built-in functions. Certain functions are associated with objects (more on this later) and are called methods. The code document.write("hello"); is a JavaScript statement that invokes the write method of the document object with the argument "hello". An argument is additional information passed to a function or method. Statements are terminated by semicolons. This piece of code will write out the literal string of characters h, e, l, l, o as part of the HTML document. The document.write method writes out anything within the parentheses. Since I wanted the information written out to change as the date and time change, I needed a way to access the current date and time, so I used the built-in JavaScript Date function. This function produces an object with the date and time. Later, you’ll see how to use Date objects to compute how long it takes for a player to complete a game. For now, all I want to do is display the current date and time information, and that’s just what this code does: document.write(Date()); To use the formal language of programming: this code calls (invokes) the write method of the document object, a built-in piece of code. The period (.) indicates that the write to be invoked is a method associated with the document produced by the HTML file. So, something is written out as part of the HTML document. What is written out? Whatever is between the opening parenthesis and the closing parenthesis. And what 14
Chapter 1
The Basics
is that? It is the result of the call to the built-in function Date. The Date function gets information maintained by the local computer and hands it off to the write method. Date also requires the use of parentheses, which is why you see so many. The write method displays the date and time information as part of the HTML document, as shown in Figure 1-2. The way these constructs are combined is typical of programming languages. The statement ends with a semicolon. Why not a period? A period has other uses in JavaScript, such as indicating methods and serving as a decimal point for numbers. Natural languages, such as English, and programming languages have much in common—different types of statements; punctuation using certain symbols; and grammar for the correct positioning of elements. In programming, we use the term notation instead of punctuation, and syntax instead of grammar. Both programming languages and natural languages also let you build up very complex statements out of separate parts. However, there is a fundamental difference: As I tell my students, chances are good that much of what I say in class is not grammatically correct, but they’ll still understand me. But when you’re “talking” to a computer via a programming language, your code must be perfect in terms of the grammatical rules of the language to get what you want. The good news is that unlike a human audience, computers do not exhibit impatience or any other human emotion so you can take the time you need to get things right. There’s also some bad news that may take you a while to appreciate. If you make a mistake in grammar—termed a syntactic error—in HTML, CSS, or JavaScript, the browser still tries to display something. It’s up to you figure out what and where the problem is when you don’t get the results you wanted in your work.
Using a Text Editor You build an HTML document using a text editor and you view/test/play the document using a browser. Though you can use any text editor program to write the HTML, I suggest TextPad for PCs and Sublime for Macs. These are shareware, which makes them relatively inexpensive. Don’t use a word processing program, which may insert non-text characters. Notepad also works, although the other tools have benefits such as color- coding that I’ll demonstrate. To use the editor, you open it and type in the code. Figure 1-7 shows what the Sublime screen looks like.
15
Chapter 1
The Basics
Figure 1-7. Starting off in Sublime You will want to save your work frequently and, most important, save it as the file type.html. Do this at the start and then you will gain the benefits of the color-coding. In Sublime, click on File ➤ Save As and then enter the name with the file extension .html, as shown in Figure 1-8.
16
Chapter 1
The Basics
Figure 1-8. Saving a file as type HTML Notice that I gave the file a name and a file extension and that I also specified the folder where I want the file to reside. After saving the file, the window appears as shown in Figure 1-9, with color coding.
17
Chapter 1
The Basics
Figure 1-9. After saving the file as HTML The color coding, which you’ll see only after the file is saved as HTML, indicates tags and quoted strings. This can be valuable for catching many errors. Sublime and the other editors do provide options for changing the color scheme. Assuming that you are using the one shown here, if you see long sections of yellow, the color for quoted strings, it probably means a missing closing quotation marks. By the way, you can use single or double quotation marks but you can’t mix them up. Also, if you copy and paste from Word or PowerPoint, and copy so-called “smart” quotation marks, ones that curve, this will cause problems.
B uilding the Applications You can examine the source code for the following applications at ????. The source code for an HTML document typically includes an HTML document and other files. •
18
The verysimple.html file is complete in itself and was shown in Figure 1-3.
Chapter 1
•
The second.html application was shown in Figure 1-4. Two image files are referenced: frog.gif two times and jhome.gif one time.
•
The third.html, with the garish colors, references two image files: frogface.gif and crane.gif.
•
The games.html file is complete in itself in that it does not reference any image files. If the files mentioned in the href attributes of the a tags are not present, then there will be error messages when the hyperlinks are clicked.
•
The ch01FavoriteSites.html file references two image files: avivasmugmug.jpeg and apressshot.jpeg.
The Basics
Keeping track of files is a critical part of building HTML applications. Now let’s delve into the HTML coding, first for the list of annotated links describing games and then for the favorite sites. The code uses the features described in the previous section. Table 1-1 shows the complete code that produced the display shown in Figure 1-1: paragraphs of text with links to different files, all located in the same folder.
Table 1-1. The “My Games” Annotated Links Code Code
Explanation
Opening html tag.
Opening head tag.
Annotated links
Opening title tag, the title text, and closing title tag.
Opening body tag.
My games
Opening h1 tag, text and then closing h1 tag. This will make “My Games” appear in a big font. The actual font will be the default.
Opening p for paragraph tag.
(continued)
19
Chapter 1
The Basics
Table 1-1. (continued) Code
Explanation
The Dice game presents the game called craps. the attribute href set to the value craps.html. Presumably this is a file in the same folder as this HTML file. The contents of the a element— whatever is between the and the —will be displayed, first in blue and then in mauve once clicked, and underlined.
Closing p tag.
Opening p tag.
The See the previous case. The a element here refers Cannonball is a ballistics to the cannonball.html file and the displayed simulation. A ball appears to move text is Cannonball. on the screen in an arc. The program determines when the ball hits the ground or the target. The player can adjust the speed and the angle.
Closing p tag.
Opening p tag.
The Slingshot simulates shooting a slingshot. A ball moves on the screen, with the angle and speed depending on how far the player has pulled back on the slingshot using the mouse.
See previous. This paragraph contains the hyperlink to slingshot.html.
Closing p tag.
Opening p tag.
(continued)
20
Chapter 1
The Basics
Table 1-1. (continued) Code
Explanation
The Concentration/memory game hyperlink to memory.html. presents a set of plain rectangles you can think of as the backs of cards. The player clicks on first one and then another and pictures are revealed. If the two pictures represent a match, the two cards are removed. Otherwise, the backs are displayed. The game continues until all matches are made. The time elapsed is calculated and displayed.
Closing p tag.
Opening p tag.
The Quiz See previous. This paragraph contains the game presents the player with hyperlink to quiz1.html. 4 boxes holding names of countries and 4 boxes holding names of capital cities. These are selected randomly from a larger list. The player clicks to indicate matches and the boxes are moved to put the guessed boxes together. The program displays whether or not the player is correct.
Closing p tag.
Opening p tag.
(continued)
21
Chapter 1
The Basics
Table 1-1. (continued) Code
Explanation
The Maze program is a multi-stage game. The player builds a maze by using the mouse to build walls. The player then can move a token through the maze. The player can also save the maze on the local computer using a name chosen by the player and retrieve it later, even after closing the browser or turning off the computer.
See previous. This paragraph contains the hyperlink to maze.html.
Closing p tag.
Closing body tag.
Closing html tag.
Once you have created several of your own HTML applications, you may build a document such as this one to serve as your own annotated list. If you use folders, the href links will need to reflect the location in terms of the HTML document. The Favorite Sites code has the features of the annotated list with the addition of formatting: a green box around each item and a picture in two of the three items. See Table 1-2.
22
Chapter 1
The Basics
Table 1-2. The Favorites Sites Code Code
Explanation
Opening html tag.
Opening head tag.
Annotated links
Complete title element: opening and closing tag and Annotated links in between.
Closing style tag.
Closing script tag.
Opening body tag.
Favorite Sites
Text surrounded by h3 and /h3 tags. This makes the text appear somewhat larger than the norm.
Opening article tag.
The
This is a good example for you to take the time to write and run, both because it showcases timing events and also because it will make you appreciate how long a second lasts. The code takes the value out of the secs input field in the form named f, converts that value to a number, adds 1 to that number, and then converts it back to a string to assign as the value of the secs element. Try replacing the single statement inside the increase function with the statement document.f.secs.value = 1+document.f.secs.value; and see what happens. This is a lesson in the difference between numbers and character strings. Please play around with this little example. If you want to make the numbers go up in smaller increments, change the 1000 to 250 and the 1 to .25. This makes the script show quarter-second changes.
96
Chapter 3
Bouncing Ball
If you want to allow your code to stop a particular event, you can set up a global variable (one that’s outside of any function). I use a variable named tev, my shorthand for timing event. var tev; You would then modify the setInterval call to be: tev = setInterval(moveball,100); When you wanted to stop this event, you’d include this code: clearInterval(tev); By the way, if my code invoked the statement with the setInterval function again without issuing a clearInterval, it would be the equivalent of setting up an additional alarm clock. The effect would be to increase the speed. When I describe the cotton candy game, you will notice that my code includes multiple clearInterval statements. To reiterate, the setInterval function sets up a timing event that keeps occurring until it is cleared. If you know you want an event to happen just once, the setTimeout method sets up exactly one event. You can use either method to produce the same results, but JavaScript furnishes both to make things easier. For the bouncing ball application, the moveball function calculates a new position for the ball, does the calculations to check for collisions and when they occur, redirects the ball and draws a new display. This is done over and over—the calls to moveball keep happening because we used setInterval.
Calculating a New Position and Collision Detection Now that we know how to draw, and how to clear and redraw, and we know how to do something at fixed intervals, the challenge is how to calculate the new positions and how to do collision detection. We’ll do this by declaring variables ballx and bally to hold the x and y coordinates of the ball’s center; ballvx and ballvy to hold the amount by which the ball position is to be changed; and boxboundx, inboxboundx, boxboundy, and inboxboundy to indicate a box slightly smaller than the actual box for the collision calculation. The amounts by which the ball position is to be changed are initialized to 4 and 8 (totally arbitrarily) and are changed if and when a player makes a valid change (see the next section) and clicks on the change button. These amounts are termed displacements or deltas and, less formally, velocities or speeds. 97
Chapter 3
Bouncing Ball
The change in direction is pretty simple in this situation. If the ball “hits” a vertical wall, the horizontal displacement must change sign; i.e., if the ball was moving four units to the right and we hit a wall, we want to start adding -4 to its position, which will make it move to the left. The vertical displacement stays the same. The hit is determined by comparing the next horizontal value with the boundary. Similarly, if the ball “hits” a horizontal wall as determined by comparing the vertical position with the appropriate boundary, the vertical displacement changes sign while the horizontal displacement remains the same. The change is for the next iteration. The check for collisions is done four times, that is, for each of the four walls. The calculation consists of comparing the proposed new x or y value, as appropriate, with the boundary condition for the particular wall. The tentative new position is adjusted if the ball center goes past one of the four walls to be exactly at the boundary. This has the effect of making the ball go slightly behind each wall or appear to be squeezed by each wall. The boundary values are set up to be just inside the box with the upper corner at boxx, boxy, a width of boxwidth, and a height of boxheight. I could use a more complex calculation to compare any point on the circle with any point on the walls. However, there is a more fundamental principle involved here. There are no walls and no ball. This is a simulation based on calculations. The calculations are done at intervals. If the ball is moving fast enough and the walls are thin enough, thinner than the ballrad specified here, the ball can escape the box. This is why I do the calculation in terms of the next move and a slightly smaller box. var var var var
boxboundx = boxboundy = inboxboundx inboxboundy
boxwidth+boxx-ballrad; boxheight+boxy-ballrad; = boxx+ballrad; = boxy+ballrad;
Here is the code for the moveandcheck function, the function that checks for collisions and repositions the ball: function moveandcheck() { var nballx = ballx + ballvx; var nbally = bally +ballvy; if (nballx > boxboundx) { ballvx =-ballvx; nballx = boxboundx; }
98
Chapter 3
Bouncing Ball
if (nballx < inboxboundx) { nballx = inboxboundx ballvx = -ballvx; } if (nbally > boxboundy) { nbally = boxboundy; ballvy =-ballvy; } if (nbally < inboxboundy) { nbally = inboxboundy; ballvy = -ballvy; } ballx = nballx; bally = nbally; } You might say that not much actually happens here and you’d be correct. The variables ballx and bally are modified to be used later when things get drawn to the canvas. It is not obvious from this code, but do keep in mind that vertical values (y values) increase going down the screen and horizontal values (x values) increase going from left to right.
Validation Forms, ways of obtaining input from a user/player/client, are part of the original HTML. The form element starts with a tag, which provides a way to specify the action on submitting a form and contains input elements. HTML5 provides new facilities for validating form input. The creator of a form can specify that an input field is of type number as opposed to text, and HTML5 will immediately check that the user/player entered a number. Similarly, we can specify max and min values. The code for the form is
Horizontal velocity
99
Chapter 3
Bouncing Ball
Vertical velocity
The input is still text, that is, a string of characters, but the values are to be text that can be interpreted as a number in the indicated range. Other types of input include "email" and "URL" and it is very handy to have HTML5 check these. Of course, you can check any character string to see if it’s a number using isNumber and more complicated coding, including regular expressions (patterns of characters that can be matched against), to check for valid email addresses and URLs. One common tactic for checking an email address is to make the user type it in twice so you can compare the two and make sure the user hasn’t made any mistakes. We want to take advantage of the work HTML5 will do for us, but we also want to let the user/player know if something is wrong. You can use HTML5 and CSS to do this, by specifying a style for valid and invalid input. input:valid {background:green;} input:invalid {background:red;} HTML5 validation is operational in the latest version of browsers, at least on computers, but you need to decide what you want to do for older browsers and for devices. If you’re using a compliant browser, such as Chrome, you can test the example given in the next section. Notice that the ball keeps bouncing even if an invalid value, say "abc" is entered where a number was specified, because the program continues to use the current settings.
Tip Validating input and generating appropriate feedback to users is important in any application. Among the new features HTML5 provides is a pattern attribute in the input element in which a special language called regular expressions can be used to specify valid input. Put “HTML5 regular expressions” into a search field to find up-to-date information.
100
Chapter 3
Bouncing Ball
Stopping and Resuming Animation Triggered by Buttons When I decided to add stopping and resuming, I decided that an important lesson was how much this could be just an addition, with no change to the rest of the program. A term for what is going on here is event-driven programming. We, the builders, think about the different events more or less distinctly. I also decided to use button elements, a feature introduced as part of HTML5. A button element provides a way to specify the event, in this case, onClick, and the function that will handle the event. The text between the tag and the tag is what appears in the lozenge shaped button. The old way was to use forms, which, for my example, would have meant multiple forms. The following code produces the two buttons. The next section describes the significance of the return statement. The is what is called an entity and produces a space but does not force a line break. STOP RESUME I now owe you the definition of the stopcc function and the resume function. The task for the stopcc function is to stop the moving of the cotton candy image over the background. You know how to do that: invoke clearInterval. My code does need to do a few more things. Because I will want to resume the bouncing, I write code to save the ballvx and ballvy values. This may be unnecessary, but certain cases seem to require it. The code also invokes moveBall to produce one more picture. The use of return is explained in the next section. The code follows. function stopcc() { clearInterval(tid); stoppedx = ballvx; stoppedy = ballvy; moveBall(); return false; } The resume function does contain a call to setInterval, but I need to do something else to protect the players from themselves. If a player clicked on the resume button without having stopped the animation, or just to see what would happen, then invoking multiple setIntervals would produce multiple timing events. This, in turn, would have the effect of making the bouncing appear faster and faster. To present this, I insert a call 101
Chapter 3
Bouncing Ball
to clearInterval. If there is no timing event in place, nothing will happen. My code resets ballvx and ballvy using the previously saved values. This may be not necessary, but it is a precaution. function resume(){ clearInterval(tid); ballvx = stoppedx; ballvy = stoppedy; tid = setInterval(moveball,100); return false; }
HTML Page Reload Before continuing, I want to mention some issues that may cause unexpected problems. Browsers come with reload/refresh buttons. The document is reloaded when the button is clicked. We used this in the simple die throw application in Chapter 2. However, at times you may want to prevent a reload and, in such cases, you can put a return (false); in functions that don’t have anything to return to keep the page from reloading. When a document has a form, reloading does not always reinitialize the form input. You may need to leave the page and then reload it using the full URL. Lastly, browsers attempt to use files previously downloaded to the client (user) computer rather than requesting files from a server based on inspection of the date and time. The files on the client computer are stored in what is called the cache. If you think you made a change but the browser isn’t displaying the latest version, you may need to take steps such as clearing the cache.
P reloading Images Computers are so fast and, in general, our perception is sufficiently slow, that we expect no delays in anything we do. However, images on websites must be downloaded from the server to our local computer and large images are, obviously, large files. Actually, I should make another point. Our modern cameras produce images made up of thousands of pixels, which is termed high resolution. This makes the files large. To make sure that the images are ready for use, one trick is to create img elements holding the images in the body element. For this example, this includes the background photo and 102
Chapter 3
Bouncing Ball
the cotton candy photo. The files will be loaded before the init function is invoked by action of the onLoad attribute in the body tag. The fully loaded background image will be available to be drawn before the cotton candy image is drawn on top of it. The challenge is how to prevent those two images from being displayed. The answer is to include the following directive in the style element. img {visibility: hidden;} The CSS directive stops any img file from being displayed. In my example, the img elements are never displayed. What are displayed are the Image elements created and manipulated by code.
Building the Application and Making It Your Own I will now explain the code for the basic bouncing ball application; the application that uses an image for the ball and gradients for the walls; the application that validates the input and the bouncing cotton candy. Table 3-1 shows all the function calls and what is being called. The table includes the functions for all four applications. The stopcc and resume functions are only present in the fourth application.
Table 3-1. Functions in the Bouncing Ball Applications Function
Invoked By/Called By
Calls
init
Action of onLoad in the body tag
moveball
moveball
Invoked directly by init and by action of setInterval
moveandcheck
moveandcheck
Invoked by moveball
change
Invoked by action of onSubmit in the form tag
stopcc
Invoked by action of onClick in a button tag
resume
Invoked by action of onClick in a button tag
moveBall
The moveandcheck code could be part of the moveball function. I chose to separate it because it is a good practice to define functions that perform specific actions. Generally, more, smaller functions are better than fewer, larger ones when you’re developing applications. By the way, when doing your own programming, don’t forget to put 103
Chapter 3
Bouncing Ball
comments in the code as described in Chapter 2. And add blank lines to make the code more readable. Table 3-2 shows the code for the basic bouncing ball application and explains what each line does.
Table 3-2. The Bouncing Ball Application Code
Explanation
Start html.
Start head.
Bouncing Ball➥ with inputs
Complete the title element.
Close script.
Close head.
Start body element. Set up call to init function.
Start of canvas element.
Your browser doesn't support the ➥ HTML5 element canvas.
Message for non-compliant browsers.
Close canvas element.
Line break.
Start of form. Give name and id (may need for some browsers). Set up action on submit button.
H orizontal velocity
Line break.
(continued) 107
Chapter 3
Bouncing Ball
Table 3-2. (continued) Code V ertical velocity
Explanation Label an input field for vertical velocity.
Submit button.
Close form.
Close body.
Close html.
The application that uses an image as the ball and the gradient-filled walls is very similar. Table 3-3 shows all the code—but I just comment the code that is different. I’m not being lazy; the idea is to let you see how each application is built on the previous one.
Table 3-3. The Second Application, with an Image as the Ball and Gradient-Filled Walls Code
Explanation
Bouncing Ball with inputs
(continued)
112
Chapter 3
Bouncing Ball
Table 3-3. (continued) Code
Explanation
This browser doesn't support ➥ the HTML5 canvas element.
H orizontal velocity
V ertical velocity
I chose to put the modest change of the style information building on the first application. Table 3-4 shows the third bouncing ball application, with form validation. Again, I have only commented the new code, but I include all the code for completeness sake.
113
Chapter 3
Bouncing Ball
Table 3-4. The Third Bouncing Ball Application, with Form Validation Code
Explanation
Bouncing Ball with inputs
Your browser doesn't support the HTML5 element canvas.
H orizontal velocity
V ertical velocity
117
Chapter 3
Bouncing Ball
The fourth application is the game with the bouncing cotton candy. The first thing I did was outside the scope of the HTML/JavaScript/CSS programming. I used pixlr to extract the portion of the original picture of the cotton candy and used another photo to fill in the missing space. I am not going to include the complete code for the cotton candy game, but just indicate the additions.
The body tag. Note that the init function is invoked when everything is loaded, including the image files mentioned in the tags.
...
... STOP
Button to invoke stopcc. Note use of to position the next button.
(continued)
119
Chapter 3
Bouncing Ball
RESUME
Button to invoke resume.
An img tag to cause the candy.png file to be fully loaded before anything happens.
An img tag to cause the reunion.jpg file to be fully loaded before anything happens.
There are many ways you can make applications like this for yourself. You can select your own image for the ball and experiment with the colors for the walls, with or without the gradients. You can change the position and the dimensions of each wall. You can add text and HTML markup to the page. You can change the look of the form. You can include more than one ball, keeping track of the positions of each. If you decide to use two balls, you need two sets of variables and two lines of code for each one line you had before. One systematic way to do this is to use the search function in the editor to find all instances of ball and, for each line, substitute two lines, so in place of ballx, you have ball1x and ball2x, and in place of the var ballx = 50; use var ball1x = 50; var ball2x = 250; This puts the second ball 200 pixels over on the canvas. You would also need a second set of all the comparisons for the walls. If you want to use more than two balls, you may want to consider using arrays. Subsequent chapters will show you how to handle sets of objects. You also can try writing code that slows the ball each time it hits a wall. This is a nice effect and does simulate a real physical result. In each of the places in the code where the direction is changed by changing the sign of the appropriate variable, add in a factor
120
Chapter 3
Bouncing Ball
to decrease the absolute value. For example, if I chose to decrease the value by 10%, I would write if (nballx > boxboundx) { ballvx =-ballvx *.9; nballx = boxboundx; } This means that the incremental change in the vertical direction would go down to 90% of what it was. You can build on and/or be inspired by the cotton candy game by using your own photos and making the game more game-like. Think about a test for the resting place being good enough. Limit the number of STOP and RESUME actions. Study the examples in the rest of this text (and move on the HTML5 and JavaScript projects) to learn other actions, such as use of mouse or touch.
Testing and Uploading the Application The first and third applications are complete in the HTML documents. The second and fourth applications require the image files to be present in the same folder. You can access files anywhere on the Web, but you need to make sure you include the correct address. For example, if you upload the HTML document to a folder called mygames and upload pearl.jpg to a subfolder of mygames named images, the line indicating this must be img.src = "images/pearl.jpg"; You must also use accurate file extensions, such as JPG, that indicate the correct file type. Some browsers are forgiving but many are not. You can try to submit bad > var ctx; function init(){ ctx = document.getElementById('canvas').getContext('2d'); ctx.fillStyle = "rgb(250,0,0)"; ctx.fillRect(50,50,100,200); ctx.fillStyle = "rgb(0,0,250)"; ctx.fillRect(50,50,5,5); }
Your browser doesn't support the HTML5 element canvas.
132
Chapter 4
Cannonball and Slingshot
The result is shown in Figure 4-6.
Figure 4-6. Rectangle (no rotation) In this exercise, the goal is to rotate the large rectangle, pivoting on the upper-left corner where the small blue square is. I want the rotation to be counterclockwise. One slight complication, common to most programming languages, is that the angle input for rotations as well as the trigonometry functions must be in radians, not degrees. Radians were explained in Chapter 2, but here’s a reminder. Instead of 360 degrees in a full circle, the measurement is based on two times the mathematical constant pi radians in a circle. Fortunately, we can use the built-in feature of JavaScript, Math.PI. One pi radians is equivalent to 180 degrees and pi divided by 2 is equivalent to a right angle, 90 degrees. To specify a rotation of 30 degrees, we use pi divided by 6 or, in coding, Math. PI/6. To change the init function given previously to do a rotation, I put in a rotation of negative pi divided by 6 (equivalent to 30 degrees going counterclockwise), draw the red rectangle, and then rotate back, undo the rotation, to draw the blue square: function init(){ ctx = document.getElementById('canvas').getContext('2d'); ctx.fillStyle = "rgb(250,0,0)"; ctx.rotate(-Math.PI/6); ctx.fillRect(50,50,100,200); ctx.rotate(Math.PI/6); 133
Chapter 4
Cannonball and Slingshot
ctx.fillStyle = "rgb(0,0,250)"; ctx.fillRect(50,50,5,5); } Unfortunately, the drawing in Figure 4-7 is not what I wanted.
Figure 4-7. Drawing and rotating a rectangle The problem is the rotation point is at the origin, (0,0) and not at the corner of the red rectangle. So, I need to write code to perform a translation to reset the origin, then the rotation, then a translation back in order to draw the next item at the correct place. I can do this using features of HTML5. All drawing on the canvas is done in terms of a coordinate system, and I can use the save and restore operations to save the current coordinate system—the position and orientation of the axes—and then restore it to make additional drawings. Here’s the code. function init(){ ctx = document.getElementById('canvas').getContext('2d'); ctx.fillStyle = "rgb(250,0,0)"; ctx.save(); ctx.translate(50,50); //move origin ctx.rotate(-Math.PI/6); //do rotation ctx.translate(-50,-50); // move origin back ctx.fillRect(50,50,100,200); //draw rectangle ctx.restore(); //undo all the transformations ctx.fillStyle = "rgb(0,0,250)"; ctx.fillRect(50,50,5,5); //draw little blue square } 134
Chapter 4
Cannonball and Slingshot
The rotate method expects an angle in radian units and clockwise is the positive direction. So my code is rotating 30 degrees counterclockwise, producing what I had in mind, as shown in Figure 4-8.
Figure 4-8. Save, translate, rotate, translate, restore Again, I urge you to modify this example to help you understand transformations and radians. Make small changes, one statement at a time. By the way, we can’t expect our players to put in angles using radians. They, and we, are too accustomed to degrees (90 degrees is a right angle, 180 degrees is your arc when you make a U-turn, etc.). The program must do the work. The conversion from degrees to radians is to multiply by pi/180.
Note Most programming languages use radians for angles in trig functions as well as rotation operations. With this background, I add to the information in the everything array indications as to whether there is to be a rotation and, if so, the required translation point. This was my idea. It has nothing to do with HTML5 or JavaScript, and it could have been done differently. The underlying task is to create and maintain information on objects in the simulated scene. The canvas feature of HTML5 provides a way to draw pictures and display images, but it does not retain information on objects! The items in the everything array for the second and third applications are themselves arrays. The first (0th index) value points to the object. The second (1st index) is true or false. A value of true means that a rotation angle value and x and y values for 135
Chapter 4
Cannonball and Slingshot
translation follow. In practice, this means that the inner arrays have either two values, with the last one being false, or five values.
Note At this point, you may be thinking: she set up a general system just to rotate the cannon. Why not put in something just for the cannon? The answer is we could, but the general system does work and something just for the cannon might have had just as much coding. The first application uses horizontal and vertical displacement values picked up from the form. The player must think of the two separate values. For the second application, the player inputs two values again, but they are different. One is the speed out of the mouth of the cannon and the other is the angle of the cannon. The program does the rest. The initial and unchanging horizontal displacement and the initial vertical displacement are calculated from the player’s input: the velocity out of the cannon and an angle. The calculation is based on standard trigonometry. Luckily, JavaScript provides the trig functions as part of the Math class of built-in methods. Figure 4-9 shows the calculation of the displacement values from the out of cannon and angle values specified by the player. The minus sign for the vertical is due to the way JavaScript screen coordinates have y values increasing going down the screen.
Figure 4-9. Calculating horizontal * vertical displacements
136
Chapter 4
Cannonball and Slingshot
At this point, you may want to skip ahead to read about the implementation of the cannonball applications. You can then come back to read about what is required for the slingshot.
Drawing Line Segments For the slingshot application, I have added a new object type by defining two functions, Sling and drawsling. My idealized slingshot is represented by four positions, as shown in Figure 4-10. Please understand that we could have done this in a number of different ways.
Figure 4-10. The idealized slingshot The Sling function resembles the other constructors, for example, Ball. function Sling(bx,by,s1x,s1y,s2x,s2y,s3x,s3y,stylestring) { this.bx = bx; this.by = by; this.s1x = s1x; this.s1y = s1y; this.s2x = s2x; this.s2y = s2y; this.s3x = s3x; this.s3y = s3y; this.strokeStyle = stylestring; 137
Chapter 4
Cannonball and Slingshot
this.draw = drawsling; this.moveit = movesling; } The Sling function sets up drawsling to be the function invoked whenever draw is used in connection with a Sling object. Though it does not happen in the current application, movesling would be invoked if you or I build on this application to move the location of the slingshot. Drawing the slingshot consists of drawing four line segments based on the four points. The bx,by point will change as I’ll describe in the next section. HTML5 lets us draw line segments as part of a path. We’ve already used paths for drawing circles. You can draw a path as a stroke or as a fill. For the circles, we used the fill method, but for the slingshot, I just want lines. Drawing a line may involve two steps: move to one end of the line and then draw it. HTML5 provides the moveTo and lineTo methods. The path is not drawn until the stroke or fill method is invoked. The drawsling function is a good illustration of line drawing. function drawsling() { ctx.strokeStyle = this.strokeStyle; ctx.lineWidth = 4; ctx.beginPath(); ctx.moveTo(this.bx,this.by); ctx.lineTo(this.s1x,this.s1y); ctx.moveTo(this.bx,this.by); ctx.lineTo(this.s2x,this.s2y); ctx.moveTo(this.s1x,this.s1y); ctx.lineTo(this.s2x,this.s2y); ctx.lineTo(this.s3x,this.s3y); ctx.stroke(); } It does the following:
138
•
Adds to path a line from bx,by to s1x,s1y
•
Adds to path a line from bx,by to s2x,s2y
•
Adds to path a line from s1x,s1y to s2x,s2y
•
Adds to path a line from s2x,s2y to s3x,s3y
Chapter 4
Cannonball and Slingshot
As always, the way to learn this is to experiment with your own designs. If there’s no invocation of moveTo, the next lineTo draws from the destination of the last lineTo. Think of holding a pen in your hand and either moving it on the paper or lifting it up and moving without drawing anything. You also can connect arcs. Chapter 5 demonstrates drawing polygons.
Mouse Events for Pulling on the Slingshot The slingshot application replaces form input with mouse drag and drop operations. This is appealing because it’s closer to the physical act of pulling back on a slingshot. When the player presses the mouse button, it is the first of a sequence of events to be managed by the program. Here is pseudo-code for what needs to be done. When the player presses the mouse button, check if the mouse is on top of the ball. If not, do nothing. If so, set a variable named inmotion. If the mouse is moving, check inmotion. If it is set, move the ball and the strings of the slingshot. Keep doing this until the mouse button is released. When the player releases the mouse button, reset inmotion to false. Calculate the angle and initial velocity of the ball and, from these, calculate the horizontal velocity and the initial vertical velocity. Start the ball moving. You can use HTML5 and JavaScript to set up event handling for pressing the standard (left) mouse button, moving the mouse, and releasing the mouse button. The code uses a method based on the canvas element directly, not the so-called context. Here is the code, which is in the init function: canvas1 = document.getElementById('canvas'); canvas1.addEventListener('mousedown',findball,false); canvas1.addEventListener('mousemove',moveit,false); canvas1.addEventListener('mouseup',finish,false); Now because this event is in terms of the whole canvas, the findball function must determine if the mouse is over the ball. The first task is to get the mouse x and y coordinates. When I wrote this originally, different browsers implement mouse events in different ways. The following was the recommended coding and works for Firefox, Chrome, and Safari. When other browsers, such as Internet Explorer, support HTML5, this code will need to be checked and possibly modified. Note that the coding inside of the canvas element does return a message when canvas is not supported. 139
Chapter 4
Cannonball and Slingshot
if ( ev.layerX || ev.layerX==0) { mx= ev.layerX; my = ev.layerY; } else if (ev.offsetX || ev.offsetX==0 ) { mx = ev.offsetX; my = ev.offsetY; } This works because if ev.layerX does not exist, its value will be interpreted as false. If ev.layerX does exist but has value 0, its value will also be interpreted as false, but ev. layerX==0 will be true. Think of this code as saying: is there a good ev.layerX value? If so, let’s use it. Otherwise, let’s try ev.offsetX. If neither of these work, mx and my will not get set and I should add another else clause to tell the player that the code doesn’t work in his browser. Now, the next step is to determine if the (mx,my) point is on the ball. I am repeating myself, but it is important to understand that the ball is now the equivalent of ink or paint on canvas and we can’t go any further without determining whether the (mx,my) point is on top of the ball. How do we do this? We can calculate how far (mx,my) is from the center of the ball and see if that’s less than the radius of the ball. There is a standard formula for distance in the plane. My code is a slight variation on this idea. It makes the determination by calculating the square of the distance and comparing it to the square of the ball’s radius. I do this to avoid computing the square root. If the mouse click was on the ball, that is, within a radius distance of the center of the ball, this function sets the global variable inmotion to true. The findball function ends with a call to drawall(). Whenever the mouse moves, there’s a call to the moveit function where we check whether inmotion is true. If it isn’t, nothing happens. If it is, the same code as before is used to get the mouse coordinates and the ball’s center, and the bx,by values for the slingshot are set to the mouse coordinates. This has the effect of dragging the ball and stretching the slingshot strings. When the mouse button is released, we call the finish function, which doesn’t do anything if inmotion is not true. When would this happen? If the player is moving the mouse around not on the ball and pressing and releasing the button.
140
Chapter 4
Cannonball and Slingshot
If inmotion is true, the function immediately sets it to false and does the calculations to determine the flight of the ball, generating the information that in the earlier cannonball application was entered by the player using a form. The information is the angle with the horizontal and the distance of the ball to the straight part of the slingshot. This is the angle formed by (bx,by) to (s1x, s1y), and the horizontal and the distance from (bx,by) to (s1x, s1y), more precisely, the square of the distance. I use Math.atan2 to do these calculations: calculating an angle from change in x and change in y. This is a variant of the arctangent function. I use the distsq function to determine the square of the distance from (bx,by) to (s1x, s1y). I want to make the velocity dependent on this value. Pulling the strings back farther would mean a faster flight. I did some experiments and decided that using the square and dividing by 700 produced a nice arc. The last step is to put in a call first to drawall() and then to setInterval to set up the timing event. Again, finish does an analogous job to fire in the cannonball applications. In the first application, our player entered the horizontal and initial vertical values. In the second application, the player entered an angle (in degrees) and a velocity out of the mouth of the cannon, and the program did the rest. In slingshot, we did away with a form and numbers and provided a way for the player to pull back, or virtually pull back, on a slingshot. The program had more to do, both in terms of responding to mouse events and calculations. Please note that I make no provisions for the player being silly and aiming the ball away from the chicken or aiming it straight up or pulling the ball down below the ground. In the latter case, the ball moves up and stops at the ground. Experiment and decide what checks and messages you would include.
Changing the List of Items Displayed Using Array Splice The last task to explain is the replacement of the target image with another picture. Since I wanted two different effects, I used different approaches. For the second application, I wanted the ball to disappear along with the original target and display what I set up in the variable htarget. What I do is keep track of where the original target was placed on the everything array and remove it and substitute htarget. Similarly, I remove the ball from the everything array. For the slingshot operation, I don’t remove the target but change its img property to be feathers. Note that in the code, chicken and feathers are Image objects. Each has a src property that points to a file. 141
Chapter 4
Cannonball and Slingshot
var chicken = new Image(); chicken.src = "chicken.jpg"; var feathers = new Image(); feathers.src = "feathers.gif"; For both of these operations, I use the array method splice. It has two forms: you can just remove any number of elements or you can remove and then insert elements. The general form of splice is arrayname.splice(index where splice is to occur, number of items to be removed, new item(s) to be added) If more than one item is to be added, there are more arguments. In my code, I add a single item, which is itself an array. My representation of objects in the everything array uses an array for each object. The second argument of the array indicates if there is any rotation. The following two lines of code do what I need: remove the target, stick in htarget with no rotation, and then remove the ball. everything.splice(targetindex,1,[htarget,false]); everything.splice(ballindex,1); By the way, if I simply wanted to remove the last item in an array, I could use the method pop. In this situation, however, the target may be somewhere in the middle of the everything array, so I need to write code to keep track of its index value.
Distance Between Points There are two places in the slingshot program in which I use the distance between points or, more accurately, the square of the distance. I need to find out if the mouse cursor is on top of the ball and I want to make the initial velocity—the equivalent of the velocity out of the cannon— depending on the stretch, so to speak, of the slingshot, the distance (bx,by) to (s1x, s1y). The formula for the distance between two points x1,y1 and x2,y2 is the square root of the sum of the squares of (x1-x2) and (y1-y2). I decided to avoid the computation of taking a square root by just computing the sum of the squares. This provides the same test for the mouse cursor being on top of the ball. For the other task, I decided it was okay to use the square of the distance for the initial velocity. I experimented with some numbers and, as I mentioned earlier, 700 seemed to work.
142
Chapter 4
Cannonball and Slingshot
Building the Application and Making It Your Own Let’s now take a look at the code for the basic firing of a cannonball, without a cannon, based on horizontal and initial vertical speeds; the firing of a cannonball from a cannon, based on angle and initial speed out of the cannon; and the slingshot, based on angle and initial speed determined from the position of the mouse. As in previous chapters, I’ll present the functions and what they call or are called by for each application. In this case, the tables are similar, though not identical, for all three applications. The calling is more varied than previous examples in that there are situations in which functions are invoked because they are named as methods of a programmer-defined object or as part of a declaration (var) statement. This is a characteristic of object-oriented, event-driven programming. I’ll also present the complete code for each application in its own table, along with an explanation of what each line does. Table 4-1 shows the functions for the basic cannonball application.
Table 4-1. Functions in the Simplest Cannonball Application Function
Invoked By/Called By
Calls
init
Action of the onLoad in body tag
drawall
drawall
Invoked directly by init, fire, change Calls the draw method of all objects in the everything array. These are the functions drawball, drawrects
fire
Invoked by action of the onSubmit attribute in form
drawall
change
Invoked by action of the setInterval function called in fire
drawall, calls the moveit method of cball, which is moveball
Ball
Invoked directly by code in a var statement
Myrectangle
Invoked directly by code in a var statement
drawball
Invoked by call of the draw method for the one Ball object
(continued) 143
Chapter 4
Cannonball and Slingshot
Table 4-1. (continued) Function
Invoked By/Called By
Calls
drawrects
Invoked by call of the draw method for the target object
moveball
Invoked by call of the moveit method for the one Ball object
Table 4-2 shows the complete code for the simplest application, with the ball moving in an arc and no actual cannon.
Table 4-2. The First Cannonball Application Code
Explanation
Opening html tag.
Opening head tag.
Cannonball
Complete title element.
Close script element.
Close head element.
Open body and set call to init.
Define the canvas element.
Your browser doesn't support the HTML5 element canvas.
Warning to users of non-compliant browsers.
Close the canvas element.
Line break.
Starting form tag, with name and ID. This sets up call to fire.
Set velocities and fire cannonball.
Label and line break.
(continued)
149
Chapter 4
Cannonball and Slingshot
Table 4-2. (continued) Code
Explanation
Horizontal displacement
Label and specification of input field.
Line break.
Initial vertical displacement
Label and specification of input field.
Submit input element.
Close form element.
Close body element.
Close html element.
You certainly can make improvements to this application, but it probably makes more sense to first make sure you understand it as is and then move on to the next.
Cannonball: With Cannon, Angle, and Speed Our next application adds a rectangle to represent the cannon, a picture for the original target instead of the simple rectangle used in the first application, and a second picture for the hit target. The cannon rotates as specified by input in the form. I made the everything array an array of arrays because I needed a way to add the rotation and translation information. I also decided to make the result more dramatic when the cannonball hits the target. This means the code in the change function for checking for a collision is the same, but the code in the if-true clause removes the old target, puts in the hit target, and removes the ball. Now, having said all this, most of the coding is the same. Table 4-3, which shows the functions, has two additional lines for Picture and drawAnImage.
150
Chapter 4
Cannonball and Slingshot
Table 4-3. Functions in the Second Cannonball Application Function
Invoked By/Called By
Calls
init
Action of the onLoad in body tag
drawall
drawall
Invoked directly by init,fire,change
Calls the draw method of all objects in the everything array. These are the functions drawball and drawrects
fire
Invoked by action of the onSubmit attribute drawall in form
change
Invoked by action of the setInterval function called in fire
Ball
Invoked directly by code in a var statement
Myrectangle
Invoked directly by code in a var statement
drawball
Invoked by call of the draw method for the one Ball object
drawrects
Invoked by call of the draw method for the target object
moveball
Invoked by call of the moveit method for the one Ball object
Picture
Invoked directly by code in var statements
drawAnImage
Invoked by call of the draw method for a Picture object
drawall, calls the moveit method of cball, which is moveball
Table 4-4 shows the complete code for the second application, but only the changed lines have comments.
151
Chapter 4
Cannonball and Slingshot
Table 4-4. The Second Cannonball Application Code
Explanation
Cannonball
(continued) 158
Chapter 4
Cannonball and Slingshot
Table 4-4. (continued) Code
Explanation
Your browser doesn't support the HTML5 element canvas.
Set velocity, angle and fire cannonball.
Velocity out of cannon
Label indicating that this is the velocity out of mouth of cannon.
Angle
Label indicating that this is the angle of the cannon.
This application provides many possibilities for you to make it your own. You can change the cannon, the ball, the ground, and the target. If you don’t want to use images, you can use drawings for the target and the hit target. You can draw other things on the canvas. You just need to make sure that the cannonball (or whatever you set your projectile to be) is on top or wherever you want it to be. You could, for example, make the ground cover up the ball. You can use an animated GIF for any Image object, including 159
Chapter 4
Cannonball and Slingshot
the htarget. You could also use images for the cannon and the ball. One possibility is to use an animated GIF file to represent a spinning cannonball. Remember that all image files referenced in the code must be in the same folder as the uploaded HTML file. If they are in a different place on the Web, make sure the reference is correct. The support for audio and video in HTML5 varies across the browsers. You can look ahead to the presentation of video as a reward for completing the quiz in Chapter 6, and to the audio presented as part of the rock-paper-scissors game in Chapter 8. If you want to tackle this subject, it would be great to have a sound when the cannonball hits the target and a video clip showing the target exploding. Moving away from the look of the game, you can invent a scoring system, perhaps keeping track of attempts versus hits.
Slingshot: Using a Mouse to Set Parameters of Flight The slingshot application is built on the cannonball application. There are differences, but much is the same. Reviewing and understanding how more complicated applications are built on simpler ones will help you to create your own work. Creating the slingshot application involves designing the slingshot, implementing the mouse events to move the ball and parts of the slingshot, and then firing the ball. The form is absent because the player’s moves are just the mouse actions. In addition, I used a somewhat different approach for what to do when the target was hit. I check for the ball to intersect with an area within the target by 40 pixels. That is, I require the ball to hit the middle of the chicken! When there’s a hit, I change the target.src value to be another Image element, going from a picture of a chicken to a picture of feathers. Moreover, I don’t stop the animation, so the ball only stops when it hits the ground. As I indicated earlier, I don’t have the slingshot slings return to their original position, as I wanted to see the position to plan my next attempt. Table 4-5 shows the functions calling and being called in the slingshot application. This table is quite similar to the one of the cannonball applications.
160
Chapter 4
Cannonball and Slingshot
Table 4-5. Functions in the Slingshot Application Function
Invoked By/Called By
Calls
init
Action of the onLoad in body tag
drawall
drawall
Invoked directly by init, change
Calls the draw method of all objects in the everything array. These are the functions drawball, drawrects, drawsling, and drawAnImage
findball
Invoked by action of addEventListener in init for the mousedown event
drawall and distsq
distsq
Called by findball
moveit
Invoked by action of addEventListener in init for the mousemove event
drawall
finish
Invoked by action of the addEventListener in init for the mouseup event
drawall and distsq
change
Invoked by action of the setInterval function called in finish
drawall, calls the moveit method of cball, which is moveball
Ball
Invoked directly by code in a var statement
Myrectangle
Invoked directly by code in a var statement
drawball
Invoked by call of the draw method for the one Ball object
drawrects
Invoked by call of the draw method for the target object
moveball
Invoked by call of the moveit method for the one Ball object
Picture
Invoked directly by code in var statements
drawAnImage
Invoked by call of the draw method for a Picture object
Sling
Invoked directly by code in var statements
drawsling
Invoked by call of the draw method for mysling 161
Chapter 4
Cannonball and Slingshot
Table 4-6 shows the code for the slingshot application, with the new or changed lines commented. Notice that the form is absent from the body element. Before looking at the code, try to identify what parts would be the same as in the cannonball application and what would be different.
Table 4-6. The Slingshot Application Code
Explanation
Slingshot pulling back
Your browser doesn't support the HTML5 element canvas.
Hold mouse down and drag ball. Releasing the mouse button will shoot the slingshot. Slingshot remains at the last position. Reload page to try again.
Instructions for using mouse.
171
Chapter 4
Cannonball and Slingshot
Testing and Uploading the Application These applications can be created without external image files, but using images for the target and the hit target is fun, so you must remember to include those files when you upload your project. You can choose your own targets. Perhaps you feel kindly towards chickens! You’ll need to test that the program performs correctly in three situations: when the ball plops down to the left of the target, when the ball hits the target, and when the ball sails over the target. Note that I massaged the values so that the chicken needs to be hit in the middle, so it is possible for the ball to touch the head or tail and not cause the feathers to appear. You can vary the position of the cannon and its target and hit target, and the slingshot and the chicken and the feathers, by changing the variables such as startrockx, and you can modify the gravity variable. If you put the slingshot closer to the target, you can have more ways to hit the chicken: pulling more to the left for a direct shot versus pulling down for more of a lob. Enjoy! As I mentioned, you could use an animated GIF for the hit target in either the cannonball or slingshot applications. This would produce a nice effect. If you do use more and/or bigger pictures, or other media, then it would be best to use a technique to make sure that all the media is downloaded from your website before being used. I describe such a technique in Chapter 6, which plays a video clip and an audio clip when the player successfully completes a turn.
S ummary In this chapter, you learned how to create two ballistics applications. It is important to understand how they are the same and how they are different. The programming techniques and HTML5 features include:
172
•
Programmer-defined objects
•
setInterval to set up a timing event for the animation, as was done for the bouncing ball
•
Building an array using the push method and using the array as a list of what to display
•
Modifying arrays using the splice method
Chapter 4
Cannonball and Slingshot
•
Using trig functions and transformations to rotate the cannon and to resolve the horizontal and vertical velocities in the cannon and slingshot applications so as to simulate gravity
•
Using a form for player input
•
Handling mouse events (mousedown, mousemove, and mouseup), with addEventListener to obtain player input
•
Drawing arcs, rectangles, lines, and images on a canvas
The technique of programmer-defined objects and the use of an array of objects to display will come up again in later chapters. The next chapter focuses on a familiar game known as either memory or concentration. It uses a different timing event as well as the Date function, which was introduced in Chapter 1.
173
CHAPTER 5
The Memory (aka Concentration) Game In this chapter, we cover •
Drawing polygons
•
Placing text on the canvas
•
Programming techniques for representing information
•
Programming a pause
•
Calculating elapsed time
•
One method of shuffling a set of card objects
I ntroduction This chapter demonstrates two versions of a card game known variously as memory or concentration. Cards appear face down, and the player turns over two at a time (by clicking on them) in an attempt to find matched pairs. The program removes matches from the board but [virtually] flips back cards that do not match. When players make all the matches, the game shows the elapsed time.
© Jeanine Meyer 2018 J. Meyer, The Essential Guide to HTML5, https://doi.org/10.1007/978-1-4842-4155-4_5
175
Chapter 5
The Memory (aka Concentration) Game
The first version of the game I describe uses polygons for the face cards; the second uses family photos. You’ll notice other differences, which were made to illustrate several HTML5 features, but I also urge you to think about what the versions have in common. Figure 5-1 shows the opening screen of version one. When a player completes the game, the form that keeps track of matches also shows the elapsed time.
Figure 5-1. Opening screen of the memory game, version one Figure 5-2 displays the result after a player has clicked on two cards (the purple squares). The depicted polygons don’t match, so after a pause the program replaces them with images of the card backs, making the cards appear to have flipped over.
176
Chapter 5
The Memory (aka Concentration) Game
Figure 5-2. Two card fronts: no match When two cards match, the application removes them and notes the match in the form (see Figure 5-3).
Figure 5-3. The application has removed the two cards that matched 177
Chapter 5
The Memory (aka Concentration) Game
As illustrated in Figure 5-4, the game displays the result—in this case, 6 matches in 36 seconds—when the player finishes.
Figure 5-4. Version one of the game after the player has completed it In version two of the game, the card fronts display photographs of people rather than polygons. And note that although many memory games consider images to be the same only if they’re completely identical, this one is similar to a 2 of Hearts matching a 2 of Diamonds in a deck of playing cards. To illustrate a programming point, we’ll define a match as the same person, even in differing pictures. This requires a method of encoding the information we use to determine matching states. Version two of the game also demonstrates writing text on the canvas, as you can see in Figure 5-5, which depicts the opening screen.
Figure 5-5. The memory game, version two, opening screen 178
Chapter 5
The Memory (aka Concentration) Game
To see one possible result of clicking on two cards in our new game, look at Figure 5-6.
Figure 5-6. This screen shows non-matching photos
179
Chapter 5
The Memory (aka Concentration) Game
Because the result shows two different people—after pausing to let the player view both pictures—the application flips the cards over and lets the player try again. Figure 5-7 shows a successful selection—two images of the same person (albeit in different pictures).
Figure 5-7. This screenshot shows a match (different scenes, but the same person)
180
Chapter 5
The Memory (aka Concentration) Game
The application removes matched images from the board. When all cards are removed, the time taken to complete the game appears along with instructions on how to play again, as shown in Figure 5-8.
Figure 5-8. The final screen of the game (photo version); all images have been matched, so no cards appear You can play the game using photos available with the source code but it’s more fun to use your own. You can start with a small number—say two or three pairs of images— then work up to images of the whole family, class, or club. And for version one of the game, you can replace the polygons with your own designs.
C ritical Requirements The digital versions of the games require ways to represent the card backs (which are all the same) and the fronts with their distinct polygons or photos. The applications must also be able to tell which cards match and where cards are on the board. Additionally, players require feedback. In the real-world game, participants flip over two cards and look for a match (which takes a few moments). If there’s none, they flip the cards face down again. The computer program must show the faces of the selected cards and pause after revealing the second card so players have time to see the two faces. This pause is an example of something required for a computer implementation that occurs more-or-less 181
Chapter 5
The Memory (aka Concentration) Game
naturally when people play the game. The application should also display the current number of pairs found and, when the game is complete, the length of time participants took to find them all. The polygon and photo versions of the program use different approaches to accomplish these tasks. Here’s a summary of what the two game versions must do: •
Draw the card backs.
•
Shuffle the cards before a player makes an initial selection so the same array of choices doesn’t appear every time.
•
Detect when a player clicks on a card and distinguish between a first and a second click.
•
On detecting a click, show the appropriate card face by drawing polygons in the case of game version one or displaying the correct photograph for version two.
•
Remove pairs that match.
•
Operate appropriately even if those pesky players do the unexpected, such as clicking on the same card twice or clicking on an empty space formerly occupied by a card.
HTML5, CSS, JavaScript Features Let’s go over the specific HTML5 and JavaScript features that provide what we need to implement the games. We’ll build on material covered previously: the general structure of HTML documents; how to draw rectangles, images, and paths made up of line segments on a canvas element; programmer-defined and built-in functions; programmer objects; the form element; and arrays. New HTML5 and JavaScript features include the time out event, the use of Date objects for the calculation of elapsed time, writing and drawing text on the canvas, and several useful programming techniques that you’ll find valuable in future applications. As in the previous chapters, this section describes the HTML5 features and programming techniques in general terms. You can see all the code in context in the “Building the Application” section. If you like, you can skip to that section to see the code, then return here for explanations of how the features work.
182
Chapter 5
The Memory (aka Concentration) Game
R epresenting Cards When we hold a physical card in our hands, we can see what it is. There’s a card face and back, and the backs are all the same. We can clearly determine the cards’ positions on the game board and whether their faces or backs show. To implement a computer game, we must represent—encode—all that information. Encoding is an essential part of creating many computer applications, not just games. In this chapter (and throughout the book), I describe one way to accomplish the task. Keep in mind, though, that there’s rarely just one way to implement a feature of an application. That said, different strategies for building an application will likely have some techniques in common. Our approach to handling cards will employ a programmer-defined object. Creating a programmer-defined object in JavaScript involves writing the constructor function; in this case we’ll call it Card. The advantage of using programmer-defined objects is that JavaScript provides the dot notation needed to access information and code for objects of a common type. We did this for the cannonball and slingshot games in Chapter 4. We’ll give the Card object properties that will hold the card’s location (sx and sy) and dimensions (swidth and sheight), a pointer to a function to draw a back for the card, and for each case, the information that specifies the appropriate front (info). In the case of a polygon, the value of info will indicate the number of sides to be drawn. (In a later section we’ll discuss the code for drawing it.) For a photo card face, the value will be a reference, img, to an Image object we’ve created. The object will hold a specific image file along with a number (info) that ties together pictures that match. To draw the image for the file, we’ll use the built-in drawImage method. Needless to say, the cards don’t exist as physical entities, with two sides. The application draws the card’s face or back on the canvas where the player expects to see it. The function flipback draws the card’s back. To give the appearance of a removed card, flipback effectively erases a card by drawing a rectangle that’s the color of the board. Both applications use a function named makedeck to prepare the deck, a process that includes creation of the Card objects. For the polygon version of the game, we store the number of sides (from three to eight) in the Card objects. The application draws no polygons during setup, though. The photos version sets up an array called pairs, listing the image file names for the photos. You can follow this example to create your own family or group memory game.
183
Chapter 5
The Memory (aka Concentration) Game
Tip If you use the online code to play the game, as noted earlier, you can download the image files. To make the game your own, you need to upload the pictures and then change the code to reference your files. The code indicates what you need to change. The makedeck function creates the Image objects and uses the pairs array to set the src property to the image object. When the code creates Card objects, it puts in the index value that controls the pairs array so that matched photos have the same value. As in the polygon version, the application draws no image on the canvas during the creation of the deck. On the screen, the cards all appear the same; the information is different, though. These cards are in fixed positions—shuffling comes later. The code interprets position information, the sx and sy properties, differently for Card and Polygon. In the first case, the information refers to the upper-left corner. In the second case, the value identifies the center of the polygon. You can compute one from the other, though.
Using Date for Timing We need a way to determine how long the player took to make all the matches. JavaScript provides a way to measure elapsed time. You can view the code in context in the “Building the Application” section. Here I provide an explanation of how to determine the number of seconds between two distinct events in a running program. A call to Date() generates an object with date and time information. The two lines starttime = new Date(); starttime = Number(starttime.getTime()); store the number of milliseconds (thousands of a second) since the start of 1970 in the variable starttime. (The reason JavaScript uses 1970 doesn’t matter.) You can do arithmetic with Date objects, but I have chosen to extract the millisecond values. When either of our two memory programs determines the game is over, it invokes Date() again as follows: var now = new Date(); var nt = Number(now.getTime()); var seconds = Math.floor(.5+(nt-starttime)/1000); 184
Chapter 5
The Memory (aka Concentration) Game
This code 1. Creates a new Date object and stores it in the variable now. 2. Extracts the time using getTime, converts it to Number, and assigns it to the variable nt. This means nt holds the number of milliseconds from the start of 1970 until the point at which the code called Date. The program then subtracts the saved starting time, starttime, from the current time, nt. 3. Divides by 1,000 to get to seconds. 4. Adds .5 and invokes Math.floor to round the result up or down to whole seconds. We want numbers with fractional parts equal or greater than .5 to be rounded up and less than .5, to be rounded down. If you need more precision than seconds provides, omit or modify the last step. You can use this code whenever you need to calculate time elapsed between two events in a program.
P roviding a Pause When we play memory using real cards, we don’t consciously pause before flipping nonmatching cards face down. But as noted earlier, our computer implementation must provide a pause so players have time to see the two differing cards. You may recall from Chapters 3 and 4 that the animation applications—bouncing ball, cannonball, and slingshot—used the JavaScript function setInterval to set up events at fixed time intervals. We can employ a related function, setTimeout, in our memory games. (To see the complete code in context, go to the “Building the Application” section.) Let’s see how to set up the event and what happens when the pause time runs out. The setTimeout function sets up a single event, which we can use to impose a pause. The choose function, called when a player clicks on the canvas, first checks the firstpick variable to determine if the person has made a first or second selection. In either case, the program draws the card front on the canvas in the same spot as the card back. If the click was a second choice and the two cards match, the code sets the variable matched to true or false, depending on whether the cards did or didn’t match. If the application determines that the game isn’t over, the code invokes setTimeout(flipback,1000); 185
Chapter 5
The Memory (aka Concentration) Game
This leads to a call to the flipback function in 1,000 milliseconds (1 second). The function flipback then uses the matched variable to determine whether to redraw card backs or erase the cards by drawing rectangles with the table background color at the appropriate card locations. You can use setTimeout to set up any individual timed events. You need to specify the time interval and the function you want invoked when the interval expires. Remember that the time unit is milliseconds.
D rawing Text HTML5 includes a mechanism for placing text on the canvas. This provides a much more dynamic, flexible way to present text than previous versions. You can create some good effects by combining text placement with the drawing of rectangles, lines, arcs, and images we’ve already demonstrated. In this section, we outline the steps for placing text in a canvas element, and we include a short example that you can try. If you want, skip ahead to the “Building the Application” section to view the complete description of the code that produces what you see in Figures 5-5 through 5-8 for the photos version of the memory game. To put text on the canvas, we write code that sets the font, and then we use fillText to draw a string of characters starting at a specified x-y location. The following example creates words using an eclectic set of fonts (see the caution note later in the section).
Fonts
Your browser doesn't support the HTML5 element canvas.
This HTML document produces the screenshot shown in Figure 5-9.
Figure 5-9. Text in different fonts drawn on the canvas, produced using the font and fillText functions
Caution Make sure you pick fonts that will be present on the computers of all your players. In Chapter 10, you’ll learn how to use a CSS feature, called fontfamily, that provides a systematic way to specify a primary font and backups. 187
Chapter 5
The Memory (aka Concentration) Game
Note that although what you see appears to be text, you’re actually looking at ink on the canvas—that is, bitmap images of text, not a text field that you can modify in place. This means that to change the text, we need to write code that will completely erase the current image. We do so by setting the fillStyle to the value we placed in the variable tablecolor earlier, and use fillRect at the appropriate location and with the necessary dimensions. After creating the text image, the next step is to set fillStyle to a color other than tablecolor. We’ll use the color we chose for the card backs. For the opening screen display of the photograph memory game, here’s the code to set the font used for all text: ctx.font="bold 20pt sans-serif"; Using the sans-serif font makes sense, since it’s a standard font present on any computer. Putting together what we’ve done to this point, here’s the code to display the number of matches at a particular point in the game: ctx.fillStyle= tablecolor; ctx.fillRect(10,340,900,100); ctx.fillStyle=backcolor; ctx.fillText ("Number of matches so far: "+String(count),10,360); The first two statements erase the current tally and the next two put in the updated result. The expression "Number of matches so far: "+String(count) deserves more explanation. It accomplishes two tasks: •
It takes the variable count, which is a number, and turns it into a string of characters.
•
It concatenates the constant string "Number of matches so far: " with the result of String(count).
The concatenation demonstrates that the plus sign has two meanings in JavaScript: If the operands are numbers, the sign indicates addition. If the operands are character strings, it indicates the two strings should be concatenated—put together. A fancy phrase for a single symbol having several meanings is operator overloading.
188
Chapter 5
The Memory (aka Concentration) Game
What will JavaScript do if one operand is a string and the other a number? The answer depends on which of the two operands is what >
Start the script element. The type specification isn’t necessary but is included here because you’ll see it.
var ctx;
Variable that holds the canvas context.
var firstpick = true;
Declare and initialize firstpick.
var firstcard;
Declare a variable to hold the info defining the first pick.
var secondcard;
Declare a variable to hold the info defining the second pick.
var frontbgcolor = "rgb(251,215,73)"; Set the background color value for the card fronts.
(continued) 195
Chapter 5
The Memory (aka Concentration) Game
Table 5-2. (continued) Code
Explanation
var polycolor = "rgb(254,11,0)";
Set the color value for the polygons.
var backcolor = "rgb(128,0,128)";
Set the color value for card backs.
var tablecolor = "rgb(255,255,255)";
Set the color value for the board (table).
var cardrad = 30;
Set the radius for the polygons.
var deck = [];
Declare the deck, initially an empty array.
var firstsx = 30;
Set the position in x of the first card.
var firstsy = 50;
Set the position in y of the first card.
var margin = 30;
Set the spacing between cards.
var cardwidth = 4*cardrad;
Set the card width to four times the radius of the polygons.
var cardheight = 4*cardrad;
Set the card height to four times the radius of the polygons.
var matched;
This variable is set in choose and used in flipback.
var starttime;
This variable is set in init and used to calculate elapsed time.
function Card(sx,sy,swidth,sheight,info) {
Header for the Card function, setting up card objects.
this.sx = sx;
Set the horizontal coordinate.
this.sy = sy;
Set the vertical coordinate.
this.swidth = swidth;
Set the width.
this.sheight = sheight;
Set the height.
this.info = info;
Set info (the number of sides).
this.draw = drawback;
Specify how to draw.
}
Close the function.
(continued) 196
Chapter 5
The Memory (aka Concentration) Game
Table 5-2. (continued) Code
Explanation
function makedeck() {
Function header for setting up the deck.
var i;
Used in the for loop.
var acard;
Variable to hold the first of a pair of cards.
var bcard;
Variable to hold the second of a pair of cards.
var cx = firstsx;
Variable to hold the x coordinate. Start out at the first x position.
var cy = firstsy;
Will hold the y coordinate. Start out at the first y position.
for(i=3;i Your browser does not accept the audio tag.
230
Chapter 6
Including controls="controls" puts the familiar controls on the screen to allow the player/user to start or pause the audio clip. I do not provide controls for the video. At this point, you may be asking: where is the video and the audio control when the quiz starts? The answer is that I use CSS to make the two not display: audio {visibility: hidden;} video {visibility: hidden; display: none; position:absolute;} You also may ask why I don’t write code to create the video and audio elements dynamically, but have them in the HTML document. The answer to that is that I want to make sure the audio and video files are downloaded completely. Since human play does take some time, this probably would happen with no special work, but it is a good precaution to take.
Tip CSS has its own language, sometimes involving hyphens in terms. The CSS term for expressing how elements are layered on the screen is z-index; the JavaScript term is zIndex.
Checking the Player's Answer The checkorder function performs the task of checking if the player has clicked on the blocks in the correct order. It was not immediately obvious to me, but I did realize that my program did not need to order the set of selected names. Instead, my code checks if the player’s list as represented in the slots array is out of order. The slots array will hold the index position of each president as ordered by the player. The code iterates through the items to see if any item is greater than the following item. This for loop accomplishes the task: var ok = true; for (var i=0;islots[i+1]){ 231
Chapter 6
Quiz
ok = false; break; } } The ok variable starts out as true and the code in the for loop will change the value of ok to false if there is any discrepancy from a correct ordering. The break statement causes control to leave the for loop if and when this happens. If ok is set to false, the for loop is exited. The next step is to provide either the audio/video reward along with displaying the result CORRECT or display the result WRONG. if (ok){ res.innerHTML= "CORRECT"; song.style.visibility="visible"; song.currentTime = 4; //prevent seconds of no sound song.play(); v.style.visibility="visible"; v.currentTime=0; v.style.display="block"; v.play(); } else { res.innerHTML = "WRONG"; } With this background on JavaScript, HTML, and CSS, we are now ready to describe the coding of the quiz application.
Building the Application and Making It Your Own The knowledge base for the quiz is represented in the facts variable, which is an array of arrays. If you want to change the quiz to another topic, one that consists of pairs of names or other text, you just need to change facts. Of course, you also need to change the text that appears as an h1 element in the body element to let the player know the category of questions. I defined a variable named nq, for number in each quiz (the number of pairs to appear onscreen) to be 4. You can, of course, change this value if you 232
Chapter 6
Quiz
want to present a different number of pairs to the player. The other variables are used for the original positions of the blocks and to hold status information, such as whether it’s a first click or a second click. I created four functions for this application: init, setupgame, pickelement and checkorder. I could have combined init and setupgame and combined pickelement with checkorder but made them separate to facilitate a Replay button and also for general principle. Defining distinct functions for distinct tasks is a good practice. Table 6-3 describes these functions and what they call or are called by.
Table 6-3. Functions in the Quiz Application Function
Invoked By/Called By
Calls
init
Invoked by the action of the onLoad in the tag
setupgame
setupgame
init
pickelement Invoked as a result of the addEventListener calls in setupgame checkorder checkorder
pickelement
The setupgame function is where the HTML is created for the blocks. Briefly, an expression using Math.random is evaluated to pick one of the rows in the facts array. If that row has been used, the code tries again. When an unused row is found, it is marked as used (the third element, index value 2) and the blocks are created. The pickelement function is invoked when a block is clicked. It adds to the string on displayed on Your Order and adds to the slots array, which will be used by checkorder. The checkorder function does the checking. It displays either WRONG or CORRECT and, if the order was correct, makes the audio control and the video visible and starts playing both. Note that there is redundant code in my program. I did this to ease the effort to enable repeat play without reloading or “do-overs” . Table 6-4 supplies a line-by-line explanation of the code.
233
Chapter 6
Quiz
Table 6-4. The Complete Code for the Presidents Quiz
HTML tag.
Defines the charset, in this case a form of Unicode. It can be omitted, and I do omit it in many examples, but include it here to let you see it.
Head tag.
Ordering Quiz with Rewards
Complete title element.
Close style element.
Close script element.
Close head element.
(continued)
240
Chapter 6
Quiz
Table 6-4. (continued)
Body tag. Note setting of onload.
Audio tag.
source src="hail_to_the_chief.mp3" < type="audio/mpeg">
The MP3 source.
source src="hail_to_the_chief.ogg" < type="audio/ogg">
The OGG source
Your browser does not accept the audio tag.
Done for older browsers.
Close audio element.
Video tag. Noted muted attribute.
The WEBM source.
The MP4 sources.
Your browser does not accept the video tag.
For older browsers.
Close video element.
Order the Presidents
Heading.
This is a challenge to put the presidents displayed in the Instructions. right order in terms of time of term in office. Click on the boxes in the order you believe correct.
Line break.
Reload for new game.
More instructions.
(continued)
241
Chapter 6
Quiz
Table 6-4. (continued)
Line break.
Your order:
Heading for player's answers.
Place for player's answers.
Vertical spacing.
Result:
Will hold result.
Vertical spacing.
Close body.
Close html.
The first step to making this application your own is to choose the content of your quiz. The values here are names, held in text, but they could be descriptions of events, mathematical expressions, or names of songs. You also could create img tags and use the information kept in the array to set the src values of img elements. More complicated, but still doable is to incorporate audio. Start simple, with something resembling the list of U.S. presidents, and then be more daring. You can change the look of the application by modifying the original HTML and/or the created HTML. You can modify or add to the CSS section. You can easily change the number of questions (but can’t have more than 9), or change the four-question game to a four-question round and make a new round happen automatically after a certain number of guesses or when clicking on a button. You would need to decide if presidents are to be repeated from round to round. You can also incorporate a timing feature. There are two general approaches: keep track of time and simply display it when the player completes a game/round successfully (see the memory games in Chapter 5) or impose a time limit. The first approach allows someone to compete with themselves but imposes no significant pressure. The second does put pressure on the player and you can decrease the allowed time for successive rounds. It could be implemented using the setTimeout command. You can identify links to websites that discuss the facts or to Google map locations as mini-awards for correct answers—or as clues. You may not like the way the quiz blocks remain on the screen while the video is showing. You can remove them using a loop that makes each element invisible. Look ahead to the Hangman application in Chapter 9 for ideas. 242
Chapter 6
Quiz
Testing and Uploading the Application The random feature of the game does not impact the testing. If you wish, you can substitute fixed choices after the Math.random coding, do the bulk of the testing, and then remove these lines of code and test again. The important thing to do for this and similar games is to make sure your testing involves both correct guesses and incorrect guesses, as well as bad behavior on the part of the player, like clicking on a choice already made. The presidents game is complete in the HTML file but the audio and video clips are distinct files. If you make your own quiz, you are not obliged to use both an audio clip and a video clip. For media, you need to •
Create or acquire the video and/or audio
•
Produce the different versions, assuming you want to support the different browsers
•
Upload all the files to the server
You may need to work with your server staff to make sure the different video types are properly specified. This involves something called the htaccess file. HTML5 has now been around for a time and this way of featuring video on web pages should be familiar to server staff. Alternatively, you can identify video and/or audio already online and use absolute URLs as the src attributes in the source elements in the media elements.
Summary In this chapter, we implemented a simple quiz that asked a player to put a small set chosen randomly from the complete list of U.S. presidents in order. Putting events in chronological order is a reasonable topic for a quiz, but the main lesson of this chapter is the distinct techniques used. The application used the following programming techniques and HTML5 features: •
Creating HTML during runtime using document.createElement, document.getElementById, and document.body.appendChild
•
Setting up event handling for the mouse click event using addEventListener 243
Chapter 6
Quiz
•
Removing event handling for the mouse click event using removeEventListener
•
Changing the color of objects on the screen using code to change CSS settings
•
Creating an array of arrays to hold the quiz content
•
Using for loops for iterating over the array
•
Using do-while loops to make a random choice of an unused question set
•
Using substring for extracting strings to be used in the checking
•
Turning a string into a number using the Number function
•
Using video and audio elements for displaying video and audio encoded in formats acceptable by different browsers
You can use dynamically created and repositioned HTML along with the drawing on canvas that you learned in the previous chapters. The implementation of Hangman, described in Chapter 9, does just that. You can use video and audio as a small part of an application, as was done here, or as the major part of a website. In the next chapter, we return to drawing on canvas as we build a maze and then travel through the maze without crossing the walls.
244
CHAPTER 7
Mazes In this chapter, we cover •
Responding to mouse events
•
Calculation of collision between circles and lines
•
Responding to the arrow keys
•
Form input
•
Encoding, saving, decoding, and restoring information from local storage using try and catch for testing if coding is recognized
•
Using join and split to encode and decode information
•
Using javascript: in a button to invoke functions
•
Radio buttons
I ntroduction In this chapter, we’ll continue our exploration of programming techniques and HTML5 and JavaScript features, this time using programs that build and traverse mazes. Players will have the ability to draw a set of walls to make up a maze. They will be able to save and load their mazes, and to traverse them using collision detection to make sure they don’t cross any walls. The general programming techniques include using arrays for everything that needs to be drawn on the canvas as well as a separate array for the set of walls in the maze. The number of walls is not known before play starts, so a flexible approach is required. Once the maze is constructed, we’ll see how to respond to presses of the arrow keys and how to detect collisions between the playing piece—a pentagon-shaped token—and the walls.
© Jeanine Meyer 2018 J. Meyer, The Essential Guide to HTML5, https://doi.org/10.1007/978-1-4842-4155-4_7
245
Chapter 7
Mazes
With HTML5, we can handle mouse events so the player can press the mouse button down and then drag and release the button to define each wall of a maze; respond to the arrow keys to move the token; and save and retrieve the layout of walls on the local computer. As usual, we’ll build more than one version of the application. In the first, everything is contained in one HTML file. That is, the player builds a maze, can travel through it, and can optionally save it to the local computer or restore a set of walls saved earlier. In the second version, there’s one program to create the mazes and a second file that offers the player a choice of specific mazes to traverse, using radio buttons. Perhaps one person might build the mazes on a given computer and then ask a friend to try traversing them. HTML5’s local storage facility accepts only strings of characters, and so we’ll look at how we can use JavaScript to encode the maze information into a character string and then decode it back to rebuild the walls of the maze. The saved information will remain on the computer even after it is turned off. The individual capabilities we’ll discuss in this chapter: building structures, using the arrow keys to move a game piece, checking for collisions, and encoding, saving, and restoring >Store date info. causes store() to be invoked when the button is clicked. You may be wondering if anyone can read any of the saved information in local storage. The answer is that access to each key/value pair in localStorage (and in other types of cookies) is restricted to the website that stored the information. This is a security feature. The Chrome browser allows testing of local storage with HTML5 scripts stored on the local computer. At the time of writing for the first edition, Firefox did not, but required files to be uploaded to a server to use local storage. Though localStorage appears to be recognized by all browsers now, I mention this to prepare you for browsers being different. Because there may be other problems such as exceeding limits set by the user for local storage and cookies, it is a good practice to include some error checking. You can use the JavaScript function typeof to check if localStorage is accepted by the browser: if (typeof(localStorage)=="undefined") Figure 7-14 shows the result of loading the date application and clicking on the Store Date Info button in an old version of Internet Explorer. (By the time you read this book, the latest version of IE may be out and this will not be a problem.)
265
Chapter 7
Mazes
Figure 7-14. The browser didn’t recognize localStorage JavaScript also provides a general mechanism for avoiding the display of errors. The compound statement try and catch will try to execute some code and if it doesn’t work, it will go to the catch clause. try { olddate = new Date(); localStorage.setItem("lastdate",olddate); alert("Stored: "+olddate); } catch(e) { alert("Error with use of local storage: "+e);} } If you removed the if (typeof(localStorage) test and tried the code in the old IE, you’d see the message shown in Figure 7-15.
Figure 7-15. Browser error, caught in a try/catch 266
Chapter 7
Mazes
Table 7-1 shows the complete date application. Remember: you may need to upload this to a server to test it.
Table 7-1. Complete Code for the Date Application Code
Explanation
Opening html tag.
Opening head tag.
Local Storage test
Complete title.
Close script element.
Close head element.
Opening body tag.
Store date info
Button for storing.
Retrieve date Button for retrieving, that is, info fetching the stored >Remove date info
Button for removing.
Closing body tag.
Closing html tag.
Combining the Date function with localStorage lets you do many things. For example, you can calculate the elapsed time between a player’s current and last use of the application or, perhaps, the player winning two games. In Chapter 5, we used Date to compute the elapsed time using the getTime method. Recall that getTime stores the number of milliseconds from January 1, 1970. You can convert that value to a string, store it, and then when you fetch it back, do arithmetic to calculate elapsed time. The localStorage key/value pairs last until they are removed, unlike JavaScript cookies, for which you can set a duration.
269
Chapter 7
Mazes
Encoding onSubmit="return getwalls()" >
Hard
Moderate
Easy
Notice that all three input elements have the same name. This is what defines the group of buttons of which only one may be selected. In this case, the markup creates an array called level. The getwalls function will be shown in full in the next section. It is similar to the function in the all-in-one script. However, in this case, the name of the localStorage item is determined from the radio buttons. The code is for (i=0;i Score:
312
Chapter 8
Rock, Paper, Scissors
Just to show you how these things are done, we’ll use styles for the score field. We set up two styles, one for the form and one for the input field. form { color: blue; font-family: Georgia, "Times New Roman", Times, serif; font-size:16px; } input { text-align:right; font:inherit; color:inherit; } We set the color for the text in the form to blue and specified the font using the font-family property. This is a way to specify a particular font and backups if that font doesn’t exist on the client computer. This is a powerful feature because it means you can be as specific as you want in terms of fonts and, with work, still make sure that everyone can read the material.
Tip You can research online for web-safe fonts to see which fonts are widely available. Then you can pick your favorite font for the first choice, one of the web-safe fonts for the second, and make the last choice either serif or sans-serif. You can even specify more than three choices if you want. Check out http://en.wikipedia. org/wiki/Web_typography for ideas. Another option is to acquire a font and put the file on your server and use the CSS @font-face rule to download it with the other files (see https://www.w3schools.com/css/css3_fonts.asp). In this style, we specify the font named Georgia, then "Times New Roman", then Times, and then whatever the standard font with serifs is on the computer. Serifs are the little extra flags on letters. The quotation marks around Times New Roman are necessary because the name involves multiple terms. Quotation marks wouldn’t be wrong around the other font names, but they aren’t necessary. We also specify the size as 16 pixels. The input field inherits the font, including size, and the color from the form element, its parent. However, because the score is a number, we use the text-align property to indicate right alignment in the field. The label Score is in the form element. The actual 313
Chapter 8
Rock, Paper, Scissors
score is in the input element. Using the inherit setting for the input style properties makes the two display in the same font, size, and color. The value in the input field will be extracted and set using its name, score. For example, newscore = Number(document.f.score.value); Number is required here to produce the number represented by the text in the field; that is 0 as opposed to "0" (the character). If we left the value as a string and the code used a plus sign to add 1 to a string, this would not be addition; it would instead be the concatenation of strings. (This is termed operator overloading, by the way: the plus sign indicates different operations depending on the autoplay controls> Your browser doesn't recognize audio
319
Chapter 8
Rock, Paper, Scissors
Figure 8-8. Audio tag with controls Remember: for our game, we will play audio for the rock crushing the scissors, the paper covering the rock, the scissors cutting the paper, and a sigh for any tie. Here is the coding for the four audio clips in rock-paper-scissors:
This should appear reasonable for describing four sets of audio files, but you may be wondering how the code knows which one to play. We could insert id attributes in each tag. However, let’s do something else instead in order to demonstrate more JavaScript that’s useful in many situations. You have seen the method document. getElementById. There is a similar method: document.getElementsByTagname. The line: musicelements = document.getElementsByTagName("audio"); extracts all elements of the tag name indicated by the parameter and creates an array, which, in this line of code, assigns the array to a variable named musicelements. We use this line in the init function so it’s performed at the very start of the application. 320
Chapter 8
Rock, Paper, Scissors
We construct another array of arrays, this one called music, and add two more global variables, for a total of three global variables for handling sounds. var music = [ [3,1,0], [1,3,2], [0,2,3]]; var musicelements; var musicch; You can check that music and beats are parallel structures with 0 standing for rock crushing scissors, 1 for paper covering rock, 2 for scissors cutting paper, and 3 for a tie. The choose function will have the extra line: musicch = music[compch][i]; The musicch variable—the name stands for choice for music—will hold 0, 1, 2, or 3. This sets up something to happen in the flyin function when the animation is complete. We don't play the clip immediately, as explained in my confession. musicelements[musicch].play(); The zeroth, first, second, or third element in musicelements is referenced by the indexing using musicch, then its play method is invoked and the clip is played.
Starting Off The application starts by setting up a call to a function in the onLoad attribute of the tag. This has been the practice in the other games. The init function performs several tasks. It sets the initial score value to 0. This is necessary just in case the player reloads the document; it is a quirk of HTML that form ;
Set the font to be used for the result messages.
ctx.fillStyle = "blue";
Set the color.
}
Close the function.
function drawall() {
Header for the function.
ctx.clearRect(0,0,cwidth,cheight);
Clear the canvas.
var i;
Variable for indexing.
for (i=0;i