HTML 5 Games Development By Example Beginner's Guide Makzan (Packt, 2011) BBS

HTML%205%20Games%20Development%20by%20Example%20-%20Beginner's%20Guide%20-%20Makzan%20(Packt%2C%202011)%20BBS

User Manual: Pdf

Open the PDF directly: View PDF PDF.
Page Count: 352

DownloadHTML 5 Games Development By Example - Beginner's Guide Makzan (Packt, 2011) BBS
Open PDF In BrowserView PDF
HTML5 Games Development by
Example
Beginner's Guide

Create six fun games using the latest HTML5, Canvas, CSS,
and JavaScript techniques

Makzan

BIRMINGHAM - MUMBAI

HTML5 Games Development by Example
Beginner's Guide

Copyright © 2011 Packt Publishing

All rights reserved. No part of this book may be reproduced, stored in a retrieval system,
or transmitted in any form or by any means, without the prior written permission of the
publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the
information presented. However, the information contained in this book is sold without
warranty, either express or implied. Neither the author, nor Packt Publishing, and its dealers
and distributors will be held liable for any damages caused or alleged to be caused directly
or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the
companies and products mentioned in this book by the appropriate use of capitals.
However, Packt Publishing cannot guarantee the accuracy of this information.

First published: August 2011

Production Reference: 1180811

Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham B3 2PB, UK.
ISBN 978-1-849691-26-0
www.packtpub.com

Cover Image by Girish Suryawanshi (girish.suryawanshi@gmail.com)

Credits
Author
Makzan
Reviewers
Matteo Ferretti

Project Coordinator
Zainab Bagasrawala
Proofreader
Joanna McMahon

Henk Jurriens
William Malone

Indexer
Rekha Nair

Acquisition Editor
David Barnes

Graphics
Geetanjali Sawant

Development Editor
Neha Mallik

Production Coordinators
Melwyn D'sa

Technical Editors

Adline Swetha Jesuthas

Pallavi Kachare
Azharuddin Sheikh

Cover Work
Melwyn D'sa

Copy Editor
Neha Shetty

About the Author
Makzan is the founder of 42games Limited. He has been designing games since he was
a child. He likes to see how the well-designed interactions in his games can trigger the
emotions and influence the player. He believes that games should let a player share joyful
times with friends. Therefore, his favorite game type is multiplayer casual games.
Makzan also wrote a book named Flash Multiplayer Virtual World. It is about developing
a virtual world to play with friends in real time with Adobe Flash and socket server.

I would like to thank the entire team from Packt Publishing. The book
would not have been possible without the help from all the editors and
proofreaders. I thank all the reviewers for providing useful comments
from which I have learned a lot. I thank my family for giving me support
during the book writing process.

About the Reviewers
Matteo Ferretti is a software engineer, an amateur comic-book artist, and an
occasional graphic designer, who was drawn into software development since he
played his first video game.
He fell in love with JavaScript at the end of the 20th century, and he still loves it with the
same passion.
Currently he is working for Mozilla, after more than two years in TomTom as a Senior
Software Engineer and Tech Leader.
I wish to thank my love, Elisa, for her patience and understanding. I also
want to thank my parents, for their continuous support throughout my
whole life.

Henk Jurriens is a software developer and developer evangelist, experienced with Java,
Groovy and Grails, and HTML5. Henk is passionate about new technologies and loves to
talk about it, and so gives different presentations about HTML5, Linked Data, and Groovy
and Grails.
In addition, Henk founded an HTML5 User Group to promote and share knowledge about
HTML5. During the year, different meetups are organized. Together with the Google
Technology User Group, he organized for example, a HTML5 Hackathon.
Last year, Henk also helped with a HTML5 Game Jam and there he saw the potential of
HTML5 Games and this was the reason for him to review this book. With the help of this
book, great HTML5 games can be built!

William Malone is a software developer specializing in dialects of ECMAScript
(ActionScript and JavaScript). He has written many articles about Flash and HTML5
which are available at http://www.williammalone.com.

www.PacktPub.com
Support files, eBooks, discount offers and more
You might want to visit www.PacktPub.com for support files and downloads related to your book.
Did you know that Packt offers eBook versions of every book published, with PDF and ePub files
available? You can upgrade to the eBook version at www.PacktPub.com and as a print book
customer, you are entitled to a discount on the eBook copy. Get in touch with us at service@
packtpub.com for more details.
At www.PacktPub.com, you can also read a collection of free technical articles, sign up for a range
of free newsletters and receive exclusive discounts and offers on Packt books and eBooks.

http://PacktLib.PacktPub.com
Do you need instant solutions to your IT questions? PacktLib is Packt's online digital book library. Here,
you can access, read and search across Packt's entire library of books.

Why Subscribe?
 Fully searchable across every book published by Packt
 Copy and paste, print and bookmark content
 On demand and accessible via web browser

Free Access for Packt account holders
If you have an account with Packt at www.PacktPub.com, you can use this to access PacktLib today
and view nine entirely free books. Simply use your login credentials for immediate access.

Table of Contents
Preface
Chapter 1: Introducing HTML5 Games
Discovering new features in HTML5
Canvas
Audio
GeoLocation
WebGL
WebSocket
Local Storage
Offline application
Discovering new features in CSS3
CSS3 transition
CSS3 transform
CSS3 animation
Learning more detail of new HTML5 and CSS3 features
The benefit of creating HTML5 games
No third-party plugin required
Supporting iOS devices without plugin
Breaking the boundary of usual browser games
Building HTML5 games
What others are playing with HTML5
Matching game
Sinuous
Asteroid-styled bookmarklet
Quake 2
RumpeTroll
Scrabb.ly
Aves Engine

1
7
8
8
8
8
9
10
10
11
11
12
13
14
15
15
16
16
16
18
18
18
19
19
20
21
21
22

Table of Contents

Browsing more HTML5 games
What we are going to create in this book
Summary

22
23
24

Chapter 2: Getting Started with DOM-based Game Development

25

Preparing the development environment
Preparing the HTML documents for a DOM-based game
Time for action – Installing the jQuery library
New HTML5 doctype
Header and footer
Best practice to place the JavaScript code
Running our code after the page is ready
Setting up the Ping Pong game elements
Time for action – Placing Ping Pong game elements in DOM
Introducing jQuery
Understanding basic jQuery selectors
Understanding the jQuery CSS function
Benefits of using jQuery
Manipulating game elements in DOM with jQuery
Time for action – Changing position of elements with jQuery
Understanding the behavior of absolute position
Getting a keyboard input from players
Time for action – Moving DOM objects by a keyboard input
Understanding a key code
Making constants more readable
Converting strings to numbers with parseInt function
Executing JavaScript expressions directly in the Console panel
Checking the console window
Supporting multiple keyboard input from players
Time for action – Listening to keyboard input with another approach
Declaring global variables in a better way
Creating a JavaScript timer with setInterval function
Understanding Game Loop
Moving a DOM object with JavaScript Interval
Time for action – Moving the ball with JavaScript Interval
Beginning collision detection
Time for action – Hitting the ball with the paddles
Showing text dynamically in HTML
Time for action – Showing the score of both players
Summary

26
26
27
28
29
29
29
30
30
32
33
34
35
35
35
36
37
38
39
40
40
42
42
43
43
45
46
46
47
47
49
50
53
53
56

[ ii ]

Table of Contents

Chapter 3: Building a Memory Matching Game in CSS3
Moving game objects with CSS3 transition
Time for action – Moving a playing card around
2D transforms functions
3D transforms functions

57
57
58
61
61

Tweening the styles by using CSS3 transition
Creating a card-flipping effect
Time for action – Flipping a card with CSS3
Toggling class with jQuery toggleClass function
Controlling the visibility of overlapped elements by z-index
Introducing CSS perspective property
Introducing backface-visibility
Creating a card matching memory game
Downloading the sprites sheet of playing cards
Setting up the game environment
Time for action – Preparing the card matching game
Cloning DOM elements with jQuery
Selecting the first child of an element in jQuery by using child filters
Vertically aligning a DOM element
Using CSS sprite with a background position
Adding game logic to the matching game
Time for action – Adding game logic to the matching game
Executing code after CSS transition ended
Delaying code execution on flipping cards
Randomizing an array in JavaScript
Storing internal custom data with an HTML5 custom data attribute
Accessing custom data attribute with jQuery
Making other playing card games
Embedding web fonts into our game
Time for action – Embedding a font from Google Font Directory
Choosing different font delivery services
Summary

62
64
64
66
67
68
69
70
70
71
71
77
77
77
78
79
80
83
83
83
84
85
87
87
88
90
91

Chapter 4: Building the Untangle Game with Canvas and Drawing API

93

Introducing the HTML5 Canvas Element
Drawing a circle in canvas
Time for action – Drawing color circles on canvas
Putting fallback content when the web browser does not support canvas
Drawing circles and shapes with canvas arc function
Converting degree to radians
Time for action – Drawing different arcs with arc function
Executing the path drawing in canvas

94
95
95
97
98
98
99
102

[ iii ]

Table of Contents

Beginning a path for each style
Closing a path
Wrapping the circle drawing in function
Time for action – Putting the circle drawing code into a function
Generating random numbers in JavaScript
Saving the circle position
Time for action – Saving the circle position
Defining a basic class definition in JavaScript
Drawing lines in canvas
Time for action – Drawing straight lines between each circle
Introducing the line drawing API
Interacting with drawn objects in canvas with mouse events
Time for action – Dragging the circles in canvas
Getting the mouse position in the canvas element
Detecting mouse events on circles in canvas
Game loop
Clearing the canvas
Detecting line intersection in canvas
Time for action – Distinguishing the intersected lines
Determining whether two line segments intersect
Making the untangle puzzle game
Time for action – Making the untangle puzzle game in canvas
Defining the leveling data
Determining level-up
Displaying current level and completeness progress
Summary

Chapter 5: Building a Canvas Games Masterclass
Filling shapes with gradient color
Time for action – Drawing a gradient color background to the Untangle game
Adding color stops in the gradient color
Filling radial gradient color
Time for action – Filling the circles with radial gradient color
Drawing text in canvas
Time for action – Displaying the progress level text inside the canvas element
Using embedded web font inside canvas
Time for action – Embedding Google Web Font into the
canvas element
Drawing images in canvas
Time for action – Adding graphics to the game
Using the drawImage function
[ iv ]

102
103
104
104
105
106
107
108
108
109
111
112
112
116
116
117
118
119
119
123
124
125
129
130
131
131

133
134
134
135
136
136
139
139
142
143
143
144
144
147

Table of Contents

Decorating the canvas-based game
Time for action – Adding CSS styles and images decoration to the game
Animating a sprite sheet in canvas
Time for action – Making a game guide animation
Creating a multi-layers canvas game
Time for action – Dividing the game into four layers
Mixing CSS technique with Canvas drawing
Summary

Chapter 6: Adding Sound Effects to your Games
Adding a sound effect to the play button
Time for action – Adding sound effects to the play button
Defining an audio element
Playing a sound
Pausing a sound
Adjusting the sound volume
Using the jQuery hover event
Creating the Ogg format audio to support Mozilla Firefox
Time for action – Converting an MP3 sound to Ogg format with Audacity
Supporting different web browsers with different audio formats
Building a mini piano musical game
Time for action – Creating a basic background to the
music game
Creating scenes in HTML5 games
Visualizing the music play back
Time for action – Creating the playback visualization in the music game
Choosing the right song for the music game
Storing and extracting the song level data
Getting the elapsed time of the game
Creating music dots
Moving the music dots
Linking the play button to the music game scene
Time for action – Animating the scene transition
Creating a slide-in effect in CSS3
Creating a keyboard-driven mini piano musical game
Time for action – Creating a mini piano musical game
Hitting the three music lines by key down
Determining music dot hits on key down
Removing an element in an array with the given index
Time for action – Removing music dots with the splice function

[]

149
149
152
152
156
156
162
163

165
166
166
169
171
171
172
172
172
173
174
174
174
174
177
178
179
183
183
184
185
186
187
187
189
190
190
192
193
194
194

Table of Contents

Adding additional features to the mini piano game
Adjusting the music volume according to the player
Time for action – Removing missed melody notes
Removing dots from the game
Storing the success count in the last five results
Recording music notes as level data
Time for action – Adding functionality to record the music level data
Handling the audio event on playback completes
Time for action – Indicating a game over event in the console
Handling audio events
Summary

Chapter 7: Using Local Storage to Store Game Data
Storing data by using HTML5 local storage
Creating a game over dialog
Time for action – Creating a game over dialog with the elapsed played time
Saving scores in the browser
Time for action – Saving the game score
Storing and loading data with local storage
The local storage saves the string value
Treating the local storage object as an associated array
Saving objects in the local storage
Time for action – Saving the time alongside the score
Getting the current date and time in JavaScript
Using the native JSON to encode an object into a string
Loading a stored object from a JSON string
Inspecting the local storage in a console window
Notifying players of breaking a new record with a nice ribbon effect
Time for action – Creating a ribbon in CSS3
Saving the entire game progress
Saving the game progress
Time for action – Saving all essential game data in the local storage
Removing a record from the local storage
Cloning an array in JavaScript
Resuming the game progress
Time for action – Resuming a game from the local storage
Summary

195
196
196
198
198
199
199
202
202
203
204

205
206
206
207
210
210
211
212
213
213
214
217
218
218
219
220
221
224
224
224
227
227
228
228
231

Chapter 8: Building a Multiplayer Draw-and-Guess Game with WebSockets 233
Trying an existing WebSockets web application
Time for action – Trying the multiuser sketchpad
[ vi ]

234
235

Table of Contents

Installing a WebSocket server
Installing the Node.JS WebSocket server
Time for action – Installing Node.JS
Creating a WebSockets server to broadcast the connection count
Time for action – Creating a WebSocket server that sends the total
count of connections
Initializing the WebSockets server
Listening to the connection event on the server side
Getting a count of connected clients on the server side
Broadcasting a message to all connected browsers
Creating a client that connects to a WebSocket server and getting the total
connections count
Time for action – Showing the connection count in a WebSocket application
Establishing a WebSocket connection
WebSockets client events
Building a chatting application with WebSockets
Sending a message to the server
Time for action – Sending a message to the server through WebSockets
Sending a message from the client to the server
Receiving a message on the server side
Broadcasting every received message on the server side to create a chat room
Time for action – Broadcasting the messages to all connected browsers
Comparing between WebSockets and polling approaches
Making a shared drawing whiteboard with Canvas and WebSockets
Building a local drawing sketchpad
Time for action – Making a local drawing whiteboard with the Canvas
Drawing on the canvas

236
236
236
238
238
239
240
240
240
241
241
243
243
243
243
244
246
246
247
247
248
250
250
251
254

Broadcasting the drawing to all connected browsers
Time for action – Sending the drawing through WebSockets
Defining a data object to communicate between the client and the server
Packing the drawing lines data into JSON for broadcasting
Recreating the drawing lines after receiving them from other clients
Building a multiplayer draw-and-guess game
Time for action – Building the draw-and-guess game
Controlling the game flow of a multiplayer game
Enumerating connected clients on the serverside
Sending a message to a specific connection on the server side
Improving the game
Storing drawn lines on each game
Improving the answer checking mechanism

254
254
258
259
259
259
260
265
266
267
267
268
268

Decorating the draw-and-guess game with CSS
[ vii ]

268

Time for action – Decorating the game
Summary

Chapter 9: Building a Physics Car Game with Box2D and Canvas
Installing the Box2D JavaScript library
Time for action – Installing the Box2D physics library
Using b2World to create a new world
Using b2AABB to define a bounding area
Setting the gravity of the world
Setting the Box2D to ignore the slept object
Creating a static ground body in the physics world
Time for action – Creating a ground in the world
Creating a shape
Creating a body
Drawing the physics world in the canvas
Time for action – Drawing the physics world into the canvas
Creating a dynamic box in the physics world
Time for action – Putting a dynamic box in the world
Setting the bouncing effect with the restitution property
Advancing the world time
Time for action – Setting up the world step loop
Adding wheels to the game
Time for action – Putting two circles in the world
Creating a physical car
Time for action – Connecting the box and two circles with revolute joint
Using a revolute joint to create an anchor point between two bodies
Adding force to the car with a keyboard input
Time for action – Adding force to the car
Applying force to a body
Understanding the difference between ApplyForce and ApplyImpulse
Adding ramps to our game environment
Time for action – Creating the world with ramps
Checking collisions in the Box2D world
Time for action – Checking a collision between the car and the destination body
Getting the collision contact list
Restarting the game
Time for action – Restarting the game while pressing the R key
Adding a level support to our car game
Time for action – Loading game with levels data
Replacing the Box2D outline drawing with graphics
Time for action – Adding a flag graphic and a car graphic to the game

268
271

273
274
275
277
278
278
278
279
279
280
280
281
281
284
284
285
286
286
287
287
288
289
290
291
291
292
293
293
293
295
295
296
297
297
299
299
303
303

Table of Contents

Using userData in shape and body
Drawing graphics every frame according to the state of its physics body
Rotating and translating an image in the canvas
Adding a final touch to make the game fun to play
Time for action – Decorating the game and adding a fuel
limitation
Adding fuel to add a constraint when applying force
Presenting the remaining fuel in a CSS3 progress bar
Summary
HTML5 game engines
Game sprites, and textures
Sound effects

Appendix: Pop Quiz Answers

306
307
308
308
309
309
314
315
316
316
317
317

319

Chapter 2: Getting Started with DOM-based Game Development
Running our code after the page is ready
Understanding the behavior of absolution position
Chapter 3: Building Memory Match Game in CSS3
Storing internal custom data with HTML5 custom data attribute
Accessing custom data attribute with jQuery
Chapter 4: Building Untangle Game with Canvas and Drawing API
Using startAngle and endAngle
Using closePath with fill command only
Accessing shapes in canvas
Clearing drawn shapes in canvas
Chapter 5: Building Canvas Games Masterclass
Drawing text in canvas
Styling canvas background
Chapter 6: Adding Sound Effects to your Games
Using the audio tag
Chapter 7: Using Local Storage to Store Game Data
Using local storage
Chapter 8: Building Multiplayer Draw-and-Guess Game with WebSockets

Index

319
319
319
319
319
319
320
320
320
320
320
320
320
320
321
321
321
321
321

237

[ ix ]

Preface
HTML5 promises to be the hot new platform for online games. HTML5 games work on
computers, smartphones, and tablets, including iPhones and iPads. Be one of the first
developers to build HTML5 games today and be ready for tomorrow!
This book will show you how to use the latest HTML5 and CSS3 web standards to build card
games, drawing games, physics games, and even multiplayer games over the network. With
this book, you will build six example games with clear systematic tutorials.
HTML5, CSS3, and the related JavaScript API are the latest hot topics in web. These standards
bring us the new game market, HTML5 Games. With the new power from them, we can
design games with HTML5 elements, CSS3 properties, and JavaScript to play in browsers.
This book is divided into nine chapters with each one focusing on one topic. We will create
six games and specifically learn how we draw game objects, animate them, add audio,
connect players, and build a physics game with a Box2D physics engine.

What this book covers

Chapter 1, Introducing HTML5 Games, introduces the new features from HTML5, CSS3, and
related JavaScript API. It also demonstrates what games we can make with these features
and its benefits.
Chapter 2, Getting Started with DOM-based Game Development, kick-starts the game
development journey by creating a traditional Ping Pong game in DOM and jQuery.
Chapter 3, Building Memory Matching Game in CSS3, walks through the new features from
CSS3 and discusses how we can create a memory card matching game in DOM and CSS3.
Chapter 4, Building Untangle Game with Canvas and Drawing API, introduces a new way
to draw games and interact with them in a web page with the new Canvas element. It also
demonstrates how to build a puzzle solving game with Canvas.

Preface

Chapter 5, Building a Canvas Game Masterclass, extends the untangle game to show how we
can draw gradients and images using Canvas. It also discusses sprite sheet animations and
multi-layer management.
Chapter 6, Adding Sounds Effects to Your Games, adds sound effects and background music
to the game by using the Audio element. It discusses the audio format capability among
web browsers and creates a keyboard-driven music game by the end of the chapter.
Chapter 7, Using Local Storage to Store Game Data, extends the CSS3 memory matching
game to demonstrate how we can use the new Local Storage API to store and resume game
progress and best records.
Chapter 8, Building a Multiplayer Draw-and-Guess Game with WebSockets, discusses the
new WebSockets API which allows browsers to establish a persistent connection with the
socket server. This allows multiple players to play the game together in real time. A drawand-guess game is created at the end of chapter.
Chapter 9, Building a Physics Car Game with Box2D and Canvas, teaches how to integrate
a famous physics engine, Box2D, into our Canvas games. It discusses how to create physics
bodies, apply force, connect them together, associate graphics with the physics, and finally
create a platform card game.

What you need for this book

You need the latest modern web browsers, a good text editor, and a basic HTML, CSS, and
JavaScript knowledge.

Who this book is for

This book is for game designers who have a basic understanding of HTML, CSS, and JavaScript
and want to create Canvas or DOM-based games that run on browsers.

Conventions

In this book, you will find several headings appearing frequently.
To give clear instructions of how to complete a procedure or task, we use:

[]

Preface

Time for action – heading
1.

Action 1

2.

Action 2

3.

Action 3

Instructions often need some extra explanation so that they make sense, so they are
followed with:

What just happened?
This heading explains the working of tasks or instructions that you have just completed.
You will also find some other learning aids in the book, including:

Pop quiz – heading
These are short multiple choice questions intended to help you test your own understanding.

Have a go hero – heading
These set practical challenges and give you ideas for experimenting with what you
have learned.
You will also find a number of styles of text that distinguish between different kinds of
information. Here are some examples of these styles, and an explanation of their meaning.
pment
Code words in text are shown as follows: "We will start our HTML5 game develo�������
journey from index.html."
A block of code is set as follows:
// starting game
var date = new Date();
audiogame.startingTime = date.getTime();
// some time later
var date = new Date();
var elapsedTime = (date.getTime() - audiogame.startingTime)/1000;

[]

Preface

When we wish to draw your attention to a particular part of a code block, the relevant lines
or items are set in bold:
function setupLevelData()
{
var notes = audiogame.leveldata.split(";");
// store the total number of dots
audiogame.totalDotsCount = notes.length;
for(var i in notes)
{
var note = notes[i].split(",");
var time = parseFloat(note[0]);
var line = parseInt(note[1]);
var musicNote = new MusicNote(time,line);
audiogame.musicNotes.push(musicNote);
}
}

Any command-line input or output is written as follows:
$ ./configure
$ sudo make install

New terms and important words are shown in bold. Words that you see on the screen, in
menus or dialog boxes for example, appear in the text like this: "You will get an introduction
page of the multiuser sketchpad. Right click on the Launch Experiment option and choose
Open link in new window".
Warnings or important notes appear in a box like this.

Tips and tricks appear like this.

[]

Preface

Reader feedback

Feedback from our readers is always welcome. Let us know what you think about this
book—what you liked or may have disliked. Reader feedback is important for us to develop
titles that you really get the most out of.
To send us general feedback, simply send an e-mail to feedback@packtpub.com, and
mention the book title via the subject of your message.
If there is a book that you need and would like to see us publish, please send us a note in the
SUGGEST A TITLE form on www.packtpub.com or e-mail suggest@packtpub.com.
If there is a topic that you have expertise in and you are interested in either writing or
contributing to a book, see our author guide on www.packtpub.com/authors.

Customer support

Now that you are the proud owner of a Packt book, we have a number of things to help you
to get the most from your purchase.

Downloading the example code for this book
You can download the example code files for all Packt books you have purchased from your
account at http://www.PacktPub.com. If you purchased this book elsewhere, you can
visit http://www.PacktPub.com/support and register to have the files e-mailed directly
to you.

Errata
Although we have taken every care to ensure the accuracy of our content, mistakes do
happen. If you find a mistake in one of our books—maybe a mistake in the text or the
code—we would be grateful if you would report this to us. By doing so, you can save other
readers from frustration and help us improve subsequent versions of this book. If you
find any errata, please report them by visiting http://www.packtpub.com/support,
selecting your book, clicking on the errata submission form link, and entering the details
of your errata. Once your errata are verified, your submission will be accepted and the errata
will be uploaded on our website, or added to any list of existing errata, under the Errata
section of that title. Any existing errata can be viewed by selecting your title from
http://www.packtpub.com/support.

[]

Preface

Piracy
Piracy of copyright material on the Internet is an ongoing problem across all media. At Packt,
we take the protection of our copyright and licenses very seriously. If you come across any
illegal copies of our works, in any form, on the Internet, please provide us with the location
address or website name immediately so that we can pursue a remedy.
Please contact us at copyright@packtpub.com with a link to the suspected
pirated material.
We appreciate your help in protecting our authors, and our ability to bring you
valuable content.

Questions
You can contact us at questions@packtpub.com if you are having a problem with any
aspect of the book, and we will do our best to address it.

[]

1

Introducing HTML5 Games
Hyper-Text Markup Language, HTML, has been shaping the Internet in the
last few decades. It defines how content is structured in web and the linkage
between related pages. HTML keeps evolving from version 2 to HTML 4.1,
and later XHTML 1.1. Thanks to those web applications and social network
applications, HTML is now on the way to HTML5.
Cascading Style Sheet (CSS) defines how web pages are presented visually. It
styles all HTML elements and the styles of their states, such as hover and active.
JavaScript is the logic controller of the web page. It makes the web page
dynamic and provides client-side interaction between the page and users. It
accesses the HTML through Document Object Model (DOM). It re-styles the
HTML elements by applying different CSS styles.

These three receipts bring us the new game market, HTML5 Games. With the new power
from them, we can design games with HTML5 elements, CSS3 properties, and JavaScript to
play in the browsers.
In this chapter, we shall:
 Discover new features in HTML5
 Discuss what makes us so excited around HTML5 and CSS3
 Take a look at what others are playing with HTML5 on game designing
 Preview what games we are going to build in later chapters
So let's get started.

Introducing HTML5 Games

Discovering new features in HTML5
There are many new things introduced in HTML5 and CSS3. Before getting our hands dirty in
creating the games, let's take an overview of the new features and see how we can use them
to create games.

Canvas
Canvas is an HTML5 element that provides drawing shapes and bitmap manipulation
functions in low level. We can imagine the Canvas element as a dynamic image tag. The
traditional  tag shows a static image. Whether the image is dynamically generated or
statically loaded from the server, the image is static and will not be changed. We can change
the  tag to another image source or apply styles to the image, but we cannot modify
the image bitmap context itself.
On the other hand, Canvas is like a client-side dynamic  tag. We can load images inside
it, draw shapes there, and interact with it by JavaScript.
Canvas plays an important role in HTML5 game development. It is one of our main focuses in
this book.

Audio
Background music and sound effects are often an essential element in game design. HTML5
comes with native audio support by the audio tag. Thanks to this feature, we do not require
the proprietary Flash Player to play sound effects in our HTML5 games. We will discuss the
usage of the audio tag in Chapter 6, Building Music Games with HTML5 Audio Elements.

GeoLocation
GeoLocation lets the web page retrieve the latitude and longitude of the user's computer.
This feature may not have been so useful years ago when everyone was using the Internet
with their desktop PC. There are not many things that we need the road level location
accuracy of the user. We can get the rough location by analyzing the IP address.
These days, more and more users are going on the Internet with their powerful
smartphones. Webkit and other modern mobile browsers are in everyone's pocket.
GeoLocation lets us design mobile applications and games to play with the location.
Location-based services have been used in several social networking applications such
as foursquare (http://foursquare.com) and Gowalla (http://gowalla.com). The
success of this type of location-based social community creates a trend of using location
services with our smartphone.

[]

Chapter 1

WebGL
WebGL extends the Canvas element by providing a set of 3D graphics API in the web
browser. The API follows the standard of OpenGL ES 2.0. The WebGL provides a real 3D
rendering place for 3D HTML5 games. However, not all browsers natively support the WebGL
yet at the time of writing this book. Currently only Mozilla Firefox 4, Google Chrome, and a
nightly build of WebKit browser support it natively.
The technique of creating games for WebGL is quite different from usual HTML5 game
developments. Creating games in WebGL requires handing the 3D models and use of API
similar to the OpenGL. Therefore, we will not discuss the WebGL game development in
this book.
The following screenshot from Google Body (http://bodybrowser.googlelabs.com)
demonstrates how they use WebGL to show a 3D human body that responds to the
user's input:

The LearningWebGL (http://learnwebgl.com) provides a collection of
tutorials on getting started with WebGL. It is a good starting point if you want
to learn more on using it.
[]

Introducing HTML5 Games

WebSocket
WebSocket is part of the HTML5 spec for connecting the web page to a socket server. It
provides us with an event-driven connection between the browser and server. That means
the client does not need to poll the server for new data every short period. The server will
push updates to the browsers whenever there is any data to update. One benefit of this
feature is that the game players can interact with each other almost in real time. When one
player does something and sends data to the server, the server will broadcast an event to
every other connected browser to acknowledge what the player just did. This creates the
possibility of creating multiplayer HTML5 games.

Due to a security issue, WebSocket is now temporary disabled by Mozilla
Firefox and Opera. Safari and Chrome may also drop the support on
WebSocket until the issue is fixed. You can learn more on this issue by
visiting the following link: http://hacks.mozilla.org/2010/12/
websockets-disabled-in-firefox-4/.

Local Storage
HTML5 provides a persistent data storage solution to web browsers.
Local Storage stores key-value paired data persistently. The data is still there after the
browser terminates. Moreover, the data is not limited to be accessible only to the browsers
that created it. It is available to all browser instances with the same domain. Thanks to Local
Storage, we can easily save game status, such as progress and earn achievements, locally in
web browsers.
HTML5 also provides Web SQL Database. It is a client-side relational database and is
currently supported by Safari, Chrome, and Opera. With the database storage, we can
not only store key-value paired data but also complicated relational structures that support
SQL queries.
Local Storage and Web SQL Database are useful for us to save game state locally when
creating games.
Besides Local Storage, some other storage approaches are now being supported by web
browsers. These include Web SQL Database and IndexedDB. These approaches support
querying the stored data with condition and thus are more powerful for supporting a
complicated data structure.
You can find more information on using the Web SQL Database and IndexedDB in the
following link from Mozilla: http://hacks.mozilla.org/2010/06/comparingindexeddb-and-webdatabase/.
[ 10 ]

Chapter 1

Offline application
Normally we need an Internet connection to browse web pages. Sometimes we can browse
cached offline web pages. These cached offline web pages usually expire quickly. With the
next offline application introduced by HTML5, we can declare our cache manifest. It is a list
of files that will be stored for later access without an Internet connection.
With the cache manifest, we can store all the game graphics, game control JavaScript
files, CSS stylesheets, and the HTML files locally. We can pack our HTML5 games as an
offline game on the desktop or the mobile device. Players can play the games even in
airplane mode.
The following screenshot from the Pie Guy game (http://mrgan.com/pieguy) shows
an HTML5 game in iPhone without an Internet connection. Note the little airplane symbol
indicating the offline status:

Discovering new features in CSS3
CSS is the presentation layer as HTML is the content layer. It defines how the HTML looks. We
cannot miss the CSS when creating games with HTML5, especially for DOM-based games. We
may purely use JavaScript to create and style the games with a Canvas element. But we need
CSS when creating DOM-based HTML5 games. Therefore, let's take a look at what is new in
CSS3 and how we can use the new properties to create games.
[ 11 ]

Introducing HTML5 Games

Instead of directly drawing and interacting on the Canvas drawing board, new CSS3
properties let us animate the DOM in different ways. This makes it possible to make
more complicated DOM-based browser games.

CSS3 transition
Traditionally, the style changes immediately when we apply a new style to an element.
CSS3 transition applies tweening during the style changes of the target elements.
For example, we have a blue box here and want to change it to red when we do a
mouseover. We will use the following code snippets:
HTML:


CSS:
a.box {
display:block;
width: 100px;
height: 100px;
background: #00f; /* blue */
border: 1px solid #000;
}
a.box:hover {
background: #f00;
}

The box changes to red immediately when we do a mouseover. With CSS3 transition applied,
we can tween the styles with a specific duration and the easing value:
a.box {
-webkit-transition: all 5s linear;
}

Downloading the example code for this book
You can download the example code files for all Packt books you have
purchased from your account at http://www.PacktPub.com. If you
purchased this book elsewhere, you can visit http://www.PacktPub.
com/support and register to have the files e-mailed directly to you.

[ 12 ]

Chapter 1

The following screenshot shows the box hover effect with the transition applied:

Since the CSS3 spec is still in draft and not yet fixed, the implementation from
different browser vendors may have some minor differences to the W3C spec.
Therefore, browser vendors tend to implement their CSS3 properties with a
vendor prefix to prevent conflict.
Safari and Chrome use the -webkit- prefix. Opera uses the -o- prefix.
Firefox uses the -moz- prefix and IE uses the -ms- prefix. It is a little
complex now to declare a CSS3 property, such as box-shadow, with several
lines of the same rule for several browsers. We can expect the prefix to be
eliminated after that property spec is fixed.
I will just use the -webkit- prefix in most examples to prevent putting so
many similar lines in the book. It is more important to get the concept instead
of reading the same rules with different vendors prefixed here.

CSS3 transform
CSS3 transform lets us scale the elements, rotate the elements, and translate their position.
CSS3 transform is divided into 2D and 3D.
We can reposition an element with translate:
-webkit-transform: translate(x,y);

or scale the element with scale transformation:
-webkit-transform: scale(1.1);

We can also scale and rotate the elements with CSS3 transform and combine other
transformations:
a.box {
-webkit-transition: all 0.5s linear;
-webkit-transform: translate(100px,50px);
}
a.box:hover {
-webkit-transform: translate(100px,50px) scale(1.1) rotate(30deg);
}
[ 13 ]

Introducing HTML5 Games

The following screenshots show the CSS3 transform effect when we do a mouseover:

CSS3 transform 3D further extends the spaces into three axes and it currently works only
on Safari and Mobile Safari. The following screenshot from WebKit.org shows a 3D card
flipping effect when we do a mouseover:

CSS3 animation
CSS3 transition is one type of animation. It declares the tweening animation between two
styles of the elements.
CSS3 animation is one step further. We can define key frames of an animation. Each key
frame contains a set of properties that should change at that moment. It is like a set of CSS3
transitions applied in sequence to the target element.

[ 14 ]

Chapter 1

The AT-AT Walker (http://anthonycalzadilla.com/css3-ATAT/index-bones.html)
shows a nice demo on creating a skeleton bone animation with CSS3 animation key frames,
transform, and transition:

Learning more detail of new HTML5 and CSS3 features
HTML5Rocks (http://html5rocks.com) from Google provides a solid quick start guide on
new HTML5 elements and CSS3 properties.
Apple also showcases how appealing it can be by using HTML5 in the WebKit-based browser
in their homepage (http://apple.com/html5).
CSS3 Info (http://www.css3.info) is a blog with the latest CSS3 news. It is a good place
to get the latest CSS3 spec status, compatible list, and basic CSS3 codes.

The benefit of creating HTML5 games
We explored several key new features from HTML5 and CSS3. With these features, we can
create HTML5 games on browsers. But why do we need to do that? What is the benefit of
creating HTML5 games?

[ 15 ]

Introducing HTML5 Games

No third-party plugin required
With the native support of all those features in modern browsers, we do not require the
users to pre-install any third-party plugin in order to play. These plugins are not standard.
They are proprietary and usually require an extra plugin installation that we may not be able
to install.

Supporting iOS devices without plugin
Millions of Apple iOS devices around the world do not support third-party plugins such as
Flash Player. Despite whatever reason Apple does not allow Flash Player running on their
Mobile Safaris, HTML5 and related web standard is what they get in their browsers. We can
reach this user base by creating HTML5 games that optimize for mobiles.

Breaking the boundary of usual browser games
In traditional game designing, we build games within a boundary box. We play video games
on a television. We play Flash games in web browsers with a rectangle boundary.
With creativity, we are not bound in a rectangle game stage any more. We can have fun
with all the page elements and we can even use many browser windows to compose
a game. Furthermore, we can even just use the URL bar to create a game (http://
probablyinteractive.com/url-hunter). It may sound confusing, but it is because not
many web pages have done this yet.
Photojojo (http://photojojo.com/store/awesomeness/cell-phone-lenses), an
online photography store, provides a fun Easter egg feature on their store page. There is a
switch button on the page with a caption Do not pull. When the user clicks on it, an orange
arm appears from the top with frame-by-frame animation. It holds the web page like a
holding cloth and pulls the whole page up to create a funny scroll-down effect. This is not a
game, but it is fun enough to demonstrate how we can break the boundary.

[ 16 ]

Chapter 1

Here is another example named Twitch (http://reas.com/twitch/) from Chrome
Experiments. It is a collection of mini games where the player has to carry the ball from
the starting point to the end point. The fun part is that each mini game is a small browser
window. When the ball reaches the destination point of that mini game, it is transferred into
the newly created mini game browser to continue the journey. The following screenshot
shows the whole map of Twitch with the individual web browser:

[ 17 ]

Introducing HTML5 Games

Building HTML5 games
Thanks to the new features from HTML5 and CSS3, we can now create an entire game
in the browser. We can control every element in the DOM. We can animate each
document object with CSS3. We have Canvas to dynamically draw things and interact
with them. We have an audio element to handle the background music and sound effects.
We also have Local Storage to save game data and WebSocket to create a real time
multiplayers game. Most modern browsers are already supporting these features. It is
now time to build HTML5 games.

What others are playing with HTML5
It is a good chance to study how different HTML5 games perform by watching other HTML5
games made with different techniques.

Matching game
The Match game (http://10k.aneventapart.com/Uploads/300/) demonstrates a
beautiful matching game with CSS3 animation and other visual enhancements. The game
starts when you press the 3D-like CSS button. The cards present at the back and the front
side are flipped using 3D rotation. The front side patterns are fetched dynamically from an
online gallery.

[ 18 ]

Chapter 1

Sinuous
Sinuous (http://10k.aneventapart.com/Uploads/83/), winner of the 10K Apart,
shows us how a simple game idea with proper implementation can get people addicted to
it. The player controls the big dots in the space with the mouse. The aim is to move the dots
to avoid the flying comets. It sounds easy and simple, but it is definitely addictive and a justone-more-try game. The game is created with a Canvas tag. Players can also play this game
with their webkit-enabled mobile devices, such as iPhone, iPad, and Android.

Asteroid-styled bookmarklet
Erik, a web designer from Sweden, created an interesting bookmarklet. It is an
asteroid-styled game for any web page. Yes, any web page. It shows an abnormal way
to interact with any web page. It creates a plane on the website you are reading from.
You can then fly the plane using arrow keys and fire bullets using the space bar. The fun
part is that the bullets will destroy the HTML elements on the page. Your goal is to destroy
all the things on the web page you choose. This bookmarklet is another example of breaking
the boundary of usual browser games. It tells us that we can think outside the box while
designing HTML5 games.
The bookmarklet is available for installation at http://erkie.github.com/.

[ 19 ]

Introducing HTML5 Games

The following screenshot shows the plane destroying the content on the web page:

Quake 2
Google demonstrates a WebGL HTML5 port of the first person shooter game, Quake 2.
Players move around using the WSAD key and shoot enemies with their mouse. Players
can even play with each other in real time by using WebSocket. According to Google, the
frame-per-seconds of the HTML5 Quake 2 can be up to 60 fps.

The Quake 2 port is available on Google Code at http://code.google.com/p/quake2gwt-port/.
[ 20 ]

Chapter 1

RumpeTroll
RumpeTroll (http://rumpetroll.com/) is an experiment of the HTML5 community
where everyone gets connected via WebSocket. We can give our creatures names and move
around through mouse clicks. We can also type anything to start a chat. Moreover, we can
see what others are doing in real time, thanks to the WebSocketInsert.

Scrabb.ly
Scrabb.ly (http://scrabb.ly) is a multiplayer crossword board game which won the
popularity prize in the Node.js Knockout contest. It connects users together with HTML5
WebSocket. This online board game is DOM-based and driven by JavaScript.

[ 21 ]

Introducing HTML5 Games

Node.js (htt���������������
p://nodejs.org) is an event-driven server-side JavaScript.
It can be used as a server connecting concurrent WebSocket clients.

Aves Engine
Aves Engine is an HTML5 game development framework developed by dextrose. It provides
tools and API for game developers building their own isometric browser game world with the
map editor. The following screenshot captured from the official demonstration video shows
how it creates an isometric world:

The engine also takes care of the 2.5 dimension isometric coordinate system, collision
detection, and other basic virtual world features. This game engine even works well on
mobile devices such as iPad and iPhone. The Aves Engine has gained a lot of attention since
its debut and is now acquired by Zynga Game Network Inc, a big social game company.
The video demonstration of the Aves Engine is available on YouTube at the following link:
http://tinyurl.com/dextrose-aves-engine-sneak

Browsing more HTML5 games
These examples are just a selected few. The following sites provide updates on HTML5 games
created by others:
 Canvas Demo (http://canvasdemo.com) collects a set of applications and games
using the HTML5 Canvas tag. It also provides a bunch of Canvas tutorial resources. It
is a good place to start learning Canvas.
[ 22 ]

Chapter 1

 HTML5 games (http://html5games.com) collect many HTML5 games and
organizes them into categories.
 Mozilla Labs hosted a HTML5 game design contest in early 2011 and many great
games were submitted to the contest. The contest is now over and the list of all the
entries is at the following link: https://gaming.mozillalabs.com/games/.
 The HTML5 Game Jam (http://www.html5gamejam.com/games) is an
HTML5 event and the website lists a collection of fun HTML5 games and also
some useful resources.

What we are going to create in this book
In the following chapters, we are going to build six games. We are going to first create a
DOM-based Ping Pong game that can be played by two players in the same machine. Then
we will create a memory matching game with CSS3 animation. Later, we will use Canvas to
create an untangle puzzle game. Next, we will build a music game with audio elements. Then
we will create a multiplayer draw and guess game with WebSocket. Lastly, we will use the
Box2D JavaScript port to create a prototype of a physics car game. The following screenshot
is of the memory matching game that we will build in Chapter 3, Building a Memory
Matching Game in CSS3

[ 23 ]

Introducing HTML5 Games

Summary
We learned a lot in this chapter about basic information of HTML5 games.
Specifically, we covered:
 New features from HTML5 and CSS3. We had a glimpse of what techniques we will
use to create our games in later chapters. Canvas, audio, CSS animation, and more
new features were introduced. We will have many new features to play with.
 The benefit of creating HTML5 games. We discussed why we want to create HTML5
games. We want to meet the web standard, meet the mobile devices, and break the
boundary of a game.
 HTML5 games that others are playing. We listed several existing HTML5 games that
were created with different techniques that we will use. We can test those games
before creating our own.
 We also previewed the games that we are going to build throughout the book.
Now that we've learned about some background information of HTML5 games, we're ready
to create our first DOM-based JavaScript-driven game in the next chapter.

[ 24 ]

2

Getting Started with DOM-based
Game Development
We have had an idea about what we are going to learn in the whole book in
Chapter 1, Introducing HTML5 Games. From this chapter, we will go through a
lot of learning-by-doing sections and we will focus on one topic in each section.
Before digging deeply into the cutting edge CSS3 animations and HTML5
Canvas game, let's start with traditional DOM-based game development.
We will warm up with some basic techniques in this chapter.

In this chapter, we will be:
 Preparing the development tools
 Setting up our first game—Ping Pong
 Learning basic positioning with the jQuery JavaScript library
 Getting keyboard inputs
 Creating the Ping Pong game with scoring

Getting Started with DOM-based Game Development

The following screenshot shows the game we will get after this chapter. It is a Ping Pong
game played by two players with one keyboard simultaneously:

So, let's get on with making our Ping Pong.

Preparing the development environment
The environment for developing HTML5 games is similar to designing websites. We need
web browsers with the required plugin and a good text editor. Which text editor is good is a
never-ending debate. Each text editor comes with its own strength, so just pick your favorite
one. For the browser, we will need a modern browser that supports the latest HTML5, CSS3
spec, and provides us with handy tools for debugging.
There are several modern browser choices on the Internet now. They are Apple Safari
(http://apple.com/safari/), Google Chrome (http://www.google.com/chrome/),
Mozilla Firefox (http://mozilla.com/firefox/), and Opera (http://opera.com).
These browsers support most features we discuss in the examples in the whole book. We
will use Google Chrome to demonstrate most examples in the book because it runs fast and
smooth with CSS3 transition and Canvas.

Preparing the HTML documents for a DOM-based game
Every website, web page, and HTML5 game starts with a default HTML document. Moreover,
the document starts with a basic HTML code. We will start our HTML5 game development
journey from index.html.

[ 26 ]

Chapter 2

Time for action – Installing the jQuery library
We will create our HTML5 Ping Pong game from scratch. It may sound as if we are going
to be preparing all the things ourselves. Luckily, at least we can use a JavaScript library to
help us. jQuery is the JavaScript library we will be using in the whole book. It will help us in
simplifying our JavaScript logic:

1.

Create a new folder named pingpong.

2.

Create a new folder named js inside the pingpong directory.

3.

Now it's time to download the jQuery library. Go to http://jquery.com/.

4.

Select Production and click on Download jQuery.

5.

Save jquery-1.4.4.min.js in the js folder we created in step 2.

6.

Create a new document named index.html and save it in the first game folder.

7.

Open index.html in text editor and insert an empty HTML template:




Ping Pong


Ping Pong

This is an example of creating a Ping Pong Game.
8. Include the jQuery JavaScript file by adding the following line before the closing of the body tag: [ 27 ] Getting Started with DOM-based Game Development 9. Finally, we have to ensure that jQuery is loaded successfully. We place the following code before the close of the body tag and after the jQuery: 10. Save the index.html and open it in the browser. We should see the following alert window showing our text. This means our jQuery is correctly set up: What just happened? We just created a basic HTML5 page with jQuery and ensured that the jQuery is loaded correctly. New HTML5 doctype The DOCTYPE and meta tags are simplified in HTML5. In HTML4.01, we declare doctype as the following code: It is a long line of code, right? While in HTML5, the doctype declaration cannot be simpler: We even do not have the HTML version in the declaration. This implies that HTML5 will support all existing content of previous HTML versions. Future HTML versions will also support the existing content of HTML5. The simplification also comes to meta tag. We define the charset of the HTML by using the following short line now: [ 28 ] Chapter 2 Header and footer HTML5 comes with many new features and improvements, one of them is semantics. HTML5 adds new elements to improve the semantics. We just used two, header and footer. Header gives a heading introduction to the section or the entire page. Therefore, we put the h1 title inside header. Footer, same as its name, contains the footer information of the section or the page. A semantic HTML means that the markup itself provides meaningful information to the content instead of only defining the visual outlook. Best practice to place the JavaScript code We put the JavaScript code right before the closing tag and after all the content in the page. There is a reason for putting the code there instead of putting it inside the section. Normally, browsers load content and render them from top to bottom. If the JavaScript code is put in the head section, then the content of document will not be loaded until all JavaScript code is loaded. Actually, all rendering and loading will be blocked if the browsers load a JavaScript code in the middle of the page. This is the reason why we want to put the JavaScript code at the bottom when possible. In this way, we can deliver the content with higher performance. At the time of writing this book, the latest jQuery version is 1.4.4. That is why the jQuery file in our code examples is named jquery-1.4.4.min.js. This version number will be different, but the usage should be the same unless there is a big change in jQuery without backward compatibility. Running our code after the page is ready We need to ensure that the page is ready before our JavaScript code is executed. Otherwise, we may get an error when we try to access an element that is not yet loaded. jQuery provides us with a way to execute the code after the page is ready. It is the following code: jQuery(document).ready(function(){ // code here. }); Actually, what we just used is the following codes: $(function(){ // code here. }); [ 29 ] Getting Started with DOM-based Game Development The $ sign is a shortcut for jQuery. When we are calling $(something), we are actually calling jQuery(something). $(function_callback) is another shortcut for the ready event. It is identical to the following: $(document).ready(function_callback); Also, identical to: jQuery(document).ready(function_callback); Pop quiz 1. Which is the best place to put JavaScript code? a. Before the tag b. Inside the elements c. Right after the tag d. Right before the tag Setting up the Ping Pong game elements We have the preparation ready and it is time to set up the Ping Pong game. Time for action – Placing Ping Pong game elements in DOM 1. We will continue from our jQuery installation example. Open the index.html in a text editor. 2. Then, create the following playground and game objects with DIV nodes in the body. There are two paddles and one ball inside the playground. Moreover, the playground is inside the game:
[ 30 ] Chapter 2 3. We now have the game objects' structure ready and it is time to apply styles to them. Put the following styles inside the head element: 4. In the last section, we put our JavaScript logic right after the jQuery inclusion. We will put it in a separate file as our code is getting large. Therefore, create a file named html5games.pingpong.js inside the js folder. [ 31 ] Getting Started with DOM-based Game Development 5. We prepared the JavaScript file. Now it is time to link them to our HTML file. Put the following code in index.html before the tag: 6. We will place the game logic inside the html5games.pingpong.js. Our only logic now is the following paddle's initialization code: // code inside $(function(){} will run after the DOM is loaded and ready $(function(){ $("#paddleB").css("top", "20px"); $("#paddleA").css("top", "60px"); }); 7. We will test the setup in a browser. Open the index.html file in a browser and we should see a screen similar to the one shown in the following screenshot: What just happened? We have put two paddles and a ball in the Ping Pong game. We also used jQuery to initialize the position of the two paddles. Introducing jQuery jQuery is a JavaScript library that is designed for easily navigating the DOM elements, manipulating them, handling events, and creating an asynchronies remote call. It contains two major parts: selection and modification. Selection uses CSS selector syntax to select all matched elements in the web page. Modification actions modify the selected [ 32 ] Chapter 2 elements, such as add, remove children, or style. Using jQuery often means chaining selection and modifications actions together. For example, the following code selects all elements with box class and sets the CSS properties: $(".box").css({"top":"100px","left":"200px"}); Understanding basic jQuery selectors jQuery is about selecting elements and performing actions on them. We need a method to select our required elements in the entire DOM tree. jQuery borrows the selectors from CSS. The selector provides a set of patterns to match elements. The following table lists the most common and useful selectors that we will use in this book: Selector pattern Meaning Examples $("Element") Selects all elements with the given tag name $("p") selects all the p tags. Selects the element with the given ID of the attribute Provides the following code: $("#id") $("body") selects the body tag.
$("#box1") selects the highlighted element. $(".className") Selects all elements with the given class attribute Provides the following code:
class="apple">
class="orange">
class="banana">
$(".apple") selects the highlighted elements with class set to apple. $("selector1, selector2, selectorN") Selects all elements that match the given selector Provides the following code:
class="apple"> class="orange"> class="banana"> $(".apple, .orange") selects the highlighted elements that class is set to, either apple or orange. [ 33 ] Getting Started with DOM-based Game Development Understanding the jQuery CSS function The jQuery css is a function to get and set the CSS properties of the selected elements. Here is a general definition of how to use the css function: .css(propertyName) .css(propertyName, value) .css(map) The css function accepts several types of arguments as listed in the following table: Function type .css(propertyName) Arguments definitions Discussion propertyName is a CSS property The function returns the value of the given CSS property of the selected element. For example, the following code returns the value of the background-color property of the body element: $("body").css("backgroundcolor") It will only read the value and not modify the property value. .css(propertyName, value) propertyName is a CSS property, The function modifies the given CSS property to the given value. value is a value to set for the property For example, the following code sets the background color to red of all elements with box class: $(".box").css("backgroundcolor","#ff0000") .css(map) map is a set of property-value pairs to update This function is useful for setting multiple CSS properties to the same selected elements at the same time. For example, the following code sets both left and top CSS properties to the selected element with ID box1: $("#box1").css({ "left" : "40px", "top" : "100px" }) [ 34 ] Chapter 2 Benefits of using jQuery There are several advantages of using jQuery over pure JavaScript, which are as follows:  Using jQuery requires shorter code to select DOM nodes and modify them  Shorter code results in more clear code for reading, it is important in game development that usually contains a lot of code  Writing shorter code increases the development speed  Using the jQuery library enables the code to support all major browsers without extra tweaks; jQuery wraps the pure JavaScript code and deals with cross browser capability by itself Manipulating game elements in DOM with jQuery We initialized the paddles game elements with jQuery. We will do an experiment on how we use jQuery to place the game elements. Time for action – Changing position of elements with jQuery Let's inspect our Ping Pong game element with a grid background: 1. We will continue with our Ping Pong example. 2. I have prepared a grid image. Download the pixel_grid.jpg image from the following URL: http://gamedesign.cc/html5games/pixel_grid.jpg 3. Create a folder named images in the example directory. 4. Place the pixel_grid.jpg into the images folder. This image helps us inspect the pixel displacement later. 5. Next, open the index.html file in a text editor. 6. Modify the background property of the playground DIV to include the pixel grid image like the following: #playground{ background: #e0ffe0 url(images/pixel_grid.jpg); width: 400px; height: 200px; position: relative; overflow: hidden; } [ 35 ] Getting Started with DOM-based Game Development 7. Now on opening the index.html in web browser we should have the following screenshot. The game elements are overlaid on top of a grid image so we can see where the elements are placed: What just happened? We began the example by placing an image called pixel_grid.jpg. This is an image I created for easy debugging purposes. The image is divided into small grids. Every 10 x 10 grid forms a big block with 100 x 100 pixels. By placing this image as background of the DIV, we put a ruler that enables us to measure the position of its children DIVs on the screen. Understanding the behavior of absolute position When a DOM node is set to be the absolute position, the left and top properties can be treated as a coordinate. We can treat the left/top properties into X/Y coordinates with Y positive pointing down. The following graphs show the relationship. The left side is the actual CSS value and the right side is the coordinate system in our mind when programming the game: [ 36 ] Chapter 2 By default, the left and top properties refer to the top left edge of the web page. This reference point is different when any parent of this DOM node has a position style set explicitly. The reference point of the left and top properties becomes the top left edge of that parent. This is why we need to set the playground with relative position and all game elements inside with absolute position. The following code snippet from our example shows their position values: #playground{ position: relative; } #ball { position: absolute; } .paddle { position: absolute; } Pop quiz 1. Which jQuery selector is to be used if you want to select all header elements? a. $("#header") b. $(".header") c. $("header") d. $(header) Getting a keyboard input from players This book is about game development. We can think about game development as the following loop: 1. A game state is visually displayed. 2. Players input their commands. 3. The game runs according to the players' input under the designed game mechanics. 4. Loop the process again from step 1. We learned how to display game objects with CSS and jQuery in previous sections. The next thing we need to create in the game is getting input from the players. We will discuss the keyboard input in this chapter. [ 37 ] Getting Started with DOM-based Game Development Time for action – Moving DOM objects by a keyboard input We are going to create a traditional ping pong game. There are two paddles on the left and right side. A ball is placed in the middle of the playground. Players can control the left paddle and move it up and down by using w and s keys, and use arrow-up and down keys for the right paddle. We will focus on the keyboard input and leave the ball movement for the later section: 1. Let's continue with our pingpong directory. 2. Open the html5games.pingpong.js file which will contain our game logic. Our only logic now is to listen to the key down event and move the corresponding paddles up or down. Replace the content in the file with the following code: var KEY = { UP: 38, DOWN: 40, W: 87, S: 83 } $(function(){ // listen to the key down event $(document).keydown(function(e){ switch(e.which){ case KEY.UP: // arrow-up // get the current paddle B's top value in Int type var top = parseInt($("#paddleB").css("top")); // move the paddle B up 5 pixels $("#paddleB").css("top",top-5); break; case KEY.DOWN: // arrow-down var top = parseInt($("#paddleB").css("top")); // move the paddle B down 5 pixels $("#paddleB").css("top",top+5); break; case KEY.W: // w var top = parseInt($("#paddleA").css("top")); // move the paddle A up 5 pixels $("#paddleA").css("top",top-5); break; case KEY.S: // s var top = parseInt($("#paddleA").css("top")); // move the paddle A drown 5 pixels $("#paddleA").css("top",top+5); [ 38 ] Chapter 2 break; } }); }); 3. Let's test the paddle control of the game. Open the index.html in Google Chrome. Try pressing the w key, the s key, and arrow-up and down. The two paddles should be able to move up or down according to the input, but they cannot move at the same time now. What just happened? Let's take a look at the HTML code we just used. The HTML page contains header, footer information, and a DIV with ID game. The game node contains a child named playground. The playground contains three children, two paddles, and the ball. We often start the HTML5 game development by preparing a well-structured HTML hierarchy. The HTML hierarchy helps us group similar game objects (which are some DIVs) together. It is a little like grouping assets into a movie clip in Adobe Flash if you have ever made animations with it. We may also consider it as layers of game objects for us to select and style them easily. Understanding a key code Every key on the keyboard is assigned a number. By getting that number, we can find out which key is pressed. We listen to the jQuery keydown event listener. The event fires with the event object containing the key code. We can obtain the key code by calling the which function to the key down event object. [ 39 ] Getting Started with DOM-based Game Development You can try adding a console log function inside the keydown event listener and observe the representing integer of each key: $(document).keydown(function(e){ console.log(e.which); }); Making constants more readable In our example, we use the key code to check whether the player hits the keys we are interested in. Take the arrow-up key as an example. Its key code is 38. We can simply compare the key code with the number directly, as follows: $(document).keydown(function(e){ switch(e.which){ case 38: // do something when pressed arrow-up } } However, this is not a recommended practice because it makes the game code more difficult to maintain. Imagine later if we want to map the action from the arrow-up key to another key. We may not be sure whether 38 means the arrow-up. Instead, we can give the constant a meaningful name with the following code: var KEY = { UP: 38, DOWN: 40, W: 87, S: 83 } // listen to the key down event $(document).keydown(function(e){ switch(e.which){ case KEY.UP: // do something when pressed arrow-up } } By giving 38 a name KEY.UP, we can be sure that the block of code is mapped to the arrow-up key and so we can modify it without doubt when maintaining the game. Converting strings to numbers with parseInt function In most cases, we apply the left and top CSS styles to DOM elements by using the format such as 100px. We specify the unit when setting the property. It is the same when we get the value of the property. When we call $("#paddleA").css("top"), we get the value [ 40 ] Chapter 2 of 100px instead of 100. This gives us a problem when we want to perform an arithmetic operation on the value. In the example, we want to move up the paddle by setting the paddle top property to its current position minus five pixels. Let us assume paddle A has the top property set to 100px now. If we use the following expression to add five pixels, it fails and returns 100px5: $("#paddleA").css("top") + 5 It is because JavaScript executes the css function and gets "100px". Then it appends "5" to the "100px" string. We need a method to convert the "100px" string before doing any mathematical operation. JavaScript provides us with the parseInt function. Here is a general definition of how to use the parseInt function: parseInt(string, radix) The parseInt function takes one required argument and one option: Argument Definition Discussion String The string to be parsed The function parses the first number of the string. It will return NaN, Not a Number, if the given string cannot be converted into a number. It will parse the string starting with "0x" in hexadecimal by default. Take the following code as examples: parseInt("100px") returns 100. parseInt("5cm") returns 5. parseInt("0xF") returns 15. Radix Optional. A number to indicate which number system to be used The second argument forces the parseInt function to parse the string in a given number system. For example: parseInt("0x10") returns 16 parseInt("0x10",10) returns 0 parseInt("FF",16) returns 255 [ 41 ] Getting Started with DOM-based Game Development Executing JavaScript expressions directly in the Console panel You should also know that you can execute JavaScript expressions by directly typing it into the console window. The console window is a tool from the Developer Tool in Google Chrome. (There are also other similar tools in other web browsers). We can open the console by clicking on Wrench Icon | Tools | Developer tools | Console. It is a handy way to quickly test a simple expression when you are not sure whether it works during development. The following screenshot tests the return value of the two parseInt expressions: Have a go hero Converting strings to integers can be tricky sometimes. Do you know what is the parseInt result of 10 seconds 20? How about 10x10 and $20.5? It is time to open the console panel and try converting some strings into numbers. Checking the console window We are writing more complicated logic code now. It is good practice to keep an eye on the console of the Developers Tools. If the code contains any error or warning, the error message will appear there. It reports any error found and the line of code that contains the error. It is very useful and important to have the console window open when testing the HTML5 games. I have seen many times that people get stuck and have no idea as to why the code is not working. The reason is that they have a typo or syntax error and they did not check the console window until fighting with the code for hours. [ 42 ] Chapter 2 The following screenshot shows that there is an error in line 25 of the html5games. pingpong.js file. The error message is Invalid left-hand side in assignment. After inspecting the code, I found that I wrongly used an equal sign (=) when setting the CSS top property in jQuery: $("#paddleA").css("top"=top+5); // instead of the correct code: // $("#paddleA").css("top", top+5); Supporting multiple keyboard input from players The previous input method only allows one input at a time. The keyboard input is also not so smooth. Imagine now that two players are playing the Ping Pong game together. They cannot control the paddle well because their inputs interrupt the others. In this section, we are going to modify our code to make it support multiple keyboard inputs. Time for action – Listening to keyboard input with another approach We will use another approach to handle the key down event. This approach will be a lot smoother and supports multiple inputs at the same time: 1. Open the html5games.pingpong.js we used in the last section. 2. Delete all the code we coded there. It is simpler to start from scratch. [ 43 ] Getting Started with DOM-based Game Development 3. We will need a global variable of array to store the key pressed status. Enter the following code in the opened JavaScript file: var pingpong = {} pingpong.pressedKeys = []; 4. The next thing is the code is executed once the page is loaded and ready. It will listen and mark the pressed key. Put the following code in the JavaScript file after the two lines we just coded there: $(function(){ // set interval to call gameloop every 30 milliseconds pingpong.timer = setInterval(gameloop,30); // mark down what key is down and up into an array called "pressedKeys" $(document).keydown(function(e){ pingpong.pressedKeys[e.which] = true; }); $(document).keyup(function(e){ pingpong.pressedKeys[e.which] = false; }); }); 5. We have stored the key which is pressed. What we are missing is actually moving the paddles. We set a timer to continuously call a function to move the paddles. Paste the following code in the html5games.pingpong.js file: function gameloop() { movePaddles(); } function movePaddles() { // use our custom timer to continuously check if a key is pressed. if (pingpong.pressedKeys[KEY.UP]) { // arrow-up // move the paddle B up 5 pixels var top = parseInt($("#paddleB").css("top")); $("#paddleB").css("top",top-5); } if (pingpong.pressedKeys[KEY.DOWN]) { // arrow-down // move the paddle B down 5 pixels var top = parseInt($("#paddleB").css("top")); $("#paddleB").css("top",top+5); } [ 44 ] Chapter 2 if (pingpong.pressedKeys[KEY.W]) { // w // move the paddle A up 5 pixels var top = parseInt($("#paddleA").css("top")); $("#paddleA").css("top",top-5); } if (pingpong.pressedKeys[KEY.S]) { // s // move the paddle A down 5 pixels var top = parseInt($("#paddleA").css("top")); $("#paddleA").css("top",top+5); } } 6. Let's test what we just coded. Save all the files and open index.html in the web browser. 7. Try pressing the keys to control both paddles. The two paddles should move smoothly and respond at the same time without interruption. What just happened? We have used another approach to capture the keyboard input. Instead of doing the action once after the key press is detected, we store which keys are pressed and which are not. Afterwards, we use a JavaScript interval to check the pressed keys every 30 milliseconds. This approach enables us to know all the keys pressed at the time and so we can move both paddles at the same time. Declaring global variables in a better way Global variables are variables that can be accessed globally in the entire document. Any variable that is declared outside any function is a global variable. For instance, in the following example code snippets, a and b are global variables while c is a local variable that only exists inside the function: var a = 0; var b = "xyz"; function something(){ var c = 1; } Since global variables are available in the entire document, it may increase the change of variable name conflicts if we integrate different JavaScript libraries into the web page. As good practice, we should put all global variables we use into an object. [ 45 ] Getting Started with DOM-based Game Development In the Time for action section, we have a global array to store all pressed keys. Instead of just putting this array in global scope, we created a global object named pingpong and put the array inside it: var pingpong = {} pingpong.pressedKeys = []; In the future, we may need more global variables and we will put them all inside the pingpong object. This reduces the chance of name confliction to only one name, pingpong. Creating a JavaScript timer with setInterval function The pressed keys are stored in the array and we have a timer to loop and check the array periodically. This can be done by the setInterval function in JavaScript. Here is the general definition of the setInterval function: setInterval(expression, milliseconds) The setInterval takes two required arguments: Argument Definition Discussion expression The function call back or code expression to be executed The expression can be a reference of function call back or an inline code expression. The inline code expression is quoted and reference of function call back is not. For example, the following code calls the hello function 100 milliseconds: setInterval(hello,100); The following code calls the hi function with parameters every 100 milliseconds: setInterval("hi('Makzan')",100); milliseconds The duration between every execution of the expression, in milliseconds The unit of the interval is in milliseconds. Therefore, setting it to 1000 means running the expression every second. Understanding Game Loop We have a timer to execute some game-related code every 30 milliseconds, so this code is executed 33.3 times per second. In game development, this is called Game Loop. [ 46 ] Chapter 2 There are several common things we will execute inside a game loop:  Processing user input, which we just did  Updating game objects' status, including position and appearance  Checking game over What is actually executing in the game loop differs in different types of games but the purpose is the same. The game loop is executed periodically to help run the game smoothly. Moving a DOM object with JavaScript Interval Imagine now we can make the little red ball move around in the playground. The ball will bounce away when it hits the paddles. The player will lose a score when the ball passes the paddle and hits the playground edge behind the paddle. All these actions are manipulating the position of the DIVs inside the HTML page by jQuery. To complete this Ping Pong game, our next step is to move the ball. Time for action – Moving the ball with JavaScript Interval We just learnt and used the setInterval function to create a timer. We will use the timer to move the ball a little bit every 30 milliseconds. We are going to also change the direction of the ball movement once it hits the playground edge. Let's make the ball move now: 1. We will use our last example, listening to multiple keyboard inputs, as the starting point. 2. Open the html5games.pingpong.js file in the text editor. 3. We are now moving the ball and we need to store the ball status globally. We will put the ball-related variable inside the pingpong object: pingpong.ball = { speed: 5, x: 150, y: 100, directionX: 1, directionY: 1 } [ 47 ] Getting Started with DOM-based Game Development 4. In every game loop, we used to move the paddles. Now we will move the ball as well. Add a moveBall function call to the gameloop function: function gameloop() { moveBall(); movePaddles(); } 5. It is time to define the moveBall function. The function is divided into four parts, it gets the current ball position, checks the boundaries of the playground, changes the direction of the ball when hitting the boundaries and actually moves the ball after all these calculations. Let's put the following moveBall function definition in the JavaScript file: function moveBall() { // reference useful variables var playgroundHeight = parseInt($("#playground").height()); var playgroundWidth = parseInt($("#playground").width()); var ball = pingpong.ball; // check playground boundary // check bottom edge if (ball.y + ball.speed*ball.directionY > playgroundHeight) { ball.directionY = -1; } // check top edge if (ball.y + ball.speed*ball.directionY < 0) { ball.directionY = 1; } // check right edge if (ball.x + ball.speed*ball.directionX > playgroundWidth) { ball.directionX = -1; } // check left edge if (ball.x + ball.speed*ball.directionX < 0) { ball.directionX = 1; } ball.x += ball.speed * ball.directionX; ball.y += ball.speed * ball.directionY; // check moving paddle here, later. [ 48 ] Chapter 2 // actually move the ball with speed and direction $("#ball").css({ "left" : ball.x, "top" : ball.y }); } 6. We have prepared the code to move the ball every 30 milliseconds. Save all files and open index.html in Google Chrome to test it. 7. The paddles work just as in the last example and the ball should be moving around the playground. What just happened? We just successfully made the ball move around the playground. We have a loop to run routine game logic every 30 milliseconds. Inside that game loop, we move the ball five pixels at a time. There are three properties of the ball, speed, and direction X/Y. The speed defines how many pixels the ball moves in each step. The direction X/Y is either 1 or -1. We move the ball with the following equation: new_ball_x = ball_x_position + speed * direction_x new_ball_y = ball_y_position + speed * direction_y The direction value is multiplied by the movement. When the direction is 1, the ball moves to the positive direction of the axis. When the direction is -1, the ball moves to the negative direction. By toggling the X and Y directions, we can move the ball in four directions. We compare the ball's X and Y with the four edges of the playground DIV element. This checks whether the ball's next position is beyond the boundary and then we toggle the direction between 1 and -1 to create the bouncing effect. Beginning collision detection We have checked the boundary of the playground when moving the ball in the previous section. Now we can control the paddles with the keyboard and watch the ball moving around the playground. What is missing now? We cannot interact with the ball. We control the paddles but the ball just passes through them as if they are not there. It is because we missed the collision detection between the paddles and the moving ball. [ 49 ] Getting Started with DOM-based Game Development Time for action – Hitting the ball with the paddles We will use a similar approach of checking the boundary to check the collision: 1. Open the html5games.pingpong.js file we used in the previous section. 2. In the moveball function, we have already reserved the place to put the collision detection code there. Find the line with // check moving paddle here. 3. Let's put the following code there. The code checks whether the ball is overlapping with either paddle and bounces the ball away when they overlap: // check left paddle var paddleAX = parseInt($("#paddleA").css("left"))+parseInt($("#pa ddleA").css("width")); var paddleAYBottom = parseInt($("#paddleA").css("top"))+parseInt($ ("#paddleA").css("height")); var paddleAYTop = parseInt($("#paddleA").css("top")); if (ball.x + ball.speed*ball.directionX < paddleAX) { if (ball.y + ball.speed*ball.directionY <= paddleAYBottom && ball.y + ball.speed*ball.directionY >= paddleAYTop) { ball.directionX = 1; } } // check right paddle var paddleBX = parseInt($("#paddleB").css("left")); var paddleBYBottom = parseInt($("#paddleB").css("top"))+parseInt($ ("#paddleB").css("height")); var paddleBYTop = parseInt($("#paddleB").css("top")); if (ball.x + ball.speed*ball.directionX >= paddleBX) { if (ball.y + ball.speed*ball.directionY <= paddleBYBottom && ball.y + ball.speed*ball.directionY >= paddleBYTop) { ball.directionX = -1; } } 4. We will also need to reset the ball in the middle area after the ball hits the left or right edge of the playground. Remove the bouncing ball code in the check right and check left code section and paste the following code there: // check right edge [ 50 ] Chapter 2 if (ball.x +ball.speed*ball.directionX > playgroundWidth) { // player B lost. // reset the ball; ball.x = 250; ball.y = 100; $("#ball").css({ "left": ball.x, "top" : ball.y }); ball.directionX = -1; } // check left edge if (ball.x + ball.speed*ball.directionX < 0) { // player A lost. // reset the ball; ball.x = 150; ball.y = 100; $("#ball").css({ "left": ball.x, "top" : ball.y }); ball.directionX = 1; } 5. Test the game in a browser and the ball will now bounce away after hitting the left or right paddle. It will also reset to the center of the playground when hitting the left or right edge. [ 51 ] Getting Started with DOM-based Game Development What just happened? We have modified the ball checking to make it bounce away when overlapping with the paddles. Moreover, we reposition the ball in the center of the playground when hitting the left and right edge. Let's see how we check the collision between the ball and the left paddle. At first, we check whether the ball's X position is less than the left paddle's right edge. The right edge is the left value plus the width of the paddle. Then we check whether the ball's Y position is between the top edge and bottom edge of the paddle. The top edge is the top value and the bottom edge is the top value plus the height of the paddle. We bounce the ball away if the ball's position passes both checks. This is how we check it and it is just a basic collision detection. We determine that the two objects are overlapped by checking their position and width/ height. This type of collision detection works well in rectangle objects but is not good for circles and other shapes. The following screenshot illustrates the issue. The collision areas shown in the following graph are false positive. Their bounding box collides but the actual shapes do not overlap each other. [ 52 ] Chapter 2 For special shapes, we will need more advanced collision detection techniques that we will discuss later. Have a go hero We check three edges of the paddles to determine whether the ball overlaps with them. If you play the game and observe the ball bouncing carefully, you will find that it is not perfect now. The ball may bounce while behind the paddles. Think about the reason and modify the code to make a better collision detection with the ball and the paddles. Showing text dynamically in HTML We have the basic game mechanics implemented in the previous sections. Our Ping Pong game is missing a scoring board now showing both players' scores. We discussed how to use jQuery to modify the CSS styles of the selected elements. Can we also alter the content of the selected elements with jQuery? Yes, we can. Time for action – Showing the score of both players We are going to create a text-based scoreboard and update the scores when either player scores a goal: 1. We are making improvements on our existing game so we use the last example as the starting point. 2. Open the index.html in the text editor. We are going to add the scoreboard DOM elements. [ 53 ] Getting Started with DOM-based Game Development 3. Add the following HTML code before the game DIV inside index.html:
Player A : 0
Player B : 0
4. Let's move onto the JavaScript part. Open the html5games.pingpong.js file. 5. We need two more global variables to store the players' scores. Add their score variables inside the pingpong global object: var pingpong = { scoreA : 0, // score for player A scoreB : 0 // score for player B } 6. We had a place to check if player B lost. We incremented the player A's score there and updated the scoreboard with the following code: // player B lost. pingpong.scoreA++; $("#scoreA").html(pingpong.scoreA); 7. We have similar code as in step 6 to update player B's score when player A lost: // player A lost. pingpong.scoreB++; $("#scoreB").html(pingpong.scoreB); 8. It is time to test our latest code. Open the index.html in a web browser. Try playing by controlling both paddles and lose some points. The scoreboard should be counting the scores correctly: [ 54 ] Chapter 2 What just happened? We just used another common jQuery function: html() to alter the content of the game on the fly. The html() function gets or updates the HTML content of the selected element. Here is a general definition of the html() function: .html() .html(htmlString) When we use the html ( ) function without an argument, it returns the HTML content of the first match element. When we use it with an argument, it sets the HTML content to all matched elements with the given HTML string. For example, provide the following HTML structure:

My name is Makzan.

My pet's name is Both the following jQuery calls return Makzan: $("#myname").html(); // returns Makzan $(".name").html(); // returns Makzan However, in the following jQuery call, it sets all matched elements to the given HTML content: $(".name").html("Mr. Mystery") Executing the jQuery command makes the following HTML result:

My name is Mr. Mystery

My pet's name is Mr. Mystery

Have a go hero – Winning the game We have the scoring now. See whether you can modify the game to make it stop after any player gets 10 points. Then show a win message. You might also want to try styling the game to make it more appealing. How about giving the scoreboard and playground some image backgrounds? Replacing the paddles with two goalkeeper characters? [ 55 ] Getting Started with DOM-based Game Development Summary We learned a lot in this chapter about basic techniques of creating a simple Ping Pong game with HTML5 and JavaScript. Specifically, we covered:  Creating our first HTML5 game—Ping Pong  Using jQuery to manipulate DOM objects  Getting keyboard inputs with multiple keys down support  Detecting collisions with the bounding box We also discussed how to create a game loop and move the ball and paddles. Now that we've warmed up by creating a simple DOM-based game, we are ready to create more advanced DOM-based games with new features from CSS3. In the next chapter, we will create games with CSS3 animation, transition, and transformation. [ 56 ] 3 Building a Memory Matching Game in CSS3 CSS3 introduces many exciting features. In this chapter, we will explore and use some of them to create a matching memory game. The CSS3 styles how the game objects look and animate while the jQuery library helps us define the game logic. In this chapter, we will:  Transform a playing card with animation  Flip a playing card with new CSS3 properties  Create the whole memory matching game  And embed a custom web font to our game So let's get on with it. Moving game objects with CSS3 transition We had a glimpse of the CSS3 transition module and transformation module in Chapter 1, Introducing HTML5 Games, when we were overviewing the new CSS3 features. We often want to animate the game objects by easing the properties. Transition is the CSS property designed for this purpose. Imagine we have a playing card on the web page and want to move it to another position in five seconds. We had to use JavaScript and setup timer and write our own function to change the position every several milliseconds. By using the transition property, we just need to specify the start and end styles and the duration. The browser does all the easing and in-between animations, magically. Building a Memory Matching Game in CSS3 Let's take a look at some examples to understand it. Time for action – Moving a playing card around In this example, we will place two playing cards on the web page and transform them to a different position, scale, and rotation. We will tween the transformation by setting the transition: 1. Create a new folder with three files in the following hierarchy. The css3transition. css and index.html is empty now and we will add the code later. The jquery1.6.min.js is the jQuery library that we have used in the previous chapter. 2. We are using two playing card graphic images in this example. The images are available in the code bundle or you can download them from http:// gamedesign.cc/html5games/css3-basic-transition/images/AK.png and http://gamedesign.cc/html5games/css3-basic-transition/ images/AQ.png. 3. Create a new folder named images and place the two card images inside. 4. The next thing is to code the HTML with two card DIV elements. We will apply CSS transition style to these two cards elements when the page is loaded: Getting Familiar with CSS3 Transition
[ 58 ] Chapter 3

Getting Familiar with CSS3 Transition

This is an example of transitioning cards.

5. It is time to define the visual styles of the playing cards via CSS. It contains basic CSS 2.1 properties and CSS3 new properties. The new CSS3 properties are highlighted: body { background: #aaa; } /* defines styles for each card */ .card { width: 80px; height: 120px; margin: 20px; background: #efefef; position: absolute; -webkit-transition: all 1s linear; } /* set the card to corresponding playing card graphics */ .cardAK { background: url(../images/AK.png); } .cardAQ { background: url(../images/AQ.png); } [ 59 ] Building a Memory Matching Game in CSS3 /* rotate the applied DOM element 90 degree */ .rotateRight { -webkit-transform: rotate3d(0,0,1,90deg); } /* move and scale up the applied DOM element */ .moveAndScale { -webkit-transform: translate3d(150px,150px,0) scale3d(1.5, 1.5, 1); } 6. Let's save all the files and open the index.html in the browser. The two cards should animate as shown in the following screenshot: What just happened? We just created two animation effects by using the CSS3 transition to tween the transform property. Please note that the new CSS3 transition and transform properties are not yet finalized. Web browsers support these drafted but stable properties with a vendor prefix. In our example to support Chrome and Safari, we used the -webkit- prefix. We can use other prefixes in the code to support other browsers, such as -moz- for Mozilla and -o- for Opera. [ 60 ] Chapter 3 Here is the usage of CSS transform: transform: transform-function1 transform-function2; The arguments of the transform property are functions. There are two sets of functions, 2D transform function and 3D. CSS transform functions are designed to move, scale, rotate, and skew the target DOM elements. The following shows the usage of the transforms functions. 2D transforms functions The 2D rotate function rotates the element clockwise on a given positive argument and counter-clockwise on the given negative argument: rotate(angle) The translate function moves the element by the given X and Y displacement: translate (tx, ty) We can translate the X or Y-axis independently by calling the translateX and translateY function as follows: translateX(number) translateY(number) The scale function scales the element by the given sx, sy vector. If we only pass the first argument, then sy will be of the same value as sx: scale(sx, sy) In addition, we can independently scale the X and Y-axis as follows: scaleX(number) scaleY(number) 3D transforms functions The 3D rotation function rotates the element in 3D space by the given [x, y, z] unit vector. For example, we can rotate the Y-axis 60 degrees by using rotate3d(0, 1, 0, 60deg): rotate3d(x, y, z, angle) We can also rotate one axis only by calling the following handy functions: rotateX(angle) rotateY(angle) rotateZ(angle) [ 61 ] Building a Memory Matching Game in CSS3 Similar to the 2D translate function, translate3d allows us to move the element in all three axes: translate3d(tx, ty, tz) translateX(tx) translateY(ty) translateZ(tz) Also, the scale3d scales the element in the 3D spaces: scale3d(sx, sy, sz) scaleX(sx) scaleY(sy) scaleZ(sz) The transform functions we just discussed are those that are common and we will use them many times. There are several other transform functions not discussed. They are matrix, skew, and perspective. If you want to find the latest CSS transforms working spec, you can visit the W3C website with the following addresses. CSS 2D Transforms Modules (http://dev.w3.org/csswg/ css3-3d-transforms/) and the 3D Transforms Modules (http://www.w3.org/TR/ css3-2d-transforms/). Tweening the styles by using CSS3 transition There are tons of new features in CSS3. Transition module is one among them that affects us most in game designing. What is CSS3 transition? W3C explains it in one sentence.: CSS transitions allows property changes in CSS values to occur smoothly over a specified duration. Normally, when we change any properties of the element, the properties are updated to the new value immediately. Transition slows down the changing process. It creates smooth in-between easing from the old value towards the new value in the given duration. Here is the usage of the transition property: transition: property_name duration timing_function delay. [ 62 ] Chapter 3 Argument property_name Definition Duration The duration the transition takes. Timing_function The timing function defines the interpolation between the start and end value. The default value is ease. Normally we will use ease, ease-in, ease-out, and linear. Delay The delay argument delays the start of the transition by the given seconds. The name of the property where the transition applies. It can be set to all. We can put several transition properties in one line. For example, the following code transits the opacity in 0.3 seconds and background color in 0.5 seconds: transition: opacity 0.3s, background-color 0.5s We can also define each transition property individually by using the following properties: transition-property, transition-duration, transition-timing-function and transition-delay. Modules of CSS3 According to W3C, CSS3 is unlike CSS 2.1 in that there is only one CSS 2.1 spec. CSS3 is divided into different modules. Each module is reviewed individually. For example, there is transition module, 2D/3D transforms module, and flexible box layout module. The reason of dividing the spec into modules is because the working progress pace of each part of the CSS3 is not the same. Some CSS3 features are rather stable, such as border radius, while some have not yet settled down. By dividing the whole spec into different parts, it allows the browser vendor to support modules that are stable. In this scenario, slow pace features will not slow down the whole spec. The aim of the CSS3 spec is to standardize the most common visual usage in web designing and this module fits this aim. Have a go hero We have translated, scaled, and rotated the playing cards. How about we try changing different values in the example? There are three axes in the rotate3d function. What will happen if we rotate the other axis? Experiment with the code yourselves to get familiar with the transform and transition modules. [ 63 ] Building a Memory Matching Game in CSS3 Creating a card-flipping effect Imagine now we are not just moving the playing card around, but we also want to flip the card element, just like we flip a real playing card. By using the rotation transform function, it is now possible to create the card-flipping effect. Time for action – Flipping a card with CSS3 We are going to start a new project and create a card-flipping effect when we click on the playing card.: 1. Let's continue on our previous code example. 2. The card now contains two faces, a front face and a back face. Replace the following code into the body tag in the HTML:
3. Then change the CSS external link to the css3flip.css file: 4. Now let's add the styles to the css3flip.css: #game { background: #9c9; padding: 5px; } /* Define the 3D perspective view and dimension of each card. */ .card { -webkit-perspective: 600; width: 80px; height: 120px; } [ 64 ] Chapter 3 5. There are two faces on each card. We are going to rotate the face late. Therefore, we define how the face transits by CSS3 transition property. We also hide the back face visibility. We will look at the detail of this property later: .face { border-radius: 10px; width: 100%; height: 100%; position: absolute; -webkit-transition: all .3s; -webkit-backface-visibility: hidden; } 6. Now it is time to style each individual face. The front face has a higher z-index than the back face: .front { background: #966; z-index: 10; } .back { background: #eaa; -webkit-transform: rotate3d(0,1,0,-180deg); z-index: 8; } 7. When we flip the card, we rotate the front face to back and back face to front. We also swap the z-index of the front and back face: .card-flipped .front { -webkit-transform: rotate3d(0,1,0,180deg); z-index: 8; } .card-flipped .back { -webkit-transform: rotate3d(0,1,0,0deg); z-index: 10; } .cardAK { background: url(../images/AK.png); } .cardAQ { background: url(../images/AQ.png); } [ 65 ] Building a Memory Matching Game in CSS3 8. Next, we will add logic after loading the jQuery library to toggle the card-flipped status when clicking on the card: 9. The styles and the scripts are now ready. Let's save all the files and preview it in our web browser. Click the playing card to flip it over and click again to flip back. What just happened? We have created a card-flipping effect toggled by a mouse click. The example made use of several CSS transforms properties and JavaScript for handling the mouse click event. Toggling class with jQuery toggleClass function We apply the class card-flipped to the card element when the mouse is clicked on the card. On the second click, we want to remove the applied card-flipped style so the card flips back again. This is called toggling a class style. jQuery provides us with a handy function named toggleClass to add or remove classes automatically, depending on whether the class is applied or not. To use the function, we simply pass the classes that we want to toggle as an argument. [ 66 ] Chapter 3 For example, the following code adds or removes the card-flipped class to an element with ID card1: $("#card1").toggleClass("card-flipped"); The toggleClass function accepts toggle from more than one class at the sample time. We can pass in several class names and separate them by using space. Here is an example of toggling two classes at the same time: $("#card1").toggleClass("card-flipped scale-up"); Controlling the visibility of overlapped elements by z-index Normally, all elements in a web page are distributed and presented without overlapping. Designing a game is a different story. We always need to deal with overlapped elements and hide them (or part of them) on purpose. Z-index, a CSS 2.1 property, helps us to control the visibility behaviors when more than one element is overlapped. In this example, we have two faces for each card, the front and the back face. The two faces are placed in the exact position. They overlap each other. The Z-index property defines which element is on top and which is behind. The elements with a higher z-index go in front of elements with a lower z-index. When they overlap, the one with the higher z-index will cover the one with the lower z-index. The following screenshot demonstrates the z-index behavior: In the card-flipping example, we swapped the z-index of both faces to ensure the corresponding face is on top of the other in both the normal state and the flipped state. The following code shows the swapping. When in a normal state, the front face has a higher z-index: .front { z-index: 10; } .back { z-index: 8; } [ 67 ] Building a Memory Matching Game in CSS3 While in a flipped state, the front face changes to a lower z-index than the back face. The back face now covers the front face: .card-flipped .front { z-index: 8; } .card-flipped .back { z-index: 10; } Introducing CSS perspective property CSS3 lets us present elements in 3D. We have been able to transform the elements in 3D space. The perspective property defines how the 3D perspective view looks. You can treat the value as far as you are looking at the object. The closer you are, the more perspective distortion there is on the viewing object. While writing this book, only Safari supported the 3D perspective feature. Chrome supports 3D transform while not supporting the perspective property. Therefore, we will have the best effect in Safari and an acceptable effect in Chrome. The following two 3D cubes demonstrate how different perspective values change the perspective view of the element: [ 68 ] Chapter 3 You can view this experiment by going to the following address in Safari: http://gamedesign.cc/html5games/perspective-cube/ Have a go hero The cube is created by putting six faces together with 3D transforms applied to each face. It used the techniques we've discussed. Try to create a cube and experiment with the perspective property. The following web page gives a comprehensive explanation on creating the CSS3 cube, and also discusses controlling the rotation of the cube through the keyboard: http://www.paulrhayes.com/2009-07/animated-css3-cube-interface-using3d-transforms/ Introducing backface-visibility Before the backface-visibility is introduced, all elements on the page present their front face to the visitor. Actually, there was no concept of the front face or back face of the element because it was the only choice. While CSS3 introduces the rotation in three axes, we can rotate an element so that its face is on the back. Try looking at your palm and rotating your wrist, your palm turns and you see the back of your palm. This happens to the rotated elements too. CSS3 introduces a property named backface-visibility to define whether we can see the back face of the element or not. By default, it is visible. The following screenshots demonstrate the two different behaviors of the backface-visibility property. At the time of writing this book, only Apple Safari supported the backface-visibility property. [ 69 ] Building a Memory Matching Game in CSS3 You can read more detailed information about different properties and functions in CSS 3D transforms on the official Webkit blog: http://webkit. org/blog/386/3d-transforms/. Creating a card matching memory game We have gong through some CSS basic techniques. Let's make a game with the techniques. We are going to make a card game. The card game makes use of transform to flip the card, transition to move the card, JavaScript to hold the logic, and a new HTML5 feature called custom data attribute. Don't worry, we will discuss each component step by step. Downloading the sprites sheet of playing cards In the card-flipping example, we were using two different playing card graphics. Now we prepare the whole deck of playing card graphics. Although we only use six playing cards in the matching game, we prepare the whole deck so we can reuse these graphics in other playing card games that we may create. There are 52 playing cards in a deck and we have one more graphic for the backside. Instead of using 53 separated files, it is good practice to put separated graphics into one big sprite sheet file. The term sprite sheet was from an old computer graphics technique that loaded one graphics texture into memory and displayed part of the graphics. One benefit of using a big sprite sheet instead of separated image files is that we can reduce the amount of HTTP requests. When the browser loads the web page, it creates a new HTTP request to load each external resource, including JavaScript files, CSS files, and images. It takes quite a lot of time to establish a new HTTP request for each separated small file. Combining the graphics into one file, largely reduces the amount of requests and thus improves the responsiveness of the game when loading in the browser. Another benefit for placing graphics into one file is to avoid the overhead of the file format header. The size of a 53 images sprite sheet is less than the sum of 53 different images with the file header in each file. The following deck of playing cards graphics is drawn and aligned in Adobe Illustrator. You can download it from http://gamedesign.cc/html5games/css3-matching-game/ images/deck.png. [ 70 ] Chapter 3 The following article explains in detail why and how we can create and use the CSS sprite sheet: http://css-tricks.com/css-sprites/ Setting up the game environment The graphics are ready, we will then need to set up a static page with the game objects prepared and placed on the game area. It is easier for adding game logic and interaction later: Time for action – Preparing the card matching game Before adding the complicated game logic to our matching game, let's prepare the HTML game structure and prepare all the CSS styles: 1. Let's continue on our code. Replace the index.html file with the following HTML: CSS3 Matching Game [ 71 ] Building a Memory Matching Game in CSS3

CSS3 Matching Game

This is an example of creating a matching game with CSS3.

2. In order to make the game more appealing, I prepared background images for the game table and the page. These graphic assets can be found in the code example bundle. The background images are optional and they will not affect the gameplay and the logic of the matching game. 3. We will also place the deck sprite sheet graphics into the images folder. Download the deck.png file from http://gamedesign.cc/html5games/css3matching-game/images/deck.png and save it into the images folder. 4. Let's add style to the matching game before writing any logic. Open matchgame. css and add the following body styles: body { text-align: center; background: #a46740 url(../images/bg.jpg); } 5. Continue to add the styles to the game element. It will be the main area of the game: #game { border-radius: 10px; border: 1px solid #666; background: #232 url(../images/table.jpg); width: 500px; [ 72 ] Chapter 3 height: 460px; margin: 0 auto; display: box; box-pack: center; box-align: center; } 6. We will put all card elements into a parent DOM named cards. By doing this, we can easily center all cards to the game area: #cards { position: relative; width: 380px; height: 400px; } 7. For each card, we define a perspective property to give it a visual depth effect: .card { -webkit-perspective: 600; width: 80px; height: 120px; position: absolute; -moz-transition: all .3s; -webkit-transition: all .3s; transition: all .3s; } 8. There are two faces on each card. The face will be rotated later and we will define the transition properties to animate the style changes. We also want to make sure the back face is hidden: .face { border-radius: 10px; width: 100%; height: 100%; position: absolute; -webkit-transition-property: opacity, transform, box-shadow; -webkit-transition-duration: .3s; -webkit-backface-visibility: hidden; } [ 73 ] Building a Memory Matching Game in CSS3 9. Then we set the front and back face styles. They are almost the same as the flipping card example, except that we are now giving them background images and box shadows: .front { background: #999 url(../images/deck.png) 0 -480px; z-index: 10; } .back { background: #efefef url(../images/deck.png); -webkit-transform: rotate3d(0,1,0,-180deg); z-index: 8; } .card:hover .face, .card-flipped .face { -webkit-box-shadow: 0 0 10px #aaa; } .card-flipped .front { -webkit-transform: rotate3d(0,1,0,180deg); z-index: 8; } .card-flipped .back { -webkit-transform: rotate3d(0,1,0,0deg); z-index: 10; } 10. When any card is removed, we want to fade it out. Therefore, we declare a card-removed class with 0 opacity: .card-removed { opacity: 0; } 11. In order to show different playing card graphics from the sprite sheet of the card deck, we clip the background of the card into different background positions: .cardAQ .cardAK .cardBQ .cardBK .cardCQ .cardCK .cardDQ .cardDK 12. {background-position: {background-position: {background-position: {background-position: {background-position: {background-position: {background-position: {background-position: -880px -960px -880px -960px -880px -960px -880px -960px 0;} 0;} -120px;} -120px;} -240px;} -240px;} -360px;} -360px;} We have defined a lot of CSS styles. It is now time for the JavaScript logic. Open the html5games.matchgame.js file and put the following code inside: $(function(){ // clone 12 copies of the card for(var i=0;i<11;i++){ [ 74 ] Chapter 3 $(".card:first-child").clone().appendTo("#cards"); } // initialize each card's position $("#cards").children().each(function(index) { // align the cards to be 4x3 ourselves. $(this).css({ "left" : ($(this).width() + 20) * (index % 4), "top" : ($(this).height() + 20) * Math.floor(index / 4) }); }); }); 13. Now save all files and preview the game in the browser. The game should be well styled and 12 cards should appear in the center. However, we cannot click on the cards yet because we have not set any interaction logic to the cards. [ 75 ] Building a Memory Matching Game in CSS3 What just happened? We created the game structure in HTML and applied styles to the HTML elements. We also used jQuery to create 12 cards on the game area once the web was loaded and ready. The styles of flipping and removing of the cards are also prepared and can be applied to the card by using the game logic later. Since we are using absolute positioning for each card, we need to align the cards into 4x3 tiles ourselves. In the JavaScript logic, we loop through each card and align it by calculating the position with the looping index: $("#cards").children().each(function(index) { // align the cards to be 4x3 ourselves. $(this).css({ "left" : ($(this).width() + 20) * (index % 4), "top" : ($(this).height() + 20) * Math.floor(index / 4) }); }); The "%" in JavaScript is the modulus operator that returns the remainder left after division. The remainder is used to get the column count when looping the cards. The following diagram shows the row/column relationship with the index number: The division, on the other hand, is used to get the row count so we can position the card on that corresponding row. Take index 3 as an example, 3 % 4 is 3. So the card at index 3 is on the third column. And 3 / 4 is 0, so it is on the first row. Let's pick another number to see how the formula works. Let's see index 8. 8 % 4 is 0 and it is on the first column. 8 / 4 is 2 so it is on the third row. [ 76 ] Chapter 3 Cloning DOM elements with jQuery In our HTML structure, we only have one card and in the result, we have 12 cards there. It is because we used the clone function in jQuery to clone the card element. After cloning the target element, we called the appendTo function to append the cloned card element as a child in the cards element: $(".card:first-child").clone().appendTo("#cards"); Selecting the first child of an element in jQuery by using child filters When we selected the card element and cloned it, we used the following selector: $(".card:first-child") The :first-child is a child filter that selects the first child of the given parent element. Besides :first-child, we can also select the last child by using :last-child. You can also check other child-related selectors on the jQuery document: http://api.jquery.com/category/selectors/child-filterselectors/ Vertically aligning a DOM element We put the cards DIV in the center of the game element. CSS3 flexible box layout module introduces an easy method to achieve the vertical center alignment. As this module is still in progress, we need to apply a browser vendor prefix. We will use Webkit as an example here: display: -webkit-box; -webkit-box-pack: center; -webkit-box-align: center; The flexible box module defines the alignment of the element when there are extra spaces in their container. We can set the element to behaviors as a flexible box container by using the display, a CSS2 property, with the value box, a new CSS3 property value. box-pack and box-align are two properties for defining how it aligns and uses the extra free space horizontally and vertically. We can center the element by setting both properties to center. [ 77 ] Building a Memory Matching Game in CSS3 Vertical alignment is just a small part of the flexible box layout module. It is very powerful when making layout in web design. You may find further information on the W3C page of the module (http://www.w3.org/TR/css3-flexbox/) or the CSS3 Info website (http://www.css3.info/introducing-the-flexible-box-layout-module/). Using CSS sprite with a background position The CSS sprite sheet is a big image that contains many individual graphics. The big sprite sheet image is applied as background image for the elements. We can clip each graphic out by moving the background position on a fixed width and height element. Our deck image contains a total of 53 graphics. In order to demonstrate the background position easily, let's assume we have an image that contains three card images, such as the following screenshot: In the CSS style, we set the card element to 80px width and 120px height, with the background image set to the big deck image. If we want the top left graphic, we apply both the X and Y of the background position to 0. If we want the second graphic, we move the background image to left 80px. That means setting the X position to -80px and Y to 0. Since we have a fixed width and height, only the clipped 80x120 area shows the background image. The rectangle in the following screenshot shows the viewable area: [ 78 ] Chapter 3 Adding game logic to the matching game Let's now imagine holding a real deck in our hand and setting up the matching game. We first shuffle the cards in our hand and then we put each card on the table with the back facing up. For easier game play, we align the cards into a 4x3 array. Now the game is set up. Now we are going to play the game. We pick up one card and flip it to make it face up. We pick another one and face it upwards. Afterwards, we have two possible actions. We take away those two cards if they are in the same pattern. Otherwise, we put it back facing down again, as if we have not touched them. The game continues until we pair all cards and take them all. The code flow will be much more clear after we have the step-by-step scenario in our mind. Actually, the code in this example is exactly the same as the procedure we play with a real deck. We just need to replace the human language into the JavaScript code. [ 79 ] Building a Memory Matching Game in CSS3 Time for action – Adding game logic to the matching game We have prepared the game environment in the last example and decided the game logic to be the same as playing a real deck. It is time to code the JavaScript logic now: 1. Let's begin from our last matching game example. We have styled the CSS and now it is time to add the game logic in the html5games.matchgame.js file. 2. The game is to match pairs of playing cards. We have 12 cards now so we need six pairs of playing cards. The following global array declares six pairs of card patterns: var matchingGame = {}; matchingGame.deck = [ 'cardAK', 'cardAK', 'cardAQ', 'cardAQ', 'cardAJ', 'cardAJ', 'cardBK', 'cardBK', 'cardBQ', 'cardBQ', 'cardBJ', 'cardBJ', ]; 3. We aligned the cards in the jQuery ready function in the previous chapter. Now we need to prepare and initialize more codes in the ready function. Change the ready function to the following code. The changed code is highlighted: $(function(){ matchingGame.deck.sort(shuffle); for(var i=0;i<11;i++){ $(".card:first-child").clone().appendTo("#cards"); } $("#cards").children().each(function(index) { $(this).css({ "left" : ($(this).width() + 20) * (index % 4), "top" : ($(this).height() + 20) * Math.floor(index / 4) }); // get a pattern from the shuffled deck var pattern = matchingGame.deck.pop(); // visually apply the pattern on the card's back side. $(this).find(".back").addClass(pattern); // embed the pattern data into the DOM element. $(this).attr("data-pattern",pattern); // listen the click event on each card DIV element. [ 80 ] Chapter 3 $(this).click(selectCard); }); }); 4. Similar to playing a real deck, the first thing we want to do is shuffle the deck. Add the following shuffle function to the JavaScript file: function shuffle() { return 0.5 - Math.random(); } 5. When we click on the card, we flip it and schedule the checking function. Append the following codes to the JavaScript file: function selectCard() { // we do nothing if there are already two card flipped. if ($(".card-flipped").size() > 1) { return; } $(this).addClass("card-flipped"); // check the pattern of both flipped card 0.7s later. if ($(".card-flipped").size() == 2) { setTimeout(checkPattern,700); } } 6. When two cards are opened, the following function executes. It controls whether we remove the card or flip the card back: function checkPattern() { if (isMatchPattern()) { $(".card-flipped").removeClass("card-flipped").addClass ("card-removed"); $(".card-removed").bind("webkitTransitionEnd", removeTookCards); } else { $(".card-flipped").removeClass("card-flipped"); } } 7. It is time for the pattern checking function. The following function accesses the custom pattern attribute of the opened cards and compares whether they are in the same pattern: function isMatchPattern() { var cards = $(".card-flipped"); var pattern = $(cards[0]).data("pattern"); var anotherPattern = $(cards[1]).data("pattern"); [ 81 ] Building a Memory Matching Game in CSS3 return (pattern == anotherPattern); } 8. After the matched cards fade out, we execute the following function to remove the cards: function removeTookCards() { $(".card-removed").remove(); } 9. The game logic is ready now. Let's open the game HTML in a browser and play. Remember to check the console window in Developer Tools if there is any error. [ 82 ] Chapter 3 What just happened? We coded the game logic of the CSS3 matching game. The logic adds the mouse click interaction to the playing cards and it controls the flow of the pattern checking. Executing code after CSS transition ended We remove the pair cards after playing the fade out transition. We can schedule a function to be executed after the transition is ended by using the TransitionEnd event. The following code snippet from our code example adds a card-removed class to the pair card to start the transition. Then, it binds the TransitionEnd event to remove the card complete in DOM afterwards. Also, please note the webkit vendor prefix for the event because it is not yet finalized: $(".card-flipped").removeClass("card-flipped").addClass("cardremoved"); $(".card-removed").bind("webkitTransitionEnd", removeTookCards); Delaying code execution on flipping cards The game logic flow is designed in the same way as playing a real deck. One big difference is that we used several setTimeout functions to delay the execution of the code. When the second card is clicked, we schedule the checkPattern function to be executed 0.7 seconds later in the following code example snippet: if ($(".card-flipped").size() == 2) { setTimeout(checkPattern,700); } The reason we delay the function call is to give time to the player to memorize the card pattern. That's why we delayed it by 0.7 seconds before checking the card patterns. Randomizing an array in JavaScript There is no built-in array randomize function in JavaScript. We have to write our own. Luckily, we can get help from the built-in array sorting function. Here is the usage of the sort function: sort(compare_function); The sort function takes one optional argument. [ 83 ] Building a Memory Matching Game in CSS3 Argument compare_function Definition Discussion A function that defines the sort order of the array. The compare_function requires two arguments The sort function compares two elements in the array by using the compare function. Therefore, the compare function requires two arguments. When the compare function returns any value that is bigger than 0, it puts the first argument at the lower index than the second argument. When the return value is smaller than 0, it puts the second argument at a lower index than the first argument. The trick here is that we used the compare function that returns a random number between -0.5 and 0.5: anArray.sort(shuffle); function shuffle(a, b) { return 0.5 - Math.random(); } By returning a random number in the compare function, the sort function sorts the same array in an inconsistent way. In another words, we are shuffling the array. The following link from the Mozilla Developer Network provides a detailed explanation on using the sort function with example: https://developer.mozilla.org/en/JavaScript/Reference/ Global_Objects/Array/sort Storing internal custom data with an HTML5 custom data attribute We can store custom data inside the DOM element by using the custom data attribute. We can create a custom attribute name with data- prefix and assign a value to it. For instance, we can embed custom data to the list elements in the following code: [ 84 ] Chapter 3 This is a new feature proposed in the HTML5 spec. According to the W3C, the custom data attributes are intended to store custom data private to the page or application, for which there are no more appropriate attributes or elements. W3C also stated that this custom data attribute is "intended for use by the site's own script and not a generic extension mechanism for publicly-usable metadata." We are coding our matching game and embedding our own data to the card elements, therefore, custom data attribute fits our usage. We used the custom attribute to store the card pattern inside each card so we can check whether the two flipped cards match in JavaScript by comparing the pattern value. Also, the pattern is used to style the playing cards into corresponding graphics as well: $(this).find(".back").addClass(pattern); $(this).attr("data-pattern",pattern); Pop quiz 1. According to W3C's guideline about the custom data attribute, which of the following statements is true? a. We may create a data-href attribute to store the link of the a tag. b. We may want to access the custom data attribute in a third party game portal website. c. We may want to store a data-score attribute in each player's DOM element to sort the ranking in our web page. d. We may create a ranking attribute in each player's DOM element to store the ranking data. Accessing custom data attribute with jQuery In the matching game example, we used the attr function from the jQuery library to access our custom data: pattern = $(this).attr("data-pattern"); The attr function returns the value of the given attribute name. For example, we can get the links in all a tags by calling the following code: $("a").attr("href"); For the HTML5 custom data attribute, jQuery provides us with another function to access the HTML5 custom data attribute. It is the data function. [ 85 ] Building a Memory Matching Game in CSS3 Data function was designed to embed custom data into the jQuery object of the HTML elements. It was designed before the HTML5 custom data attribute. Here is the usage of the data function: .data(key) .data(key,value) The data function accepts two types of functions: Function type .data(key) Arguments definition Discussion key is a string naming the entry of the data When there is only the key given, the data function reads the data associated with the jQuery object and returns the corresponding value. In the recent jQuery update, this function is extended to support the HTML5 custom data attribute. .data(key, value) key is a a string naming the entry of the data value is the data to be associated to the jQuery object When both key and value arguments are given, the data function sets a new data entry to the jQuery object. The value can be any JavaScript type, including array and object. In order to support the HTML5 custom data attribute, jQuery extends the data function to let it access the custom data defined in the HTML code. The following code explains how we use the data function. Given the following HTML code:
We can access the data-custom-name attribute by calling the data function in jQuery: $("#target").data("customName") It will return "HTML5 Games". [ 86 ] Chapter 3 Pop quiz 1. Given the following HTML code:
which two of these jQuery statements reads the custom score data and returns 100? a. $("#game").attr("data-score"); b. $("#game").attr("score"); c. $("#game").data("data-score"); d. $("#game").data("score"); Have a go hero We have created the CSS3 matching game. What is missing here? The game logic does not check whether the game is over. Try adding a You won text when the game is over. You can also animate the text by using the techniques we discussed in this chapter. Making other playing card games This CSS3 playing card approach is suitable for creating card games. There are two sides in a card that fit the flipping. The transition is suitable for moving the cards. With both moving and flipping, we can just define the playing rule and make the most of the card games. Have a go hero Can you use the playing card graphics and flipping techniques to create another game? How about poker? Embedding web fonts into our game Over the years, we have been using limited fonts to design web pages. We could not use whatever fonts we wanted because the browser loaded the font from the visitor's local machine. We cannot control and ensure that visitors have our desired fonts. Although we can embed web fonts back to Internet Explorer 5 with limited type format, we have to wait until browser vendors support embedding the most common TrueType font format. Imagine that we can control the mood of the game by embedding different styles of web fonts. We can design the games with our desired fonts and have more control over the appeal of game. Let's try embedding a web font to our matching memory game. [ 87 ] Building a Memory Matching Game in CSS3 Time for action – Embedding a font from Google Font Directory Google Font Directory is a web font service that lists free-to-use web fonts. We will embed a web font chosen from the Google Font Directory: 1. 2. Go to the Google Font Directory site: http://code.google.com/webfonts. 3. Choose one of them and click on the font name to proceed to the next step. In this example, I used Droid Serif. 4. After clicking on a font, the font directory displays detailed information about that font. There are several actions we can carry out there, such as preview the fonts, choose from variants, and most importantly get the font embedding code. 5. Click on the Get the code tab and you will see the following screenshot. It shows a guide on how to embed this font to our web page: In the font directory, there is a list of web fonts that is under an open source license and can be used freely. [ 88 ] Chapter 3 6. Copy the link tag provided by Google and paste it into the HTML code. It should be placed before any other style definition: 7. Now we can use the font to style our text. Set the body's font family property to the following code: body { font-family: 'Droid Serif', arial, serif; } 8. Save all the files and open the index.html file. The browser will download the font from the Google server and embed it into the web page. Keep an eye on the fonts, they should be loaded and rendered as our selected Google font. What just happened? We have just styled our game with a non-common web font. The font is hosted and delivered through the Google Font Directory. [ 89 ] Building a Memory Matching Game in CSS3 Besides using the font directory, we can embed our font file by using the @ font face. The following link provides a bulletproof approach to embed a font ourselves: http://www.fontspring.com/blog/the-new-bulletprooffont-face-syntax Check the font license before embedding Normally the font licenses do not cover the usage on web pages. Be sure to check the license before embedding the font. All the fonts listed in the Google Font Directory are licensed under open source license and can be used on any website. Choosing different font delivery services Google Font Directory is just one of those font delivery services. Typekit (http://typekit. com) and Fontdeck (http://fontdeck.com) are two other font services providing hundreds of high quality fonts via yearly subscription plans. [ 90 ] Chapter 3 Summary In this chapter we learned about using different CSS3 new properties to create games. Specifically, we covered:  Transforming and animating the game object by transition module  Flipping a card back and forth with perspective depth illusion  Creating a matching memory game based on CSS3 styles and animation and game logic by jQuery  Choosing and embedding web fonts from an online font delivery service Now that we've learned about creating DOM-based HTML5 games with the help of CSS3 features, we are going to explore another approach of creating HTML5 games in the next chapter, which is using the new Canvas tag and the drawing API. [ 91 ] 4 Building the Untangle Game with Canvas and Drawing API One new highlighted feature in HTML5 is the Canvas element. We can treat the canvas element as a dynamic area that we can draw graphics and shapes on with scripts. Images in websites have been static for years. There is animation gif but it cannot interact with its visitors. Canvas is dynamic. We draw and modify the context in canvas dynamically through JavaScript drawing API. We can also add interaction to the canvas and thus make games. In the past two chapters, we have discussed DOM-based game development with CSS3 and few HTML5 features. In the coming two chapters, we will focus on using new HTML5 features to create games. In this chapter, we will take a look at a core feature, canvas, and some basic drawing techniques. In this chapter, we shall cover the following topics:  Introducing the HTML5 canvas element  Drawing a circle in canvas  Drawing lines in the canvas element  Interacting with drawn objects in canvas with mouse events  Detecting line intersection  Building the Untangle puzzle game with canvas Building the Untangle Game with Canvas and Drawing API The Untangle puzzle game is a game where players are given circles with some lines connecting them. The lines may intersect the others and the players need to drag the circles so that no line intersects anymore. The following screenshot previews the game that we are going to achieve through this chapter: So let's start making our canvas game from scratch. Introducing the HTML5 Canvas Element W3C community states that the canvas element and the drawing functions are: A resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, or other visual images on the fly. The canvas element contains context for drawing and the actual graphics and shapes are drawn by the JavaScript drawing API. [ 94 ] Chapter 4 Drawing a circle in canvas Let's start our drawing on canvas from the basic shape—circle. Time for action – Drawing color circles on canvas 1. First, let's set up the new environment for the example. That is an HTML file that will contain the canvas element, a jQuery library to help us on JavaScript, a JavaScript file containing the actually drawing logic, and a style sheet. 2. Put the following HTML code into the index.html. It is a basic HTML document containing the canvas element: Drawing Circles in Canvas

Drawing in Canvas

Sorry, your web browser does not support Canvas content. [ 95 ] Building the Untangle Game with Canvas and Drawing API 3. Use CSS to set the background color of the canvas inside untangle.css: canvas { background: #333; } 4. In the html5games.untangle.js JavaScript file, we put a jQuery ready function and draw a color circle inside it: $(function(){ var canvas = document.getElementById("game"); var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgba(200, 200, 100, .6)"; ctx.beginPath(); ctx.arc(100, 100, 50 , 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); }); 5. Open the index.html file in a web browser and we will get the following screenshot: [ 96 ] Chapter 4 What just happened? We have just created a simple canvas context with circles on it. There are not many settings for the canvas element itself. We set the width and height of the canvas, same as we have a fixed the dimensions of a real drawing paper. Also, we assign an ID attribute to the canvas for easier reference again in JavaScript: Sorry, your web browser does not support Canvas content. Putting fallback content when the web browser does not support canvas Not every web browser supports the canvas element. Especially, those aged old version ones. The Canvas element provides an easy way to provide fallback content if the canvas element is not supported. Anything inside the canvas open and close tag is the fallback content. This content is hidden if the web browser supports the element. Browsers that don't support canvas will instead display that fallback content. It is good practice to provide useful information in the fallback content. For instance, if the canvas purpose is a dynamic picture, we may consider placing a alternative there. Or we may also provide some links to modern web browsers for the visitor to upgrade their browser easily. In this example, we provided a sentence inside the canvas element. This sentence is hidden from any browsers that support the canvas element. It will show to the visitor if their browsers do not support the new HTML5 canvas feature. The following screenshot shows the old version of Internet Explorer displaying the fallback content instead of drawing the canvas element: [ 97 ] Building the Untangle Game with Canvas and Drawing API Drawing circles and shapes with canvas arc function There is no circle function to draw a circle. Canvas drawing API provides a function to draw different arcs, including the circle. The Arc function accepts following arguments Arguments Discussion X The center point of the arc in x axis. Y The center point of the arc in y axis. radius The radius is the distance between the center point and the arc perimeter. When drawing a circle, a larger radius means a larger circle. startAngle The starting point is an angle in radian. It defines where to start drawing the arc on the perimeter. endAngle The ending point is an angle in radian. The arc is drawn from the position of the starting angle to this end angle. counterclockwise This is a Boolean indicating the arc from startingAngle to endingAngle drawn in a clockwise or counter-clockwise direction. This is an optional argument with the default value false. Converting degree to radians The angle arguments used in the arc function are in radian instead of degree. If you are familiar with the degrees angle, you may need to convert the degree into radians before putting the value into the arc function. We can convert the angle unit by using the following formula: radians = π/180 x degrees The following graph contains some common angle values in both degree and radian units. The graph also indicates the position of the angle value for us to easily pick the starting angle and ending angle argument when drawing arc in canvas. [ 98 ] Chapter 4 In order to be clearer on drawing different arcs with the starting angle and ending angle, let's draw some arcs. Time for action – Drawing different arcs with arc function Let's do some experiments on using the arc function by giving different starting and ending angles: 1. Open the html5games.untangle.js file we just used to draw the circle. 2. Replace the circle drawing code by using the following arcs drawing codes: $(function(){ var canvas = document.getElementById('game'); var ctx = canvas.getContext('2d'); ctx.fillStyle = "rgba(200, 200, 100, .6)"; // draw bottom half circle ctx.beginPath(); ctx.arc(100, 110, 50 , 0, Math.PI); ctx.closePath(); ctx.fill(); // draw top half circle ctx.beginPath(); [ 99 ] Building the Untangle Game with Canvas and Drawing API ctx.arc(100, 90, 50 , 0, Math.PI, true); ctx.closePath(); ctx.fill(); // draw left half circle ctx.beginPath(); ctx.arc(230, 100, 50 , Math.PI/2, Math.PI*3/2); ctx.closePath(); ctx.fill(); // draw right half circle ctx.beginPath(); ctx.arc(250, 100, 50 , Math.PI*3/2, Math.PI/2); ctx.closePath(); ctx.fill(); // draw a shape that is almost a circle ctx.beginPath(); ctx.arc(180, 240, 50 , Math.PI*7/6, Math.PI*2/3); ctx.closePath(); ctx.fill(); // draw a small arc ctx.beginPath(); ctx.arc(150, 250, 50 , Math.PI*7/6, Math.PI*2/3, true); ctx.closePath(); ctx.fill(); }); 3. It is time to test it in a web browser. There should be six different half circles and arcs on the canvas as shown in the following screenshot: [ 100 ] Chapter 4 What just happened? We have used different startAngle and endAngle arguments in the arc function to draw six different arc shapes. These arc shapes demonstrate how the arc function works. Let's recall the degrees and radians relationship circle and take a look at the top half circle. The top half circle begins at angle 0 and ends at angle π, and the arc is drawn in an counter-clockwise direction. If we take a look at the circle, it looks like the following graph: And if we start at angle 210 degrees and end at angle 120 degrees, in a clockwise direction, we will get the following arc: [ 101 ] Building the Untangle Game with Canvas and Drawing API Pop quiz 1. Which arc command we can use to draw the following arc? a. ctx.arc(300, 250, 50 , Math.PI*3/2, Math.PI/2, true); b. ctx.arc(300, 250, 50 , Math.PI*3/2, Math.PI/2); c. ctx.arc(300, 250, 50 , Math.PI*3/2, 0, true); d. ctx.arc(300, 250, 50 , Math.PI*3/2, 0); Executing the path drawing in canvas When we are calling the arc function or other path drawing functions, we are not drawing the path immediately on the canvas. Instead, we are adding it into a list of the paths. These paths will not be drawn until we execute the drawing command. There are two drawing executing commands. One command for filling the paths and the other for drawing the stroke. We fill the paths by calling the fill function and draw the stroke of the paths by calling the stroke function, which we will use later when drawing lines: ctx.fill(); Beginning a path for each style The fill and stroke function fills and draws the paths on canvas but it does not clear the list of paths. Take the following code snippet as an example. After filling our circle with red color, we add other circles and fill it with green. What happens to the code is both the circles are filled with green color, instead of only the new circle being filled by green color: [ 102 ] Chapter 4 var canvas = document.getElementById('game'); var ctx = canvas.getContext('2d'); ctx.fillStyle = "red"; ctx.arc(100, 100, 50 , 0, Math.PI*2, true); ctx.fill(); ctx.arc(210, 100, 50, 0, Math.PI*2, true); ctx.fillStyle = "green"; ctx.fill(); It is because when calling the second fill command, the list of paths in the canvas contain both circles. Therefore, the fill command fills both circles with green and overrides the red color circle. In order to fix this issue, we want to ensure we call beginPath before drawing a new shape every time. beginPath empties the list of paths so next time we call the fill and stroke command, it will only apply to all paths after the last beginPath. Have a go hero We have just discussed a code snippet where we intend to draw two circles with one in red color and the other in green. The code turns out drawing both circles in green color. How can we add a beginPath command to the code so that it draws one red circle and one green circle correctly? Closing a path The closePath function will draw a straight line from the last point of the latest path to the first point of the path. That is closing the path. If we are only going to fill the path and not going to draw the stroke outline, the closePath function does not affect the result. The following screenshot compares the result on a half circle with one calling closePath and the other not calling closePath: [ 103 ] Building the Untangle Game with Canvas and Drawing API Pop quiz 1. Do we need to use the closePath function on the shape we are drawing if we just want to fill the color and not draw the outline stroke? a. Yes, we need the closePath function. b. No, it does not care if we have the closePath function. Wrapping the circle drawing in function Drawing a circle is a common function that we will use a lot. It is better to create a function for drawing a circle instead of entering several code lines now. Time for action – Putting the circle drawing code into a function Let's make a function for the circle drawing and draw some circles on the canvas: 1. Open the html5games.untangle.js file. 2. Replace the original code in the JavaScript file with the following code. It basically puts the circle drawing code we just used into a function and uses a for-loop to randomly place five circles on the canvas: var untangleGame = {}; function drawCircle(ctx, x, y, radius) { ctx.fillStyle = "rgba(200, 200, 100, .9)"; ctx.beginPath(); ctx.arc(x, y, radius, 0, Math.PI*2, true); ctx.closePath(); ctx.fill(); } $(function(){ var canvas = document.getElementById('game'); var ctx = canvas.getContext('2d'); var circleRadius = 10; var width = canvas.width; var height = canvas.height; // random 5 circles var circlesCount = 5; for (var i=0;i 0.495) (Math.random() > 0.495) means there is 50 percent false and 50 percent true. We can further adjust the true/false ratio. (Math.random() > 0.7) means there is almost 70 percent false and 30 percent true. Saving the circle position When we are developing a DOM-based game, such as the games we built in previous chapters, we often put the game objects into DIV elements and access them later in code logic. It is a different story in canvas-based game development. In order to access our game objects after they are drawn on the canvas, we need to remember their states ourselves. Lets say now we want to know how many circles are drawn and where they are, and we will need an array to store their position. [ 106 ] Chapter 4 Time for action – Saving the circle position 1. Open the html5games.untangle.js file in the text editor. 2. Add the following circle object definition code at the top of the JavaScript file: function Circle(x,y,radius){ this.x = x; this.y = y; this.radius = radius; } 3. Now we need an array to store the circles position. Add a new array to the untangleGame object: var untangleGame = { circles: [] }; 4. After drawing every circle on the canvas, we save the position of the circle into the circles array. Add the highlighted line after calling the drawCircle function: $(function(){ var canvas = document.getElementById('game'); var ctx = canvas.getContext('2d'); var circleRadius = 10; var width = canvas.width; var height = canvas.height; // random 5 circles var circlesCount = 5; for (var i=0;i

Untangle Puzzle Game in Canvas

3. We also need to display the current level and the progress to the player. Add the following code after the canvas element:

Puzzle 0, Completeness: 0%

4. Open the html5games.untangle.js JavaScript file to add the game logic. 5. Add the variable info, the untangleGame. It stores the current level of the game: var untangleGame = { circles: [], thinLineThickness: 1, boldLineThickness: 5, lines: [], currentLevel: 0 }; 6. We need some pre-defined level data for the players to play. It is a collection of data defining where the circles are placed and how they connect to each other initially. Add the following level data code to the untangleGame object: untangleGame.levels = [ { "level" : 0, "circles" : [{"x" : 400, "y" : 156}, {"x" : 381, "y" : 241}, {"x" : 84, "y" : 233}, {"x" : 88, "y" : 73}], "relationship" : { "0" : {"connectedPoints" : "1" : {"connectedPoints" : "2" : {"connectedPoints" : "3" : {"connectedPoints" : [ 125 ] [1,2]}, [0,3]}, [0,3]}, [1,2]} Building the Untangle Game with Canvas and Drawing API } }, { "level" : 1, "circles" : [{"x" : 401, "y" : 73}, {"x" : 400, "y" : 240}, {"x" : 88, "y" : 241}, {"x" : 84, "y" : 72}], "relationship" : { "0" : {"connectedPoints" : "1" : {"connectedPoints" : "2" : {"connectedPoints" : "3" : {"connectedPoints" : } [1,2,3]}, [0,2,3]}, [0,1,3]}, [0,1,2]} }, { "level" : 2, "circles" : [{"x" : 92, "y" : 85}, {"x" : 253, "y" : 13}, {"x" : 393, "y" : 86}, {"x" : 390, "y" : 214}, {"x" : 248, "y" : 275}, {"x" : 95, "y" : 216}], "relationship" : { "0" : {"connectedPoints" "1" : {"connectedPoints" "2" : {"connectedPoints" "3" : {"connectedPoints" "4" : {"connectedPoints" "5" : {"connectedPoints" } : : : : : : [2,3,4]}, [3,5]}, [0,4,5]}, [0,1,5]}, [0,2]}, [1,2,3]} } ]; 7. When starting on each level, we need to set up the initial level data. To help make the code more readable, we create a function. Add the following code to the end of the JavaScript file: function setupCurrentLevel() { untangleGame.circles = []; var level = untangleGame.levels[untangleGame.currentLevel]; for (var i=0; iPuzzle 0, Completeness: 0%

We use the jQuery HTML function that we discussed in Chapter 2, Getting Started with DOMbased Game development, to update the completeness progress: $("#progress").html(progressPercentage); Have a go hero We have only defined three levels in the example untangle puzzle game. It is not fun enough to play with three levels. How about adding more levels to the game? If you cannot come up a level, try searching similar untangle games on the Internet and get some inspiration on the leveling. Summary We learned a lot in this chapter about drawing shapes and creating interaction with the new HTML5 canvas element and the drawing API. Specifically, we covered:  Drawing different paths and shapes in canvas, including circles, arcs, and lines.  Adding mouse events and interaction with the drawn paths in the canvas.  Dragging drawn paths in the canvas.  Checking line intersection with the help of mathematics formulas.  Creating an untangle puzzle game in which players need to drag the circles so the connecting lines are not intersected by each other. Now that we've learned about basic drawing functions in the canvas and drawing API, use them to create a puzzle solving game in canvas. We're ready to learn some advanced drawing techniques in canvas. In the next chapter, we will enhance our untangle puzzle game with more canvas drawing APIs, such as drawing text, drawing images, and drawing gradients. [ 131 ] 5 Building a Canvas Games Masterclass In the previous chapter, we explored some basic canvas context drawing APIs and created a game named Untangle. In this chapter, we are going to enhance the game by using some other context drawing APIs. In this chapter we shall:      Fill our game objects with gradient color Fill text in the canvas with custom webfont Draw images in Canvas Animate a sprite sheet image And build multiple canvas layers The following screenshot is a preview to the final result that we are going to build through this chapter. It is a canvas-based Untangle game with an animated game guideline and several subtle details: Building a Canvas Games Masterclass So let's get on with it... Filling shapes with gradient color We covered filling solid color in the last chapter. Canvas can do far more when filling shapes. We can fill the shape with both linear and radial gradient. Time for action – Drawing a gradient color background to the Untangle game Let's improve the black solid background we have now. How about drawing a gradient from top to bottom? 1. We will use the Untangle game we created in the last chapter as a starting point. Open the html5games.untangle.js JavaScript file in the text editor. 2. Add the following code in the gameloop function after clearing the canvas to draw the gradient background: var bg_gradient = ctx.createLinearGradient(0,0,0,ctx.canvas. height); bg_gradient.addColorStop(0, "#000000"); bg_gradient.addColorStop(1, "#555555"); ctx.fillStyle = bg_gradient; ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height); 3. Save the files and preview the index.html in the browser. The background should be a linear gradient with black on top which gradually becomes grey at the bottom. [ 134 ] Chapter 5 What just happened? We just filled a rectangle with a linear gradient color. To fill linear gradient color, all we need to do is set the starting point and ending point of the gradient. Then we add several color stops between them. Here is how we use the linear gradient function: createLinearGradient(x1, y1, x2, y2); Argument Definition x1 The starting point of the gradient. y1 x2 The ending point of the gradient. y2 Adding color stops in the gradient color It is not enough to just have the starting and ending point. We also need to define what color we use and how it is applied to the gradient. It is called a color stop in gradient. We can add a color stop to the gradient by using the following gradient function: addColorStop(position, color); Argument Definition Discussion position A floating number between 0 and 1. Position 0 means the color stops at the starting point and 1 means it stops at the ending point. Any number between 0 and 1 means it stops in between the starting and ending point. For example, 0.5 means a half and 0.33 means 30 percent away from the starting point. color The color style of that color stop. [ 135 ] The color style shares the same syntax from the CSS color styling. We may use the HEX expression, such as #FFDDAA. Or other color styles such as RGBA color name. Building a Canvas Games Masterclass The follow screenshot shows a side-by-side comparison between a linear gradient setting and the result drawing. The starting point and ending point defines the scope and the angle of the gradient. The color stops define how the color mixes between the gradient scopes: Adding color stop with opacity We can set an opacity value to the color stop by using the RGBA function. The following code tells the gradient to start by using red color with half opacity: gradient.addColorStop(0, "rgba(255, 0, 0, 0.5)"); Filling radial gradient color There are two types of gradients in the Canvas drawing API. The one we just used is called linear gradient. The other one is radial gradient. The radial gradient fills the gradient from one circle to another circle. Time for action – Filling the circles with radial gradient color Imagine that we now fill our dragging circles to radial gradient. We will change the solid yellow circles to white-yellow gradient: 1. Open the html5game.untangle.js JavaScript file. We are going to modify the code we used to draw the circle in the game. 2. After we draw the circle path with the arc function and before we fill it we replace the original solid color style setting to the following radial gradient color: [ 136 ] Chapter 5 function drawCircle(ctx, x, y) { // prepare the radial gradients fill style var circle_gradient = ctx.createRadialGradient(x-3,y3,1,x,y,untangleGame.circleRadius); circle_gradient.addColorStop(0, "#fff"); circle_gradient.addColorStop(1, "#cc0"); ctx.fillStyle = circle_gradient; // draw the path ctx.beginPath(); ctx.arc(x, y, untangleGame.circleRadius, 0, Math.PI*2, true); ctx.closePath(); // actually fill the circle path ctx.fill(); } 3. Save the modified file and preview the index.html in a web browser. The circles are now filled with radial gradient color. In the following screenshot I've scaled up the drawing to 200 percent to better demonstrate the radial gradient in the circle: [ 137 ] Building a Canvas Games Masterclass What just happened? We just made the dragging circles look more realistic by filling a radial gradient. Here is how we create a radial gradient: createRadialGradient(x1, y1, r1, x2, y2, r2); Argument Definition x1, y1 The center of the starting circle in x and y in the canvas coordinate. r1 The radius of the starting circle. x2, y2 The center of the ending circle in x and y in the canvas coordinate. r2 The radius of the ending circle. The following screenshot shows a side-by-side comparison between a radial gradient setting and the final result drawing in canvas: The radial gradient blends the color from the starting circle to the ending circle. In this gradient circle, the starting circle is a small circle in the center and the ending circle is the outermost circle. There are three color stops. A white color stops at both the starting and ending circle; another dark color stops 90 percent away from the starting circle. [ 138 ] Chapter 5 Have a go hero – Filling gradients We add color stops to the gradients to define how the colors blend. What happens if we forget to add any color stops to the gradient and fill a rectangle? What if we only define one color stop? Try experimenting with the color stop settings. In the radial gradient example, the small starting circle is inside the bigger ending circle. What happens if the starting circle is bigger than the ending one? How about if the starting circle is not inside the ending circle? That is, what happens if the two circles do not overlap? Drawing text in canvas Imagine now we want to show the progress level directly inside the canvas. Canvas provides us with methods to draw text inside canvas. Time for action – Displaying the progress level text inside the canvas element 1. We will continue using our Untangle game. Open the html5games.untangle.js JavaScript file in text editor. 2. First, let's make the level progress percentage a global variable so we can use it in different places: var untangleGame = { circles: [], thinLineThickness: 1, boldLineThickness: 5, lines: [], currentLevel: 0, progressPercentage: 0 }; 3. Add the following code after the canvas drawing code in the gameloop function: // draw the title text ctx.font = "26px Arial"; ctx.textAlign = "center"; ctx.fillStyle = "#ffffff"; ctx.fillText("Untangle Game",ctx.canvas.width/2,50); // draw the level progress text ctx.textAlign = "left"; ctx.textBaseline = "bottom"; [ 139 ] Building a Canvas Games Masterclass ctx.fillText("Puzzle "+untangleGame.currentLevel+", Completeness: " + untangleGame.progressPercentage + "%", 20,ctx.canvas.height5); 4. Save the file and preview the index.html in a web browser. We will see that the text is now drawn inside the canvas. What just happened? We have just drawn the title and the level progress text in our canvas-based game. We draw text in canvas by using the fillText function. The following table shows how we use the function: fillText(string, x, y); Argument Definition string The text that we are going to draw. x The x coordinate that the text draws. y The y coordinate that the text draws. This is the basic setting to draw a text. There are several more drawing context properties to set up the text drawing. [ 140 ] Chapter 5 Context properties context.font Definition Discussion The font style of the text. It shares the same syntax we used to declare font style in CSS. For example, the following code sets the font style to 20 pixels bold with Arial typeface: ctx.font = "bold 20px Arial"; context.textAlign The text alignment. The alignment defines how the text aligns. It can be one of the following values:      start end left right center For instance, if we are going to place a text on the right edge of the canvas. Using left alignment means we need to calculate text width in order to know the x coordinate of the text. When using right alignment in this case, all we need to do is set the x position directly to the canvas width. The text will then automatically be placed on the right edge of the canvas. context.textBaseline The text baseline. The following lists the common value of a textBaseline:     top middle bottom alphabet Similar to the text alignment, the bottom baseline is useful when we want to place our text at the bottom of the canvas. The y position of the fillText function is based on the bottom baseline of the text instead of the top. The alphabet baseline aligns the y position based on the lower case alphabet. The following screenshot shows our text drawing with alphabet baseline. [ 141 ] Building a Canvas Games Masterclass Please beware that the text drawing in canvas is treated as bitmap image data. That means visitors cannot select the text; search engines cannot index the text; we cannot search them. For this reason, we should think carefully whether we want to draw the text inside a canvas or just place them directly in the DOM. Pop quiz – Drawing text in canvas 1. If we are going to draw a text close to the bottom rightcorner of the canvas which alignment and baseline setting is better? a. Left alignment, bottom baseline. b. Center alignment, alphabet baseline. c. Right alignment, bottom baseline. d. Center alignment, middle baseline. 2. We are going to make a realistic book with a flipping effect with the latest open web standard. Which of the following settings is better? a. Draw the realistic book in canvas, including all the text and the flipping effect. b. Put all text and content in DOM and draw the realistic page-flipping effect in canvas. Using embedded web font inside canvas We used custom font in our memory matching game in the previous chapter. The custom font embedding also worked in the canvas. Let's conduct an experiment on drawing a custom font in our Untangle game in canvas. [ 142 ] Chapter 5 Time for action – Embedding Google Web Font into the canvas element Let's draw the canvas texts with a handwriting style font: 1. First, go to the Google Font Directory and choose a handwriting style font. I used the font Rock Salt and you can get it from the following URL: http://code.google.com/webfonts/family?family=Rock+Salt&subset= latin#code. 2. The Google font directory provides a CSS link code that we can add to our game in order to embed the font. Add the following CSS link to the head of index.html: 3. The next thing is to use the font. We open the html5games.untangle.js JavaScript file and modify the context font property to the following: ctx.font = "26px 'Rock Salt'"; 4. It is time to open our game in the web browser to test the result. The text drawn in the canvas now is using the font we choose in the Google font directory. [ 143 ] Building a Canvas Games Masterclass What just happened? We just chose a web font and embedded it into the canvas when drawing text. It shows that we can style the font family of the filled text in canvas just like other DOM elements. Sometimes the width of the text varies in different font families although they have the same word count. In this case, we can use the measureText function to get the width of the text we draw. The following link to the Mozilla Developer Network explains how we can use the function: https://developer.mozilla.org/en/Drawing_text_using_ a_canvas#measureText() Drawing images in canvas We have drawn some text inside canvas. What about drawing an image? Yes. Drawing images and image manipulation is one big feature that canvas has. Time for action – Adding graphics to the game We are going to draw a blackboard background to the game: 1. Download the graphic files from the code example bundle or the following URL. The graphics files include all graphics that we need in this chapter: http://gamedesign.cc/html5games/1260_05_example_graphics.zip 2. Put the newly downloaded graphics files into a folder named images. 3. We will load an image and loading means it may take a while until the image is loaded. Ideally, we should not start the game until all game assets are loaded. In this case, we can prepare a splash screen with loading words to let the player know the game is going to start later. Add the following code in the jQuery ready function after clearing the canvas context: // draw a splash screen when loading the game background // draw gradients background var bg_gradient = ctx.createLinearGradient(0,0,0,ctx.canvas. height); bg_gradient.addColorStop(0, "#cccccc"); bg_gradient.addColorStop(1, "#efefef"); ctx.fillStyle = bg_gradient; ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); [ 144 ] Chapter 5 // draw the loading text ctx.font = "34px 'Rock Salt'"; ctx.textAlign = "center"; ctx.fillStyle = "#333333"; ctx.fillText("loading...",ctx.canvas.width/2,canvas.height/2); 4. Then it is time to really load the image. There is a board.png in the graphics file we just downloaded. It is a blackboard graphics we will draw to the canvas as background. Add the following code after the code we just added in the previous step: // load the background image untangleGame.background = new Image(); untangleGame.background.onload = function() { // setup an interval to loop the game loop setInterval(gameloop, 30); } untangleGame.background.onerror = function() { console.log("Error loading the image."); } untangleGame.background.src = "images/board.png"; 5. In the gameloop function, we draw the image into the canvas after clearing the context and before drawing anything else. Since the image loading takes time, we also need to ensure it is loaded before drawing it: // draw the image background ctx.drawImage(untangleGame.background, 0, 0); 6. We had set up a levels array to store the level data including the initial circles position. Some circles are now overlapped with the border of the background image so we may want to alter the circles position. Update the circles array of level 2 with the following new values: "circles" : {"x" : 353, {"x" : 493, {"x" : 490, {"x" : 348, {"x" : 195, 7. [{"x" "y" : "y" : "y" : "y" : "y" : : 192, "y" : 155}, 109}, 156}, 236}, 276}, 228}], Also we need to adjust the position of the level progress text. Modify the fill text function calling as the following code with a different position value: ctx.fillText("Puzzle "+untangleGame.currentLevel+", Completeness: " + untangleGame.progressPercentage + "%", 60, ctx.canvas.height80); [ 145 ] Building a Canvas Games Masterclass 8. Next, we do not want a background color set to the canvas now because we have a PNG background with a transparent border. Open the untangle.css file and remove the background property in canvas. 9. Now save all files and open the index.html in the web browser. The background should be there and the handwritten fonts should match our blackboard theme. What just happened? We just drew an image inside the canvas element. There are two common ways to draw an image on canvas. We can either reference an existing img tag or load the image on the fly in JavaScript. Here is how we reference the existing image tag in canvas. Assuming that we have the following img tag in HTML: [ 146 ] Chapter 5 We can draw the image in canvas by using the following JavaScript code: var img = document.getElementById('board'); context.drawImage(img, x, y); Here is another code snippet to load the image without attaching the img tag into DOM. If we load the image inside JavaScript, we need to make sure the image is loaded before drawing it on canvas. Therefore, we draw the image after the onload event of the image: var board = new Image(); board.onload = function() { context.drawImage(board, x, y); } board.src = "images/board.png"; The order meters when setting the onload event handler and assigning the image src When we assign the src property to the image and if the image is cached by the browser, some browsers fire the onload event immediately. If we place the onload event handler after assigning the src property, we may miss it because it is fired before we set the event handler. In our example, we used the latter approach. We create an Image object and load the background. When the image is loaded, we start the game loop and thus start the game. Another event that we should handle when loading the image is the onerror event. It is especially useful when we are accessing extra network data. We have the following code snippet to check the error in our example: untangleGame.background.onerror = function() { console.log("Error loading the image."); } Have a go hero The error loading now only displays a message in the console. The console is normally not viewed by players. How about designing an alert dialog or some other approaches to tell players that the game failed to load the game assets? Using the drawImage function There are three behaviors to draw an image in the canvas. We can draw the image without any modification on a given coordinate, we can also draw the image with a scaling factor on a given coordinate, or we can even crop the image and draw only the clipping region. [ 147 ] Building a Canvas Games Masterclass The drawImage function accepts several arguments: drawImage(image, x, y); Argument Definition Discussion image The image reference that we are going to draw. We either get the image reference by getting an existing img element or creating a JavaScript Image object. x The x position to place the image in canvas coordinate. The x and y coordinate is where we place the image with respect to its top-left corner. y The y position to place the image in canvas coordinate. drawImage(image, x, y, width, height); Argument Definition Discussion image The image reference that we are going to draw. We either get the image reference by getting an existing img element or creating a JavaScript Image object. x The x position to place the image in canvas coordinate. The x and y coordinate is where we place the image with respect to its top-left corner. y The y position to place the image in canvas coordinate. width The width of the final drawn image. height The height of the final drawn image. We are applying scale to the image if the width and height is not the same as the original image. drawImage(image, sx, sy, sWidth, sHeight, dx, dy, width, height); Argument Definition Discussion image The image reference that we are going to draw. We either get the image reference by getting an existing img element or creating a JavaScript Image object. sx The x coordinate of the top-left corner of the clipping region. sy The y coordinate of the top-left corner of the clipping region. The clipping x, y, width, height together defines a rectangular clipping area. The given image is clipped by this rectangle. sWidth The width of the clipping region. sHeight The height of the clipping region. [ 148 ] Chapter 5 Argument Definition Discussion dx The x position to place the image in canvas coordinate. The x and y coordinate is where we place the image with respect to its top-left corner. dy The y position to place the image in canvas coordinate. width The width of the final drawn image. height The height of the final drawn image. We are applying scale to the clipped image if the width and height is not the same as the clipping dimension. Have a go hero – Optimizing the background image In the example, we draw the blackboard image as background in every call of the gameloop function. Since our background is static and does not change along the time, clearing it and redrawing it again and again is wasting CPU resources. How can we optimize this performance issue? Decorating the canvas-based game We have enhanced the canvas game with gradients and images. Before moving forward, let's decorate the web page of our canvas game. Time for action – Adding CSS styles and images decoration to the game We are going to build a center-aligned layout with a game title: 1. We embed another font from the Google font directory to style the normal body text. Add the following CSS link within the head in index.html: 2. It is easier for us to style the layout with one grouping DOM element. We put all the elements inside the body into a section with id page:
...
3. Let's apply CSS to the page layout. Replace existing content in the untangle.css file with the following code: html, body { [ 149 ] Building a Canvas Games Masterclass background: url(../images/title_bg.png) 50% 0 no-repeat, url(../ images/bg_repeat.png) 50% 0 repeat-y #889ba7; margin: 0; font-family: 'Josefin Sans', arial, serif; color: #111; } #game{ position:relative; } #page { width: 821px; min-height: 800px; margin: 0 auto; padding: 0; text-align: center; text-shadow: 0 1px 5px rgba(60,60,60,.6); } header { height: 88px; padding-top: 36px; margin-bottom: 50px; font-family: "Rock Salt", Arial, sans-serif; font-size: 14px; text-shadow: 0 1px 0 rgba(200,200,200,.5); color: #121; } 4. Now we have the header text in the ribbon. Showing the title again in canvas seems redundant. Let's remove the following line of code which draws the title: ctx.fillText("Untangle Game",ctx.canvas.width/2,50); 5. It is time to save all the files and preview it in the web browser. We should see a title ribbon and a well-styled layout that is center-aligned. The following screenshot shows the result: [ 150 ] Chapter 5 What just happened? We just decorated the web page that contains our canvas-based game. Although our game is based on canvas drawing, it does not restrict us from decorating the whole web page with graphics and CSS styles. Default background of the canvas element The default background of the canvas element is transparent. If we do not set any background CSS style of the canvas, it will be transparent. It is useful when our drawing is not a rectangle. In this example, the textured layout background shows within the canvas region. Pop quiz – Styling a canvas background 1. How can we set the canvas background to be transparent? a. Set the background color to #ffffff. b. Do nothing. It is transparent by default. [ 151 ] Building a Canvas Games Masterclass Animating a sprite sheet in canvas We first used sprite sheet images in Chapter 3, Building a Memory Matching Game in CSS3, when displaying a deck of playing cards. Time for action – Making a game guide animation There is a graphics file named guide_sprite.png in the images folder. It is a game guideline graphic that contains each step of the animation. Let's draw this guide into our game with animations: 1. Open the html5games.untangle.js JavaScript file in the text editor. 2. In the jQuery ready function add the following code: // load the guide sprite image untangleGame.guide = new Image(); untangleGame.guide.onload = function() { untangleGame.guideReady = true; // setup timer to switch the display frame of the guide sprite untangleGame.guideFrame = 0; setInterval(guideNextFrame, 500); } untangleGame.guide.src = "images/guide_sprite.png"; 3. We add the following function to move the current frame to the next frame every 500 meters: function guideNextFrame() { untangleGame.guideFrame++; // there are only 6 frames (0-5) in the guide animation. // we loop back the frame number to frame 0 after frame 5. if (untangleGame.guideFrame > 5) { untangleGame.guideFrame = 0; } } 4. In the gameloop function, we draw the guide animation according to the current frame. [ 152 ] Chapter 5 // draw the guide animation if (untangleGame.currentLevel == 0 && untangleGame.guideReady) { // the dimension of each frame is 80x130. var nextFrameX = untangleGame.guideFrame * 80; ctx.drawImage(untangleGame.guide, nextFrameX, 0, 80, 130, 325, 130, 80, 130); } 5. Let's watch the animation in the web browser by opening the index.html. The following screenshot demonstrates the animation of the game guideline. The guideline animation will play and loop until the player levels up: What just happened? We can draw only a region of an image when using the drawImage context function. The following screenshot demonstrates the process of the animation step by step. The rectangle is the clipping region. We used a variable named guideFrame to control which frame to show. The width of each frame is 80. Therefore, we get the x position of the clipping region by multiplying the width and the current frame number: var nextFrameX = untangleGame.guideFrame * 80; ctx.drawImage(untangleGame.guide, nextFrameX, 0, 80, 130, 325, 130, 80, 130); [ 153 ] Building a Canvas Games Masterclass The guideFrame variable is updated every 500 meters by the following guideNextFrame function: function guideNextFrame() { untangleGame.guideFrame++; // there are only 6 frames (0-5) in the guide animation. // we loop back the frame number to frame 0 after frame 5. if (untangleGame.guideFrame > 5) { untangleGame.guideFrame = 0; } } Animating a sprite is a commonly used technique when developing games. There are some benefits of using sprite animation when developing games in traditional video games. The reasons may not apply to the web game development but we have other benefits of using sprite sheet animation: [ 154 ] Chapter 5  All frames are loaded as one file so the whole animation is ready once the sprite file is loaded.  Putting all frames into one file means we can reduce the HTTP request from the web browser to the server. If each frame is a file, the browser requests the file many times while now it just requests one file and uses one HTTP request.  Putting different images into one file also helps reduce the duplicate file's header, footer, and meta data.  Putting all frames into one image means we can easily clip the image to display any frame without the complex code to change the image source. It is usually used in character animation. The following screenshot is a sprite animation of an angry cat that I used in an HTML5 game named Neighbours (http://gamedesign.cc/ html5games/neighbours/): We built the sprite sheet animation by clipping the frame and setting up the timer ourselves in this example. When working with a lot of animations, we may want to use some third party sprite animation plugin or create our own canvas sprite animation to better reuse and manage the logic code. [ 155 ] Building a Canvas Games Masterclass Sprite animation is an important topic in HTML5 games development and there are many online resources discussing this topic. The following links are some of them: The sprite animation tutorial (http://codeutopia.net/ blog/2009/08/21/using-canvas-to-do-bitmap-spriteanimation-in-javascript/) from CodeUtopia discusses how we can make a sprite object from scratch and use it to animate a sprite. The sprite animation demo (http://www.johnegraham2.com/webtechnology/html-5-canvas-tag-sprite-animation-demo/) by John Graham provides another sprite object to animate a sprite in canvas. The Spritely (http://www.spritely.net/), on the other hand, provides sprite animation over the DOM element with CSS. It is useful when we want to animate a sprite without using canvas. Creating a multi-layers canvas game Now all things are drawn into the context and it has no other state to distinguish the drawn items. We may split the canvas game into different layers and code the logic to control and draw each layer at a time. Time for action – Dividing the game into four layers We are going to separate our Untangle game into four layers: 1. In index.htm, we changed the canvas HTML to the following code. It contains several canvases within a section:
Sorry, your web browser does not support canvas content.
2. We also need to apply some styles to the canvas so they overlap with each other to create the multiple layers effect. Also we have to prepare a fadeout class and dim class to make the target transparent. Add the following code into the untangle. css file: #layers { [ 156 ] Chapter 5 height: 440px; position: relative; margin: 0 auto; width:768px; height: 440px; } #layers canvas{ left: 50%; margin-left: -384px; position: absolute; } #guide { opacity: .7; } #guide.fadeout { opacity: 0; -webkit-transition: opacity .5s linear; transition: opacity .5s linear; } #ui { -webkit-transition: opacity .3s linear; transition: opacity .3s linear; } #ui.dim { opacity: .3; } 3. In the html5games.untangle.js JavaScript file, we modify the code to support the layers feature. First, we add an array to store the context reference of each canvas: untangleGame.layers = new Array(); 4. Then, we get the context reference and store them in the array: // prepare layer 0 (bg) var canvas_bg = document.getElementById("bg"); untangleGame.layers[0] = canvas_bg.getContext("2d"); // prepare layer 1 (guide) var canvas_guide = document.getElementById("guide"); untangleGame.layers[1] = canvas_guide.getContext("2d"); // prepare layer 2 (game) var canvas = document.getElementById("game"); var ctx = canvas.getContext("2d"); [ 157 ] Building a Canvas Games Masterclass untangleGame.layers[2] = ctx; // prepare layer 3 (ui) var canvas_ui = document.getElementById("ui"); untangleGame.layers[3] = canvas_ui.getContext("2d"); 5. Since now the game canvas are overlapped together, the mouse event listener we had in the game canvas does not fire anymore. We can listen to the event from the parent layers DIV which has the same position and dimension of the canvas: $("#layers").mousedown(function(e) $("#layers").mousemove(function(e) $("#layers").mouseup(function(e) 6. We are going to separate the drawing part into different functions for different layers. In the following drawLayerBG function, it is only in charge of drawing the background: function drawLayerBG() { var ctx = untangleGame.layers[0]; clear(ctx); // draw the image background ctx.drawImage(untangleGame.background, 0, 0); } 7. We draw the background layer when the background image is loaded. Add the following highlighted code into the onload event of the background: untangleGame.background.onload = function() { drawLayerBG(); // setup an interval to loop the game loop setInterval(gameloop, 30); } 8. We divide the game loop into three different functions for the specified layer: function gameloop() { drawLayerGuide(); drawLayerGame(); drawLayerUI(); } [ 158 ] Chapter 5 9. We put the guideline animation into a dedicated canvas now so we can easily apply CSS style to fade out the guideline later: function drawLayerGuide() { var ctx = untangleGame.layers[1]; clear(ctx); // draw the guide animation if (untangleGame.guideReady) { // the dimension of each frame is 80x130. var nextFrameX = untangleGame.guideFrame * 80; ctx.drawImage(untangleGame.guide, nextFrameX, 0, 80, 130, 325, 130, 80, 130); } // fade out the guideline after level 0 if (untangleGame.currentLevel == 1) { $("#guide").addClass('fadeout'); } } 10. The following drawLayerGame keeps all the drawing code we used in the gameplay. Most of the code is from the original gameloop function: function drawLayerGame() { // get the reference of the canvas element and the drawing context. var ctx = untangleGame.layers[2]; // draw the game state visually // clear the canvas before drawing. clear(ctx); // draw all remembered line for(var i=0;i 310) { isOverlappedWithCircle = true; } } if (isOverlappedWithCircle) { $("#ui").addClass('dim'); } else [ 160 ] Chapter 5 { $("#ui").removeClass('dim'); } } 12. Save all the files and check our big code changes in the web browser. The game should be displayed as if we haven't changed anything. Try dragging the circle down close to the bottom edge of the blackboard. The level progress text should dim to a low opacity. When you finish the first level, the guideline animation will fade out gracefully. The following screenshot shows the level progress in half opacity: What just happened? There are four canvases in total now. Each canvas is in charge of one layer. The layers are divided into background, game guideline, game itself, and the user interface showing the level progress. By default, the canvases, like other elements, are placed one after the other. In order to overlap all canvases to construct the layer effect, we applied the absolute position to them. [ 161 ] Building a Canvas Games Masterclass The following screenshots show the four layers setting now in our game. By default, the later added DOM is on top of the one added before. Therefore, bg canvas is at the bottom and ui is on the top: Mixing CSS technique with Canvas drawing We are creating a canvas-based game but we are not restricted to use only a canvas drawing API. The level progress information is now in another canvas with ID ui. In this example, we mixed the CSS technique we discussed in Chapter 3, Building a Memory Matching Game in CSS3. When we drag the circles around the canvas, they may overlap the level information. When drawing the UI canvas layer, we check whether any circle's coordinate is too low and is overlapping the text. We then fade the UI canvas CSS opacity so it does not distract the player from the circles. We also fade out the guideline animation after the player levels up. This is done by fading out the whole guide canvas with CSS transition easing to 0 opacity. Since the guide canvas is only in charge of that animation, hiding that canvas does not affect other elements: if (untangleGame.currentLevel == 1) { $("#guide").addClass('fadeout'); } [ 162 ] Chapter 5 Clearing only the changed region to boost canvas performance We can use the clear function to only clear part of the canvas context. This will give the performance some boost because it avoids redrawing the entire canvas context every time. This is achieved by marking the 'dirty' region of the context which has changed state since last drawn. In the guide canvas layer in our example, we may consider clearing only the region of the sprite sheet image drawing instead of the whole canvas. We may not see significant differences in simple canvas examples but it helps boost the performance when we have a complex canvas game that includes many sprite images animations and complex shape drawings. Have a go hero We fade out the guide when the players advance to level 2. How about we fade out the guide animation once the player drags any circles? How can we do that? Summary We learned a lot in this chapter about drawing gradients, text, and images in canvas. Specifically, we covered:  Filling shapes with either linear or radial gradient  Filling text in canvas with font-face embedding and other text styles  Drawing images into canvas  Animating a sprite sheet by the clipping function when drawing images  Dividing the game into several layers by stacking several canvas elements  Mixing the CSS transition animation in a canvas-based game One thing we haven't mentioned in this book is the bitmap manipulation in canvas. Canvas context is a bitmap data where we can apply an operation on each pixel. For instance, we may draw an image in the canvas and apply Photoshop-like filters to the image. We will not cover that in the book because image manipulation is an advanced topic and the application may not relate to game development. [ 163 ] Building a Canvas Games Masterclass There are some good canvas games examples on the Internet. The Canvas Demo (http://www.canvasdemos.com/type/games/) links the latest canvas games from other websites. The Game On 2010 gallery (https://gaming.mozillalabs.com/games/) from Mozilla lists a bundle of game entries for their gaming development competition. Some of them are made in canvas. Now that we've learned about building games in canvas and making animation for game objects, such as game character, we are ready to add audio components and sound effects to our games in the next chapter. We will get back to canvas-based games in Chapter 9, Building a Physics Car Game with Box2D and Canvas. [ 164 ] 6 Adding Sound Effects to your Games We have discussed several techniques of drawing game objects visually. In this chapter, we will focus on using the audio tag that is introduced in the HTML5 specification. We can add sound effects, background music, and control the audio through the JavaScript API. In addition, we will build a music game in this chapter. It is a game that requires players to hit the correct string at the right time to produce the music. In this chapter, we will learn the following topics:  Adding a sound effect to the play button  Building a mini piano musical game  Linking the music game and the play button  Adding keyboard-driven to the game  Creating a keyboard-driven music game  Completing the musical game with level data recording and the game over event Adding Sound Effects to your Games The following screenshot shows the final result we will create through this chapter: So, let's get on with it. Adding a sound effect to the play button We had several mouse interactions in the Untangle game examples in previous chapters. Now imagine that we want to have sound effects with the mouse interaction. This requires us to instruct the game about the audio file to be used. We will use the audio tag to create a sound effect on a button. Time for action – Adding sound effects to the play button We will start with the code example available in the code bundle. We will have the folder structure similar to the one shown in the following screenshot: [ 166 ] Chapter 6 1. The index.htm file contains the basic structure of the HTML. Now let's add the following code to the body section of the index.htm file: 2. The HTML file accomplishes with a stylesheet. The file can be found in the code bundle named audiogame.css. 3. Next, we will add a sound effect to the button in the JavaScript file. Add the following JavaScript in the html5games.audio.js file: //a global object variable to store all game scope variable. var audiogame = {}; // init function when the DOM is ready $(function(){ [ 167 ] Adding Sound Effects to your Games // get the references of the audio element. audiogame.buttonOverSound = document.getElementById("buttonover"); audiogame.buttonOverSound.volume = 0.3; audiogame.buttonActiveSound = document.getElementById("buttonactive"); audiogame.buttonActiveSound.volume = 0.3; // listen the button event that links to #game $("a[href='#game']") .hover(function(){ audiogame.buttonOverSound.currentTime = 0; audiogame.buttonOverSound.play(); },function(){ audiogame.buttonOverSound.pause(); }); .click(function(){ audiogame.buttonActiveSound.currentTime = 0; audiogame.buttonActiveSound.play(); return false; }); }); 4. Open the index.htm file in a browser. There, you should see a PLAY button on a yellow background, as shown in the following screenshot. Try to move the mouse on the button and click on it. You should be able to hear a sound when you hover over the button and another sound when you click on it: [ 168 ] Chapter 6 What just happened? We just created a basic HTML5 game layout with a play button placed in the middle of the page. The JavaScript file handles the mouse hover and clicks of the button and plays corresponding sound effects. Defining an audio element The easiest way to use the audio tag is by providing a source file. The following code snippet shows how we can define an audio element: Showing the fallback content in the audio tag The audio tag is newly introduced in the HTML5 specification. We can put the fallback content inside the audio tag, such as Flash movie to play the audio. The following link from HTML5 Rocks shows a quick guide on using the audio tag with Flash fallback: http://www.html5rocks.com/tutorials/audio/quick/ Besides setting the source file of the audio tag, we can have additional controls by using several attributes. The following table shows the attributes we can set to the audio element: Arguments src Definition Explanation Defines the source file of the audio element When we use the src attribute in the audio tag, it specifies one source file of the audio file. For example, we load a sound effect Ogg file in the following code: