Beginning Game Creation
and JavaScript P5 Programming

v 1.0 © Robert P. Cook
June 1, 2016

dedicated to Kristina, Kimberley:Luke:Molly:Alex, Thomas:Joseph, Amanda:Eli, Nicholas, Jana:Kate, Peter

Disclaimer of Liability: The author makes no warranty, express or implied, including the warranties of merchantability and fitness for a particular purpose, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness of any information, apparatus, product, or process disclosed, or represents that its use would not infringe privately owned rights.

Foreword: The web site professorcook.org contains links to other textbooks. Please send any corrections or suggestions to kindlecbook@gmail.com.  You can also email me to ask questions. Please include a copy of the program with any question.

QUICK ACCESS

CHAPTER ONE --Game Scenes
CHAPTER TWO -- Game Programming
CHAPTER THREE -- Game Examples


TABLE OF CONTENTS


CHAPTER ONE -- Game Scenes

Introduction
Be Prepared
How the Book Works
JavaScript

The JavaScript Language

The whole World is a Stage
Painting Programs

Shapes
Color
Text
P5
Design your own game.

CHAPTER TWO -- Game Programming

Introduction
JavaScript Constants
Variables

Variable Names

Arrays
Tables
Objects
Exploding Objects
Debugging Program Syntax Errors

FireFox Debugging

FireFox Console
FireFox Debugger

Implement a Side Scroller

CHAPTER THREE -- Game Examples

Introduction

Sprite Animation

Popper Game

Popper Implementation

Targets
Bullets
Program Changes

Bat Swat Game

Bat Swat Implementation

Targets
Bullets
Program Changes

Air Ace Game

Air Ace Implementation

Targets
Bullets
Program Changes


CHAPTER ONE
Game Scenes

     There are only 102 types of people in the world: those that understand binary and those that don’t.

Introduction

Many years ago, a kindly IBM employee (Wayne Brown) decided to offer a weekend programming course to a group of high-school students, including myself.  That course changed my life!  For the past few decades, I have tried to repay the favor by teaching programming courses for the next generation.

The latest version of those courses focuses on video game creation and P5 JavaScript Programming.  The Programming lessons are provided mostly by the Khan Academy course Intro to JS: Drawing and Animation and Advanced JS: Games and Visualizations.  The game creation lessons are courtesy of "yours truly" and the Pixar-in-a-Box course.  If you register as a student at Khan Academy with an e-mail address, you can earn badges and recognition for your accomplishments, which in turn can be listed on college and job applications.

The games that you create will execute on Linux, OS/X, Windows and iOS on any PC, tablet or cell phone that has a web browser.

Be Prepared

An athlete trains for months to become good enough to compete.  Training is often not very fun.  A musician practices scales for months before tunes start to become recognizable.  Jugglers, artists, sculptors and many other crafts require practice.

One of the big hurdles in learning to create games is the amount of detail that must be mastered.  We have worked for years to enable students to be as creative as possible, as early as possible.  Nevertheless, be prepared to work hard.  The results will be amazing.  I promise.

Games You Build




How the Book Works

The text is a hybrid of web links to lessons at Khan Academy and Pixar, and my content.  The student assignments are labeled as "Task 1, 2" etc.  Do not skip ahead without completing the tasks; the sequencing has been carefully designed.

Task 1.1:  Watch a video (9:33) by the world's top programmers.

Task 1.2:  Watch a video (5:52) on advice for new game designers.

JavaScript

Why learn JavaScript? JavaScript is a cross-platform, light-weight, scripting language. The term "cross-platform" means that a program written for Windows or Mac OS/X or Android or Apple iOS can be run on the other platforms without rewriting.  The term "scripting" indicates that programs are not converted from text to binary before execution.  A text representation facilitates "cross-platform" execution because binary programs, such as a Windows .exe, cannot be run on different platforms without a re-translation from text.

An additional, nice property of a scripting language is "immediate execution", like a calculator application.  As a result, JavaScript enables the execution of web pages to generate dynamic content, to interact with the user through web forms, or to play games.

"Processing is an open source programming language and integrated development environment (IDE) built for the electronic arts, new media art, and visual design communities with the purpose of teaching the fundamentals of computer programming in a visual context, and to serve as the foundation for electronic sketchbooks. The project was initiated in 2001 by Casey Reas and Benjamin Fry, both formerly of the Aesthetics and Computation Group at the MIT Media Lab. One of the stated aims of Processing is to act as a tool to get non-programmers started with programming, through the instant gratification of visual feedback" [from Wikipedia]

There are over 300,000 example programs (with source code) that are posted at openprocessing.org.

The Processing environment is based on the Java programming language.  However, many browsers now disable Java automatically as the result of security concerns. Thus, the Processing designers added an option to translate Java programs to JavaScript, which is never disabled in web browsers.  The Khan Academy computer lessons use the Java/JavaScript version of Processing.

Lauren McCarthy extended the Processing philosophy to JavaScript by implementing a "pure" JavaScript version P5.js (p5js.org), which is the focus of this textbook and the programming courses at Khan Academy. She is an artist and programmer based in Brooklyn, NY. She is a full-time member of the faculty at NYU ITP, and a former resident at the CMU Studio for Creative Inquiry. She holds a BS Computer Science and BS Art and Design from MIT and an MFA from UCLA.  This book uses P5.

WATCH the video: Introduction to P5

JavaScript Language

Most of us have spoken one or more languages all our life without knowing the definition of a "language".  In programming, that understanding is critically important.  A language is the collection of possible sentences that can be derived from its grammar and its vocabulary.  A grammar is the set of syntax rules for sentence formation in a language.  Every program in any programming language, not just JavaScript, is a sentence defined by its grammar.

Example Grammar
Sentence := Adjective Noun Verb Adjective

Adjective := the    a    blue    red    white
Noun := cat    dog    bird
Verb := is     eats
Example Sentences
the cat is red
a bird is white
blue dog eats the
a cat eats a

All of the sentences in the example are legal; however, only the first two sentences make sense.  The reason is that the counterpart of syntax is semantics.  The semantics of a language defines the meanings, or actions, of the sentences in a language.  Thus, while "blue" and "the" are both adjectives; they cannot be used interchangeably because, for example, dogs can never be blue.

Many beginning programmers fail because they use language features without knowing their effect. Always try out new language statements in a separate test program before adding to a larger program.  To be successful, a programmer must understand a language's grammar and semantics.

Computers are unforgiving.  Any error in syntax or semantics will cause a program to fail.

The whole World is a Stage

A video game represents the most challenging form of media entertainment.   A stage play has moving actors, a script, and multiple, static scenes.  A movie has all the elements of a stage play, plus moving scenes, multiple camera angles, and a soundtrack.  A video game is a movie in which the audience interacts with the narrative, and possibly each other.

The following tasks challenge you to create a game's title screen, credits screen, and the first scene.  If you register as a student at Khan Academy, the web site keeps track of your progress and awards points and badges for completion.

Task 1.3:  Watch the Khan Academy video (3:07) Intro to Games and Visualizations.  Do not freak out when the video says that you already know JavaScript.

Task 1.4:  Read the Khan Academy lesson What are Scenes?  Click on the Balloon Popper 2 link and play the game.

The Khan Academy (KA) examples are coded and executed at the KA web site. Many of the book's examples, however, are executed on a local computer.  This presents a small problem.  Web browsers are designed to access web servers.  It is possible, and not too hard, to set up a local server, but we avoid that step by relaxing a browser security rule in order to execute web programs locally.

Task 1.5:  Download and install the FireFox web browser if it is not already loaded.  Be sure to download the latest version as some earlier versions have bugs that prevent my software from working..

WARNING: ONLY USE THE FIREFOX BROWSER FOR LESSONS UNTIL YOU TURN OFF THE SECURITY EXCEPTION.

Task 1.6:  Browsers require that all images on a web page come from the same file system as the web page.  We turn off that option as follows so that you can create JavaScript games with your own graphics on your own computer. Be sure that parents or roommates are aware of the security change.

  1. Open the FireFox web browser.
  2. Type about:config in the web address edit box.  Ignore the warning.
  3. Scroll down to security.fileuri.strict_origin_policy.  Double-click mouse on that line to change the value to false.
  4. Repeat the procedure and change the value back to true when not using FireFox for lessons.

Task 1.7:  Download the file of software for this course from my web site: professorcook.org.  The web link is professorcook.org/gamecamp/MyGames.zip.  A "zip" file contains an encoded version of a directory or folder hierarchy.  Double-click the MyGames.zip icon to unzip the files.  Drag the MyGames icon to the Desktop.  Delete the zip file (icon with a zipper or a Z on it).


Task 1.8:   Double-click on the MyGames directory/folder.  Then double-click on the game1 folder.  It should appear as follows:



If the file name extensions (.htm .js) are not visible, click View and then turn the "Extensions" option on in Windows 10.  In earlier versions of Windows, select Organize, then SearchAndFolderOptions, then View, then click off the X to the left of Hide File Extensions.

Task 1.9:  You will be creating and editing JavaScript (.js) files to create games and double-clicking on the .htm file to execute games.  It is critical that .htm files be associated with FireFox and that .js files are associated with an editor, such as WordPad on Windows.  Right click on game1.htm, click ChooseDefaultProgram, then select FireFox as the default program.  Right click on game1.js and repeat the steps to associate WordPad as the default program.  Observe that the small icons to the left of the file names should change as in the previous figure.


When creating new JavaScript files in WordPad, do a SaveAs "plain text"; otherwise, the file contains hidden formatting codes that are illegal JavaScript syntax.  You may also need to change the file name extension to .js from .txt.  Ignore the warning about changing file extensions.



Task 1.10:  Double-click game1.htm to see the game execute in FireFox.  The game consists of three scenes, or more abstractly, three states: START, CREDITS, PLAY; or splash-scene, credits-scene, play scene.  The transitions among scenes (states) are usually represented by a diagram that uses circles for states and arrow-labels for actions, such as a button press, winning or losing.






Every operating system distribution includes a Paint application.  Typically, the user selects a shape, edge width and color, and a fill color.  Then, the canvas can be clicked and dragged to place shapes of any size.  It is easy to see the correspondence between a Paint application's features and the drawing functions listed previously.  In fact, a quality measure for Paint programs is whether they have features that extend the basic drawing operations of P5.

Paint Program


Task 1.11:
  Now examine the "assets" folder in the "game1" folder.  Observe the correspondence between the image names and the screen views and buttons.  This task is to design and paint new graphics for game1 to design a new game.  The names and sizes of your images must match exactly those used in the assets folder.  Find a Paint program to do the drawing. 
Steps to Replace to titlebg.jpg
  1. Programming shares a motto with the medical profession: Do no harm.  It would be a bad idea to change game1 in place as any mistake would leave you with an unworkable mess.  Always make a copy of an existing project before changing it.  Change to the MyGames folder in the File Manager. Right-click the game1 folder, select Copy, then right-click in the MyGames window and select Paste.  A duplicate directory with "copy" in the name will be created.  Click on that folder name and change it to something like "test1".
  2. Double-click the test1 directory that you just created. Right-click on the Windows Start button, select Run, then enter mspaint or paint for the name of the program, then click OK.  Or select Programs or All Apps, then go to Windows Accessories or Accessories to find the Paint application.
  3. Select Resize, then click off Maintain Aspect Ratio, then click Pixels and enter 480 for the width of the image and 320 for the height.  Observe that these dimensions match the current size of titlebg.png.



  4. Now experiment with the different drawing options in Paint to create a new Title screen.  Once you are finished, select File/SaveAs.  Be sure to select the matching file format (jpg in this case).  Name the file "titlebg.jpg".  I always save new files to the Desktop, then move them to the target directory.



  5. At this point, I usually rename the titlebg.jpg file in the test1 directory to xtitlebg.jpg.  Now drag the new titlebg.jpg from the desktop to the test1/assets directory.
  6. Finally, test the replacement by double-clicking game1.htm in the test1 directory.


One of the top rules in programming is "Solve problems by step-wise refinement".  Always take little steps that you are confident will succeed.  Instead of replacing all the files in game1 before testing, replace and test one file at a time.

Game1 Assets (use Paint app to resize your images)
Name
Dimensions
backbtn.png
48 x 24 pixels
creditsbtn.png
80 x 24 pixels
playbtn.png
48 x 24 pixels
titlebg.jpg
480 x 320 pixels
credits.png
480 x 320 pixels
play.png
480 x 320 pixels

Watch the Pixar video (4:23) on Storytelling Rules.

Task 1.12:  Restricting the screen size to only 480 x 320 is annoying.   Further, having the buttons in fixed positions is cramping my creativity.  Redesign your game, or design a new game, with a different screen size and different button placements by modifying (yes that would be programming) the game1.js file.
  1. Change the following line to change the screen size.  Be aware that a scene's image files (title, credits, play.png) must match the dimensions of the createCanvas function.
                                    createCanvas(480, 320);
  2. Change the xy values in the following code to place your buttons in different positions.  Observe that the origin (x=0, y=0) of the screen is the upper-left corner and that the y axis is positive downward, which are both different conventions than those taught for the Cartesian coordinate system in school.
  3. Change the numbers in the game1.js file to different xy values to relocate buttons.
        button1.file = "./assets/playbtn.png";
        button1.xy = [440, 60];
        button1.state = PLAY;
        button2.file = "./assets/creditsbtn.png";
        button2.xy = [440, 105];
        button2.state = CREDITS;
        button3.file = "./assets/backbtn.png";
        button3.xy = [440, 160];
        button3.state = START;
Cartesian XY Coordinates
Screen XY Coordinates



Painting Programs

After completing Tasks 11 and 12, you have learned that you can modify code in an existing program to create applications that appear completely different from the original.  In Chapter Two, we introduce programming concepts that will allow you to be even more creative.

But first, we utilize Lessons at Khan Academy to practice coding programs that Paint shapes and text.

Anything that is displayed on the screen by any application can be captured by tapping the Print Screen key (Prt Sc).  Next, start the MsPaint program and tap the Paste icon.  The image of the entire screen will appear.  Next, tap the Select icon and drag a selection rectangle (dotted lines) around the image of interest.  Now tap the Crop icon.  Finally, select File/SaveAs.  I always save all my images to the Desktop, then drag/drop them to the assets folder.

Shapes

Task 1.13:  Complete Lessons 1 and 2 at https://sites.google.com/site/professorcookga/.

Colors

Color seems like a simple concept. The three kinds of photo-receptors in the human eye respond most to yellow, green and violet light. The difference in the signals received enables the brain to differentiate a wide range of colors, being most sensitive to yellowish-green light and to variations in hues in the green-to-orange region.

The most common computer color model is RGB, which combines Red, Green and Blue weights to encode a color.  Typically, the values are encoded as 0 to 255 with (0, 0, 0) as black and (255, 255, 255) as white.  Note that the binary (base 2) range of numbers that can be stored in a byte (8 bits) is 000000002 to 111111112 (0 to 255).

Rendering projects a 3D program-generated scene onto a 2D matrix of pixels in a graphic card's frame buffer.  To make the result more realistic, it is desirable to have color values with an added transparency component. Observe that RGB is stored in 3 bytes; the 4th byte stores a transparency code (0 invisible, to 255 opaque).  The four-byte color model is referred to as RGBA.  I know that A is not a mnemonic for transparent so I looked up the history. "The inventors named alpha after the Greek letter in the classic linear interpolation formula αA + (1-α)B." [Wikipedia]

Most frame buffers allocate 4 bytes for each pixel. A 640 pixel (wide) by 480 (high) display with 32-bit color would need 640*480*4B or 1.2MB of  memory.

Top Rectangle is Partially Transparent

Task 1.14:  Complete the first 3 steps of Lesson 3 at https://sites.google.com/site/professorcookga/.

Programming Rule #1:  The best way to write correct code is to copy correct code.

The documentation at the Khan Academy web site has an online reference manual and an example for each function.  The p5js.org web site also has an online reference and many examples.  Copy an example and then use step-wise composition to transform it to do your bidding.

Text

In addition to graphics, a display paints characters, such as the ones that you are reading. Characters are grouped into FONT families.  In the old days, each character in a font was carved in a block of wood.  Typesetting a newspaper involved arranging the wooden characters in a large frame that was coated with ink and stamped on a blank sheet of paper. Display font characters are stored as a block (rectangle) of pixels (picture elements).


When needed, each rectangle is copied (BLiTed (block transfer)) to video memory. In the past, each character (a b A B) in each font required its own definition rectangle, which resulted in thousands of definitions for every combination of size/family/language (12 pixel/Times/Arabic) that a user might want. Today TrueType technology uses mathematics to define a single description of each font family that can be scaled larger or smaller arbitrarily.  A TrueType font only has one file for all the choices, which represents a significant space savings.

The following letter A would need 1000s of bytes to store its pixel rectangle, but if you examine its outline, there are only four curves, two of which are symmetric, and a number of straight lines.  Thus, by describing the straight lines (two end points) and the curve parameters, an A of any size can be drawn.  The letter in the next Figure was drawn with a TrueType font size of 640.

Task 1.15: Watch the Khan Academy video (4:16) Terrific Text: Part One.

To make it easier for beginning programmers, P5 permits color names to be used for the background, fill and stroke functions.  Bookmark the following Color Link to refer to a handy list of color names. Khan Academy's programming environment does not support this option.

Task 1.16: Replace one of the image buttons in Game1 with a text button as follows.  The values in the array list are the xy position (150,40), the font size (36), and the fill color (white).

button3.xy = [0, 0];
button3.text = ["score:", [150, 40, 36, "white"]];

Text can also be listed to overlay the top of an image.

button7.file = "./assets/infobar.png";
button7.xy = [240, 304];
button7.text = ["acorns",[50,305],"targets",[124,310],"score",[210,310,16,"blue"]];

P5

P5 implements functions to draw points, lines, curves, arcs, triangles, rectangles, quadrilaterals, circles, and ellipses. Further, the figures can have different edge widths (termed strokeWeight) and edge colors (termed stroke, like a brush stroke).  Closed figures, such as circles, can also be drawn with, or without, a fill color.  The following example illustrates the drawing options for the different shapes and how to draw text.  Note that the stroke and fill properties must be set before drawing a figure.  Further, once a fill/stroke property is set, it will apply to all later shapes that are drawn.  A common error occurs when users draw multiple shapes and forget to set, or reset, one of the stroke, fill or weight properties.

The web link is to a JSFiddle example, which is a web site that is similar in capability to the one at Khan Academy.  We will still utilize the Khan Academy web site for lessons. As mentioned very early in the lessons, P5 is just one of thousands of code libraries for JavaScript. None of those libraries, except for P5, can be accessed from the KA environment.  The jsfiddle.net web site implements an environment in which users can code projects that can be made available world-wide, including on tablets and cell phones. JSFiddle provides a library option that is useful when multiple libraries are required.

Be aware that the external web address of any library should have an https:// prefix. You can click the "Fork" button or copy/paste the code for this example to create your own P5 Fiddles. The only difference in the code from the KA examples is the "setup" function that sets the window width and height; whereas the KA environment fixes the window size.

function setup() {
   createCanvas(320, 240);
}

function draw() {
   background(102,0,0);

}


Task 1.17: Change the code to experiment with the P5 drawing options, then click the Run button to execute.


Shape and Text Drawing
http://jsfiddle.net/bobcook/dq1r282a/



Other P5 Examples by Me (Click http://jsfiddle.net/user/bobcook/)

stroke(color)
point(X,Y)
line(X1,Y1, X2,Y2)
noStroke()
rect(X,Y, width,height)
XY locates top-left point
ellipse(X,Y, width,height)
XY locates center point
fill(color)
triangle(X1,Y1, X2,Y2, X3,Y3) ellipse(X,Y, width,width)
XY locates center point of circle
noFill()
quad(X1,Y1, X2,Y2, X3,Y3, X4,Y4)  draw a four-sided figure
strokeWeight(numPixels)
text(" words ", X,Y)
XY locates bottom-left point of the 1st letter
arc(X,Y, width,height, start,stop, mode)
start/stop angles are in radians or degrees
mode is OPEN, CHORD or PIE

A circle represents a 360 degree arc that can be divided into four 90 degree quadrants (X Y, -X Y, X -Y, -X -Y) just like a Cartesian graph. In most mathematical work, angles are typically measured in radians rather than degrees. This is for a variety of reasons; for example, the trigonometric functions have simpler and more "natural" properties when their arguments are expressed in radians. These considerations outweigh the convenient divisibility of the number 360.

Remember that PI is defined as the ratio of any circle's circumference to its diameter. One complete circle (360° or the circumference) is defined as 2π radians, so 180° is equal to π radians, or equivalently,  degrees can be converted to radians by multiplying by the mathematical constant: 1° = π  ⁄ 180.  (The little circle ° superscript denotes "degree".)  P5 defines the radians() function to convert degrees to radians and a degrees() function to convert radians to degrees.

Design Your Own Game

Task 1.18: Complete Lesson 10 at https://sites.google.com/site/professorcookga to design your own game.


CHAPTER TWO
Game Programming

“Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible,
you are–by definition–not smart enough to debug it.”
[Brian Kernighan]

Introduction

The reader has probably observed that there is a lot more to JavaScript syntax than what we have discussed so far.  In this Chapter, we cover constants, variables (not constants), and statements, such as assignment (copying a value into a variable).  With this additional information, more should become clear about programming, and the opportunities for creativity expand.

JavaScript Constants

Sadly, drawing beautiful pictures must be interrupted long enough to learn additional language concepts.  Notice that we did not say JavaScript concepts.  The majority of concepts in the book apply to all computer languages, not just JavaScript.  Therefore, you are learning how to "program".  JavaScript and P5 are just the environment chosen to make the learning process as interesting as possible. P5 is not a language; it is just a library of useful functions, such as ellipse and rect.  The JavaScript language is case sensitive; that is, rect IS NOT the same as Rect.

A constant is a value that never changes.  JavaScript supports integer (whole number) constants, real numbers (numbers with decimal fractions), Boolean (true or false) values, strings/text (zero or more characters), and arrays (ordered list of constants).  JavaScript also defines two special constants: null, which denotes the "has no value" value and undefined, which indicates that the value is unknown. The world of computing is built (mostly) on these data types.  These different data types have evolved over the decades to meet human computing needs.

A property of computer processors is that the number of bits (0s and 1s) in operands is limited in size.  In the real world, you can repetitively add one to a number until exhaustion sets in.  On a computer that does not work.  Adding one to the largest number is an errorSubtracting one from the most negative number is an error.

Numbers are stored in scientific notation in memory.  Scientific notation is the way that scientists easily handle very large numbers or very small numbers. For example, instead of writing 0.0000000078, we write 7.8 x 10-9.  The "digits" portion (7.8) of the notation is referred to as the mantissa.

Every operating system includes a Calculator application.  Multiply 99 by itself repeatedly. Eventually, the displayed result will switch to scientific notation with a mantissa and an exponent.  The reason is that calculator numbers work the same as JavaScript numbers.  Once an integer exceeds about 15 digits, the exponent will keep on increasing but the number of significant digits will stay the same.  JavaScript ARITHMETIC CAN BE INEXACT!!!  A programmer has to always be aware of her limitations.

Another problem exists with computer arithmetic.  Many fractions are inexact!  The reason is that some fractions, such as 0.1, are repeating fractions in the binary (base 2) number system ( 0.610=0.10012 ) even though they are not in decimal.  Combined with the "15 significant digits restriction", the result is that 0.1 is really 0.09999999...  The consequence is that 100.43-100.0 == 0.43 is not exactly equal to 0.43.  USE EPSILON COMPARISON WHEN EQUATING FRACTIONS.

Epsilon Comparison
AbsoluteValueOf(100.43 - 100.0) <= 0.0000001

JavaScript Constants
Constant Type
Range of Values
Examples
null
null x = null;
Boolean
true, false
today = true;
whynot = false;
number

1.7E +/- 308 (15 digits)
The 15 digits that are retained in a calculation are based on the range of magnitudes.
10.0e30 + 10.0e-30 will lose the fractional part.
degrees = -32;
hot = 100;
pi = 3.14;
half = .5E+2;
pi = 314.0e-2;
string
Zero characters to many thousands.
The beginning symbol ( ' or " ) must match the end symbol.
The \ notation represents invisible characters, such as new-line \n or tab \t.
noChars = "";
hello = 'hello';
twoLines = "hi\ngirls";
apple = 'ap\112le';
array
zero elements to many thousands
vertices = [ 0,0, 5,5, -12,34 ];
mixture = [ 5, true, 'hi', 6.8 ];
empty = [ ];


Strings obviously require some kind of marker (such as " or ') so that the parser can tell the difference between JavaScript reserved words (if return do while etc.) and a user's strings ("if" "return" etc.).  In a similar fashion, there exist markers to allow programmers to add explanatory comments to their code for the benefit of others.  Some JavaScript code has been in use for years!  Its value is enhanced by embedding documentation comments in the code.

There are two comment syntax definitions // and the multi-line comment syntax /* */.  In the first option //, all characters from the // to the next end-of-line character are ignored.  The second convention /*  */ encloses the text that comprises the comment; multiple lines can be enclosed.

Comments are also useful when an error is encountered.  Just comment out /* */ the last lines of code entered and verify that the program in its previous state still works correctly.  Consult documentation to try to identify the error in the commented-out code.

Sometimes reading documentation just does not help to overcome a mental block.  One of the traditional aids in programming is to ask someone else to take a look at the code, either face-to-face or through an online forum.  A second debugging option is based on a principle termed "determinism", which means that given a JavaScript statement, a programmer can properly describe the result.  Programming with statements or methods that are not understood is a recipe for disaster.  Sometimes mental brain freeze causes a programmer to think that code is correct when it is not.  In this case, intersperse output statements throughout the problem code, then compare the mental model to the displayed reality.

Variables

A variable (also termed an identifier) in all programming languages represents a name-value(s) pair in which the value can be modified.  Referencing a name is the same as referencing its value(s).  Like any other component of a computer language, names have syntax rules. For example, ben-gurion might be a valid human name, but in JavaScript, the minus sign (-) indicates subtraction.  Therefore, minus signs and other arithmetic symbols cannot be used in names.


Name Examples

_hello  good_bye  Y567  $boy


Variable Names

Variables are declared using the var keyword with, or without, an initial value.  If no initial value is specified, the value is undefined. The undefined value behaves as false when used in a Boolean expression. The undefined value converts to NaN (not a number) when used in an arithmetic expression. When a null variable is accessed, the null value behaves as 0 in numeric expressions and as false in Boolean expressions.

JavaScript is a dynamically typed language. That means you do not have to specify the data type of a variable when you declare it.  Further, data types are converted automatically as needed during script execution. So, for example, you could initialize a variable to a number, then assign it a string value, then a Boolean value, etc.

Creating/Declaring a Variable Name

var apple = 'ripe';
var number;
var alpha = 3, beta, gamma = false;

The language concept of scope is defined as the area of a program in which a name is known.  A declaration outside any function has global scope and can be referenced in all functions in which the name is not re-declared.  When you declare a name within a function, it has local scope; that is, the name can be accessed anywhere within that function, but nowhere else.

Task 2.1:  Complete Lesson 4 and Lesson 5 (steps 1 and 2 only) and Lesson 6 and Lesson 9 at https://sites.google.com/site/professorcookga/.
Task 2.2:  Go back to the Game in Lesson 10.  Use an "if" statement to control gate passage (if heroHas) and/or the win test.

Arrays

The term array is used generally to refer to sequences of values.  The element data type of an array need not be the same for all components. Further, the number of elements in an array can increase or decrease as a program executes.  Unlike mathematics, an element i of vector x is not referenced, or indexed, as x(i) but as x[i]. The reason for square brackets is that parentheses () were already in use to denote function arguments.

The first element of an array is always at index zero e.g. x[0].  If a vector has N elements, the last element is referenced as x[N-1]. The limits of an array are sometimes referred to as bounds. The lower bound of a JavaScript array is zero; the upper bound is N-1.  The property name.length can be used in expressions to access the number of elements (N) in an array.

The first step in creating a new data type is to write procedures to output its values.  To access the elements of an array x as a string, call x.toString(), which will return a string in which all the elements are concatenated and comma-separated.


Array Examples
       var a = [1, 2, 3, 4, 5];
       var b = [22, 'hi', 5.6, [98, 44, 37] ];
  1. An array reference consists of the array Name[Expression].
  2. The Expression is referred to as the array's subscript.
  3. The subscript expression for an array must evaluate to an integer between zero and TotalNoOfElements-1; however JavaScript neither checks for subscript errors nor issues runtime errors for violations of the rule. Accessing an out-of-bounds element yields a null value.  However, storing into an out-of-bounds element is always legal. JavaScript inserts the element at the specified index. The intervening elements, which have not been assigned, are treated as null.
  4. If an array element's value is itself an array, the variable is referred to as a multi-dimensional array.  In this case, subscripts are listed left-to-right from the outermost array to the innermost, e.g. b[3][1] == 44.
  5. The "standard" method of referring to an array's TotalNoOfElements is name.length.  In the example above, array a has five elements, b has four elements, b[3].length has the value three.
Task 2.3:  Watch the Khan Academy video (4:59): Intro to Arrays.
Watch the Pixar-in-a-Box video (5:19): Start Here.  Why watch a video about movies?  There are several reasons.  First, a video game is just a movie in which the audience gets to interact.  Second, all of the technology that supports movies, also supports games.  The game industry has lots to learn from the movie industry.

Tables

Conceptually, an array is a table whose elements are indexed by the consecutive integers 0 to array.length-1.  But what if the indices are not consecutive; what if the indices are not integers?  Another term for a table is an associative list, which is composed of (key, value) pairs.  If the indices conform to the "array" property (only integers), the data structure behaves like an array in other programming languages.

Initializing an array with non-integer indices will "break" the array property. Thereafter, the array will be treated as a table  The integer indices do not have to be initialized in order; 35421, 54321, 12345 are all legal subscript sequences that still maintain the array property.

A table can be indexed by strings, Booleans or numbers.  Telephone books and contact directories are associative lists.  Do not confuse strings as table values with strings as table keys.  An associative element can only be created by an assignment, such as x['foo']=3, x.foo=3, or by using the table constant syntax.

function setup() {
    createCanvas(320, 240);
    var a=[];
    a['pet'] ='dog';
    a.name = 'joe';
    a.age = 24;
    for (var x in a) out(x+' '+a[x]);
    a = {pet: 'cat', name: 'sally', age: 23}; //a table constant
    for (var x in a) out(x+' '+a[x]);
    a = [1,3,7,9];                                 //re-establishes the array property
    for (var x in a) out(x+' '+a[x]);
}

function draw() {
background(127);
}

function out(a) {
    console.log(arguments[0]);
}

OUTPUT
pet dog
name joe
age 24
pet cat
name sally
age 23
0 1
1 3
2 7
3 9

Task 2.4: Watch the Khan Academy video (5:25) Intro to Objects.

Objects

Early computer languages provided only a fixed set of data types, but it was not long before programmers demanded the ability to define their own data types.  Ideally, any extension would have the same capabilities as a built-in type, such as integers or strings.

Real-Life Objects [from w3schools.com]

Object Properties Methods

car.name = Fiat

car.model = 500

car.weight = 850

car.color = 'white'

car.start()

car.drive()

car.brake()

car.stop()

You define (and create) a JavaScript object with the table constant syntax.  If a table has associated functions that 'understand' its content, the table is termed an object.

Objects can consist of just functions or a mixture of data and functions.  The object's identifiers, or fields or properties, can be accessed by using a qualified, dotted name (car.model) or by using a subscript (car['model']).  An example is the Image object in P5.  It defines "width" and "height" properties, but to manipulate an Image, you pass the object to a function, such as image() or tint().

The JavaScript syntax does not define a notation for Object constants.  Instead, the "new" keyword calls an Object's constructor function to initialize its properties.

Exploding Objects

One of the most dramatic components of a computer game is a special effect, such as a laser beam, rocket vapor trail, or an explosion.  Since this is a kinder, gentler book, we use the term Fountain object to encompass special effects.

Since objects are a user-defined extension to the built-in types, Fountain-type variables can be defined and assigned to anywhere in a program.  They can be array elements and properties of other tables.

Fountain objects are composed of properties (explained shortly) and an array of Particle objects.  Each Particle has an xy location, a size, a lifetime, an angular direction of travel, and a rotation (in degrees, + clockwise, - counter-clockwise).

The number of Particle properties is minimized to save space since there can be thousands of Particles in a single Fountain.  Fountains define properties that are common to all Particles, such as color, limit, shape and speed.  Fountains also have a "name" property, which is used by the constructor function to locate a fountain's property table.

Task 2.5:  Complete Lesson 7 and Lesson 11 at https://sites.google.com/site/professorcookga/.

In P5, the function "setup" is called once before the rest of a program begins.  As described in Chapter One, an important step in "setup" is to define the canvas' width and height.  The "draw" function is called thirty times per second.  If the function draws something slightly different each call, the screen appears animated.  Particles can change their properties on every "draw" call; thus, any combination of attributes can be animated.

A Simple Fountain Definition (either format is acceptable)

    var fountain1 = {};
    fountain1.name = "foo";
    fountain1.color = ["green"];
    fountain1.shape = "rect";
    fountain1.size = [12,12];
    fountain1.angle = [200,240];
    fountain1.lifetime = 120;
    fountain1.rotation = 3;

    var fountain1 = {
    name: "foo",
    color: ["green"],
    shape: "rect",
    size: [12,12],
    angle: [200,240],
    lifetime: 120,
    rotation: 3
    };

Task 2.6A:  Click on the following link Particle User Structure to one of my jsfiddle examples.  Change the attributes and click Run to learn about simple Fountains.  Remember "step-wise composition"; do not change everything at once.

A Fountain's Draw() function displays the current array of particles.  The Create() function adds new particles and the Step() function modifies the location, size, angle and rotation of each Particle. 

Fountain Properties
  • acceleration: added to velocity on every step, default 0
  • color/colors[a,...]: array of color names or [r,g,b,a], sets this.colors, indexed by "life" fraction when drawing
  • dxy[a,b]: fraction of screen width/height, centered at xy, [-a:a,-b:b] defines generation box, default [0,0]
  • file: path string for an image file, sets this.image and this.f.image equal to loadImage
  • gravity: applied to velocity.y at every Step, default 0.01, omitted if acceleration is non-zero
  • lifetime: number of "draw" steps for each particle to live, default 99999999
  • limit: number of particles to generate, default 99999999
  • rate[a,b...]: array of pairs [draw-count, particles-to-generate-per-CreateN], default [0,1], cycles
  • shape: string name of a "Draw" function (ellipse, rect, image, point), default "ellipse"
  • sizePercent: grow or shrink particle size on every Step, default 1
  • speed: determines initial velocity, default 1
  • speedx: random add-on to speed at particle creation [-speedx,speedx], default 0

Particle Properties

  • angle[a,b]: random directional angle (between a and b) in degrees, default [0,0]
  • rotation: angular velocity in degrees, default 0
  • size[a,b]: randomly sets particle size between a and b, default [2,2]

var t =
    {
    name: "test",
    colors: ["blue",[0,255,127,127]],    //color sequence over a particle's lifetime
    lifetime: 600,                                  //number of "draw" calls to live
    angle: [330,360],                            //generate randomly from 330 to 360 degrees
    x: 0.2,                                             //x is at 2/10 of the screen's width
    y: 0.1                                              //y is at 1/10 of the screen's height
    };


Task 2.6B:  Change to the game2 directory in the MyGames directory.  The example creates Particles at the current xy mouse position and also displays a counter that reflects the number of active Particles.  Execute game1.htm and study the example, then create a different fountain using an  image file.

Steps to Create Particles from Image Files

  1. Google or Bing for public-domain clip art "stars".  I found a red star with a yellow border with this link.
  2. Unfortunately, the image is too large (600x571).  We need to reduce the size to 32x32 or 24x24 or 16x16.  However, the Paint application deletes transparency so we found an online alternative application, sketch.io.
  3. Once you have found an image that you like, right-click it and SaveAsImage to the Desktop.

  4. Go to sketch.io in the web browser and open SketchPad.
  5. Click the File icon ans select UploadAsNew.  Type the file name on the Desktop (in my case star.png).  The image should display in the window with a gray/white checkered background, which indicates an alpha value of zero (transparent).

  6. Click the Export icon, select a matching image format (png in this case), SizeTo "fit within", and set the desired width and height, then click Download.

  7. Copy the image file from the Desktop to the "assets" folder of game2.  Modify the Fountain properties as follows, then test by double-clicking test1.htm.
var fountain1 = {};
    fountain1.name = "foo";

    fountain1.color = ["white"];  //set to white for images
    fountain1.shape = "image";
    fountain1.file = './assets/Drawing.png';
    fountain1.size = [1,1];

    fountain1.angle = [200,240];
    fountain1.lifetime = 120;
    fountain1.rotation = 3;

Several other of my examples can be found at jsfiddle.net.

The second example (User Drawing) illustrates how a programmer can define their own shape functions for particles.  All Particle and Fountain properties are accessible in the function.  Further, programmers can add new Fountain properties as long as their names do not conflict with those used already.

Task 2.7 [optional]:  Define your own Particle shape function, such as triangles, by modifying the function in the User Drawing jsfiddle example linked to previously. The function draws random letters with different font sizes based on the partSize property.  Change the first color from blue to red.  Experiment with other changes by modifying existing property references or by replacing the code entirely.  The "fountain" parameter enables the "draw" function to access any property that is common to all particles.

function ftext(fountain, particle) {
  stroke(fountain.colors[Math.floor(particle.life*fountain.colors.length)]);
  noFill();
  textSize(particle.partSize);
  text(s[particle.id%26], particle.location.x, particle.location.y);
}


Debugging Program Syntax Errors

Beginning programmers have to learn to pay attention to syntax details by making errors.  I am sure that you have already made a mistake in your code and discovered that the code does not run, which usually results in a blank or frozen screen.  That is not very helpful.

Luckily, many web browsers include JavaScript debuggers.   If a syntax or execution error occurs, a debugger can be used to track down the file name and line number at which things went bad.

FireFox Debugging

We recommend the FireFox debugger.  FireFox is available free at mozilla.org.  To use the FireFox debugger, you need to create a web site on the desktop.  You can also debug a program online, but often all the JavaScript included in the environment can obscure the details of your code.
  1. Double-click on game1.htm name in your game directory.  If FireFox is not your default browser, you may need to right-click and select execution with FireFox.  The program should run and display its output. Click on the triple-line icon in the upper right to display Developer options, then click Developer.
    FireFox Developer Options



  2. Select the "Page Source" option.  The HTML source for the game1.htm file is displayed.  This is a great option to know about, as it can be used on any web page to examine how it works.



  3. Next, select the Debugger option.  The following panel is added to the bottom of the screen.


FireFox Console

By using FireFox's console, two useful debugging options are available.  JavaScript implements a console.log(list) function and P5 implements a print(list) function.  Intersperse code with print/log statements to verify that what you think is happening really is happening.  Select the debugger's Console window to view the output.

Remember the P5 draw() function is invoked thirty times per second.  When debugging display functions, it is often useful to set the frame rate to one.
  1. Double-click on game1.htm in your game directory.  Use the previous instructions to display the Console panel. Click the Console tab, then the Logging tab, the click the "reload page" icon in the address bar.

  2. TIP: For accelerated development, keep game1.js open in an editor.  As errors are discovered, fix them in the file. Next, select File/Save instead of closing the editor and double-clicking game1.htm.  Just click the browser's Reload icon (an arrow circle) in the tool bar and the program will be re-executed with the updated code.
  3. The next Figure shows a sample error message for the program sketch.js, which has a missing right parenthesis.  Error messages are often unclear. Clicking on the sketch.js:8:15 hyperlink on the right will highlight text within one line of the error.  From that point, you are on your own to track down what you did wrong.

    function setup(  {


Projectiles

Particles have no interaction with game objects, or each other.  Projectiles are particles that participate in the physics of a game.  They bounce, apply force on collisions, and are affected by friction.  Game physics is discussed in more detail in Chapter Three.

In the following example, blue balls are dropped by pressing any key.  Bullets are fired from (x=0, y=0) toward wherever the mouse is clicked.  If a bullet hits a ball, the ball is pushed forward by a force proportional to the bullet's weight and speed.  By default, a physics object's weight is proportional to its area.

Physics objects must have different draw functions from particles because their locations have to be converted from meters to pixels.  The goal of these tasks is to introduce students to different projectile properties.

Projectile Properties

  • angle - [-a,+b] specifies a shotgun effect (a,b degrees) in which bullets fan out from the barrel
  • load - number of bullets fired in a single shot
  • period - time in ms between trigger pulls, or reloading
  • pshape - physics shape (box, circle, edge, polygon)
Task 2.8: Execute game2/game2.htm and study the projectile properties.  Now modify the values to learn about their effects.  The physics shape (pshape) property can be set to 'circle' or 'box'.

    var bullet = {};
    bullet.name = "bullet";
    bullet.colors = ['red'];
    bullet.shape = "pfill";
    bullet.wh = [18,18];
    bullet.gravity = 1;
    bullet.speed = 80;
    bullet.limit = 99999;
    bullet.lifetime = 120;
    bullet.collidesWith ="4";
   
    bullet.angle = [0, 0];
    bullet.load = 4;
    bullet.period =1000;
    bullet.pshape = "circle";

Task 2.9: Execute and study the game2/game3.htm example.  Observe that the speed had to be increased to account for the greater weight of the clown.  Experiment with different bullet images.

var bullet = {};
    bullet.name = "bullet";
    bullet.shape = "pfill";
    bullet.gravity = 1;
    bullet.speed = 500;
    bullet.limit = 99999;
    bullet.lifetime = 120;
    bullet.collidesWith ="4";

    bullet.colors = ['white'];
    bullet.file = './assets/clown.png';
    bullet.wh = [50,50];
   
    bullet.angle = [0, 0];
    bullet.load = 4;
    bullet.period =1000;
    bullet.pshape = "circle";

Implement a Side Scroller

Task 2.10:  Complete Lesson 7 and Lesson 12 at https://sites.google.com/site/professorcookga/.


CHAPTER THREE
Game Examples

Q: Why did the programmer quit her job after a year?
A: She didn't get arrays!

Introduction

The challenge in writing the software for this book was to maximize the creativity of the student while only requiring a minimal understanding of programming.  The chosen solution was to define a game as a table (defs) of properties and Objects.  Chapter One introduced the screen and button properties.

Screen Definition

  1. Define a screen variable.      var screen0 = {} which is local to the setup() function.
  2. Each screen is assigned a unique State number (0, 1...) and name, such as START.
    var START=0;   which is global to all functions.
  3. Set the defs.screens property to an array of screens in numerical order by State number.
    defs.screens = [screen0, screen1, screen2];
  4. The function call  startState(state number or name) will begin the game at the selected screen.
  5. The function call  changeState(state number or name) will switch from one screen to another, usually upon winning, losing, restarting, or advancing a level.
  6. In P5, the preload() function is executed before setup() to make sure that a game's media files have been loaded prior to showing the splash screen.

    var music1, sound1;
    function preload() {
      music1 = loadSound('./assets/endingMusic.m4a');
      sound1 = loadSound("./assets/pop.mp3");
    }

  7. Assign screen properties.  Targets and Bullets will be discussed shortly.
    screen3.file = "./assets/gamebg.png";    // image file must be the same size as createCanvas
    [optional] screen3.image = image1;      //can be set directly to global variable from preload()
    screen3.fileMusic = "./assets/rock.mp3";    // background music for the screen
    [optional] screen3.music = rock1;        //must be set directly to global variable from preload()
    screen3.buttons = ["squirrel", "circle", "info", "restart"];   //array of buttons
    screen3.targets = [                                                               // array of targets
      ["ball","random",15,[80, 80, 450, 280]],
      ["wall","fixed",1,[240,253]],
      ["ball","autoFire",15,4000,"left",1,-1, 100, 200]
    ];   
    screen3.bullets = [["bullet", [0, 0]]];                                // array of bullets
    screen3.scroll = [160, 0.003];                                          // start Y, pixels/ms
Every game defines a doState() function that codes the actions associated with each screen.  The software provides two all-in-one functions: simpleScreen() and scrollScreen().  A simple screen is just a static image.  A scrolled screen can be moved either top-down (2nd argument true) or right-to-left (false).  In the former case, the screen's image must be taller than the canvas' height.  In the latter case, the screen image must have a right edge that lines up with its left edge.  The image is rotated to give the appearance of a moving background.  Both functions return the Boolean value true if a button, such as Back, is clicked that induces a state change.

function doState() {
  switch (state) {
  case START:
  case CREDITS:
    simpleScreen(state);
    break;
  case PLAY:
    if (scrollScreen(state, true)) break;
    for (var i=0; i<bullets.length; i++) bullets[i].Step();
    b2Update();
    b2Draw(false);
    if (defs.vars.targets > 15) changeState(START);
    break;
  case EXIT:
    background(0);
    return;
  } //switch
  mouseClick = [0,0];
}

Task 3.1:  Download, execute and study the two scrolling examples in game3.zip.

Button Definition

  1. Define a button variable.      var button1 = {} which is local to the setup() function.
  2. Assign a unique button name in the definition (defs) table.
    defs.buttons.back = button1;
  3. List the button names in the screen(s) where they will be displayed. The order is not critical.
    screen1.buttons = ["back", "next"];
  4. Assign button properties.  A button can be Text or an Image. Text can overlay an image.
 [optional] button1.file = "./assets/back.png";    // image file for the button's image
 [optional] button1.image = image1;      // can be set directly to global variable from preload()
 button1.xy = [160, 150];                        // location of the center of the button
 [optional] button1.rotation = 90;            // rotate the image 90 degrees clockwise
 [optional] button1.state = PLAY;           // changes the screen to PLAY when clicked
 [optional] button1.blink = true;              // the button blinks
 [optional] button1.visible = false;          //does not display or react to mouse clicks
 [optional] button1.text = ["score:",[150,40,36,'white']];     // x, y, font size, fill color
 [optional] button1.text = ["highscore",[60,324,24,'white']];

If a button's text matches a property name of defs.vars, such as score or highscore, the value is converted to text and displayed.  A game's score and high score are collected automatically.  The high score displays as a column of unique, non-zero scores.

[optional] button1.wh = [32, 44];                                //displayed width/height of an animation frame
[optional] button1.frames = [5, 1000, [32,44,32,44],  // number of frames, ms/frame, [x, y, width, height] of a frame
        [32*2,44,32,44], [32*3,44,32,44],
        [32*4,44,32,44], [32*5,44,32,44]];

Sprite Animation

One of the cool areas of game coding is animated sprites.  Back in the old days at Disney, animations were drawn one frame at a time on acetate cels, which went out of use in 1990. Disney Stores still sell production cels from The Little Mermaid (their last film to use cels) at prices from $2,500 to $3,500, without the original backgrounds.  Today, cels have been replaced by sprite sheets, such as the following image file, which is 256x256.  

We all know that the "motion" in motion pictures is actually still frames being displayed many times per second.  The source material, program or movie reel, records so many frames per second, which is referred to as the frame rate.  The rate at which the projector displays the frames is termed the refresh rate.  Since the draw function is called thirty times per second, we can generate movies under program control.

To illustrate animation, we will display a mountain lion running using eight frames from a sprite sheet, which is illustrated next. Google or Yahoo "sprite sheet". There are hundreds of examples on the web.  An image can be loaded into a Paint program to determine the rectangle size and location for each frame.  In the example, the frames are 128x64.

Mountain Lion Sprite Sheet


Using step-wise composition, we first implemented a button using just the image.  Next, we added a wh property of [64,32] and a frames property of [8,200,[0,0,128,64]].  Finally, we insert the values for the remaining 7 frames.  I like to list the frame definitions on different lines so that they match the order on the sprite sheet.  Notice that the example rotates the figure 90 degrees and displays it half-size.

    button4.file = "./assets/lucat.png";
    button4.xy = [240, 160];
    button4.wh = [64, 32];
    button4.rotation = 90;
    button4.frames = [8, 200,
        [0,0,128,64], [128,0,128,64],
        [0,64*1,128,64], [128,64*1,128,64],
        [0,64*2,128,64], [128,64*2,128,64],
        [0,64*3,128,64], [128,64*3,128,64]
    ];

Unfortunately, the Windows Paint program does not support transparent backgrounds, which is very annoying.  Luckily, many commercial products, such as Adobe, offer free trials.  However, sometimes you just have to make do.  Windows Paint is further annoying in that just re-sizing an image will change its transparent background to opaque.  In the following example, the rock is clearly too large.  Ideally, we would edit the image to the desired size.

button4.file = "./assets/rock.png";
button4.xy = [240, 160];
button4.wh = [512,512];

The button-frames property can also be utilized to crop and scale images.

    button4.file = "./assets/rock.png";
    button4.xy = [240, 160];
    button4.wh = [46, 31];   //[512,512];
    button4.frames = [1, 1, [20,120,460,310]];

Task 3.2:  Download, execute, and study the two frame examples in game4.zip.  Try downloading, cropping and re-sizing a web image.  Download a sprite sheet and play your own animation.
Complete all 14 Pixar-in-a-Box lessons on Character Rigging to gain a good appreciation of animation techniques.

Popper Game

The book's software implements a table-driven version of the very-popular Box2D physics engine.  My web site has a free P5 Box2D Physics tutorial http://professorcook.org/CHAPphysics.pdf if you are interested.  You should finish this book first.  By the way, buttons and particles are immune to physics effects, such as gravity and collisions.

Game idea
A boy has 10 rocks.  He throws the rocks to try to break all 15 Sprite bottles.  Aiming is indicated by an arrow, which is positioned by holding down the left mouse button.
Scene 1
Splash screen, visual elements are title background image, Play button, Credits button
Scene 2
Credits screen image with Back button to Scene 1
Scene 3
Win image with current score and Back button to Scene 1
Scene 4
Lose image with current score and Back button to Scene 1
Scene 5
Play screen with background image, 15 randomly scattered bottles, boy and shot-direction arrow in lower left.
Status bar at screen bottom that shows number of rocks remaining, number of targets left, the score, and a Restart button to Scene 1.
Play a sound when a rock hits a bottle.
For an extra challenge, place a wall in the bottom middle so that the player has to throw over it.
Change to Win screen when all the bottles are broken.
Change to Lose screen when all the rocks are thrown and there are still bottles remaining.





Task 3.3:  Download, execute and study game5.zip.  Change one or more aspects of the game.  Bigger objects have more weight, just as in the real world.  If you substitute a smaller object for the rock, it will be thrown further with the current speed setting.  If you make the rock bigger, the speed setting must be increased to throw it very far.  Observe that a rock bounces off bottles and the wall, and is affected by gravity.

Task 3.4:  Watch, study and code your way through the Khan Academy Lessons Logic and If Statements.  Complete all SIX of the Khan Academy lessons: Scene Management.

Popper Implementation

Step-wise composition is the rule to follow.  After designing a game, I usually define the tables for all the scenes and buttons.  Next, define the variables; in the case of Popper: score, rocks.  The properties targets and totalTargets are added by the software.

Game variables are assigned values as properties of the defs.vars variable e.g. defs.vars.score, etc.  Remember that variable names can be referenced directly in text labels (see button 7).

Targets

The sprite bottles and the wall in the Popper game are targets.  The software implements a number of target placement options.  Since targets are implemented as JavaScript tables, a designer can add additional properties, as long as there are no name conflicts.

If a target is an obstacle, it participates in the physics, but is ignored for scoring purposes.  If a target is not an obstacle, the "hitTarget" function is called on every collision.  The following table lists the target definitions with an explanation.  Remember Rule #1: Copy correct code to write correct code.

target1.wh = [15, 40];
Width,height of target; the mass or weight is proportional to the size.
target1.type = "box"; The physics options are box or circle, the width in wh is a circle's diameter.  Anything can be drawn for a physics object; the type just defines the outer perimeter for collision detection.
target1.static = true; A static body cannot be moved by forces.  If this property were set to false and obstacle to true, bottles would fly around when hit, like pool balls.
target1.categories = 4; If two physics bodies have the same category value, they will collide.  Options are 4, 8, 16, etc.
target1.gravityScale = 0; Causes a body to ignore gravity; that is float in the air.  Omit this property to stack targets on the ground as in Angry Birds.
target1.file = "./assets/sprite.png"; The file path to a body's image (Sprite bottle).
target1.fileSound = "./assets/pop.mp3"; The file path to a sound that can be played in the "hitTarget" function.
target1.score = 50; A property set by the designer to indicate the value of a hit.  Other properties might be health, ammo, money, etc.
target1.frames = [1, 1, [0, 0, 135, 400]]; The image was too large so the frames property, together with wh, were used to adjust the dimensions.


target2.wh = [20, 60];

target2.type = "box";

target2.shape = "rect";
Selects a drawing function, rect, ellipse, point
target2.color = ['sienna'];
Color name.
target2.static = true;
Does not move.
target2.categories = 4;
Collides with other 4s.
target2.gravityScale = 0;
Not affected by gravity.
target2.obstacle = true;
Does not call "hitTarget" on collisions.

Bullets

A Projectile is a Fountain in which the Particles (bullets) are physics bodies.  Firing a bullet is equivalent to a single step of a Fountain with every generated Particle created as a physics body.  Bullets can be fired from any source location and can either be fired at an angle (like a cannon) or can be fired at a target location.

Multiple bullets can be fired in a single shot either singly, in a stream (like a machine gun), or in a spread (like a shotgun).  The "period" property specifies the time (in milliseconds) between shots to simulate the trigger-pull time.  The "load" property determines the number of bullets per shot.  The following table lists the properties of the "rock" projectile.  The Fountain properties are listed first, then the physics properties, then the Projectile properties.

bullet.name = "bullet";
All Fountains have a unique name.
bullet.color = ['white'];
A single color or a list.  Should be white for images.
bullet.shape = "pfill";
Requires a different draw function to sync with the physics engine.
bullet.gravity = 1;
Fraction of gravity that is applied to Particles.
bullet.speed = 180;
Rocks are pretty heavy so they need more force to throw them.
bullet.limit = 99999;
Maximum number of Particles to generate.
bullet.lifetime = 120;
Number of draw calls (about 4 seconds) until the rock disappears.  The rock is not deleted on a collision so that it can bounce around and cause more damage.
bullet.file = "./assets/rock.png";
The rock image was too large so the frames option was used to re-size it.
bullet.wh = [24, 18];
Twenty-four by eighteen pixels.
bullet.frames = [1, 1, [20,120,460,310]];
Crop the image before re-sizing.

Physics Properties
bullet.pshape = "box";
Shape that approximates the perimeter of the object.
bullet.collidesWith ="4";
Collides with the wall and the bottles.

Projectile Properties
bullet.period =1000;
Restrict to one shot per 1000 milliseconds (1 second).
bullet.load = 1;
Only one bullet per shot.

Program Changes

Finally, we detail the program changes in the next table.  We list the functions modified and the code added to each.  The changes are listed in step-wise-composition order.

function startState
defs.vars.score = 0;
defs.vars.rocks = 10;
Add the variables that will be displayed in the infobar.  They must be assigned in the startState function because they are reset every time that the game is played.  The targets and totaltargets variables are initialized automatically.  See the button7 definition.
function setup
defs.targets = {};
defs.targets.bottle = target1;
defs.targets.wall = target2;
Add the target table definitions.
function setup
screen3.targets = [
["bottle","random",15,[80, 80, 450, 280]],
["wall","fixed",1,[240,253]]
];
Define the game's targets.  Targets are generated, placed, and drawn automatically.
Place 15 targets randomly in the rectangle at upper-left-xy 80,80 and which is 450 pixels wide and 280 pixels high.
Place 1 wall centered at x=240, y=253.
function doState
if (mouseIsPressed) {
  defs.buttons.circle.rotation += -1;
  if (defs.buttons.circle.rotation < -90)
     defs.buttons.circle.rotation = 0;
}
Add the code to aim the arrow when the mouse is pressed.  Observe that we are changing the rotation property associated with every button.  The "if" statement is need to prevent the arrow from being aimed backwards, past vertical.
function setup
defs.parts = [bullet];
screen3.bullets = [["bullet", [0, 0]]];
Add the bullet table definitions.  A screen can define multiple Projectile shooters.
The [0,0] values are offsets of the gun ports relative to the point of fire; for example, an airplane with two wing guns.
function doClick
for (var i=0; i<bullets.length; i++) {
   var of = bullets[i];
   of.location.x = defs.buttons.circle.xy[0];
   of.location.y = defs.buttons.circle.xy[1];      
   of.CreateAtAngle(defs.buttons.circle.rotation);
} //for i
defs.buttons.circle.rotation = 0;
defs.vars.rocks--;
The function is called after a mouse press/release.  The global mouseClick variable is set to [mouseX, mouseY].

Set the shot origin to the center of the aiming circle.
Shoot at the angle (in degrees) of the aim.

Reset the aim to zero after each shot just to make the game harrder.
Decrement the number of rocks by one.
function hitTarget(body)
defs.vars.targets--;
defs.vars.score += body.score;
if (body.sound) body.sound.play();
Called on a target bullet collision.
The target is destroyed so decrement the count.
Increase the score by the target's value.
If there is a sound, play it.
function doState
if (defs.vars.targets <= 0)
   changeState(WIN);
else if (defs.vars.rocks <0)
   changeState(LOSE);
Change to WIN or LOSE screens if the game is over.
There was a bug in this code because I tested for rocks <= zero.  However, the count went to zero when the last rock was thrown, not when it left the screen.  Thus, if the last rock broke the last bottles, the user would lose instead of win.

Task 3.5:  Watch the Khan Academy video (2:59) Mouse Interaction.

Task 3.6:  Modify the Popper example to learn about Targets and Projectiles. Try adding a third target with a different sound and score value.  Try substituting the following bullet definition.
    var bullet = {};
    bullet.name = "bullet";
    bullet.color = ['red'];
    bullet.shape = "pfill";
    bullet.pshape = "box";
    bullet.gravity = 1;
    bullet.speed = 10;
    bullet.limit = 99999;
    bullet.lifetime = 120;
    bullet.period =1000;
    bullet.load = 4;
    bullet.size = [4,4];
    bullet.collidesWith ="4";

Bat Swat Game

Game idea
We are flying along as a mountain landscape slowly scrolls from top to bottom.  Bats fly up the screen from the left side to the right side at random intervals and speeds.  Clicking the mouse will drop a bomb, which explodes at soon as it hits the bat.  A nice explosion effect follows.
Scene 1
Splash screen, visual elements are title background image, TapToProceed blinking button, Credits button.  Show a list of the high scores.
Scene 2
Credits screen image with Back button to Scene 1.
Scene 3
Play screen with scrolling background image, 15 bats randomly-generated, which move left to right.
Show the score at the top right.
Play a sound when a bomb explodes.

 




Task 3.7:  Download, execute and study game6.zip.  Change one or more aspects of the game.  Bigger objects have more weight, just as in the real world.  If you substitute a smaller object for the rock, it will be thrown further with the current speed setting.  If you make the rock bigger, the speed setting must be increased to throw it very far.  Observe that a rock bounces off bottles and the wall, and is affected by gravity.

Task 3.8:  Watch, study and code your way through the Khan Academy Lessons Looping.

Bat Swat Implementation

Step-wise composition is the rule to follow.  After designing a game, I usually define the tables for all the scenes and buttons.  Next, define the variables; in the case of Bat: just score.  The properties targets and totalTargets are already added by the software.

Game variables are assigned values as properties of the defs.vars variable e.g. defs.vars.score, etc.  Remember that variable names can be referenced directly in text labels (see buttons 4 and 6).

Targets

 The following table lists the target definition (the bat) with an explanation.  Remember Rule #1: Copy correct code to write correct code.

target1.wh = [30, 46];
Width,height of target; the mass or weight is proportional to the size.
target1.type = "box"; The physics options are box or circle, the width in wh is a circle's diameter.  Anything can be drawn for a physics object; the type just defines the outer perimeter for collision detection.
target1.static = false; Bats fly through the scene.
target1.categories = 4; If two physics bodies have the same category value, they will collide.  Options are 4, 8, 16, etc.
target1.gravityScale = 0; Causes a body to ignore gravity; that is float in the air.  Omit this property to stack targets on the ground as in Angry Birds.
target1.file = "./assets/bat.png"; The file path to a body's image (bat).
target1.fileSound = "./assets/pop.mp3"; The file path to a sound that can be played in the "hitTarget" function.
target1.score = 10; A property set by the designer to indicate the value of a hit.  Other properties might be health, ammo, money, etc.
target1.frames = [5, 500,
[32,48,32,48],[32*2,48,32,48],[32*3,48,32,48],[32*4,48,32,48],[32*5,48,32,48]];
Bats flap their wings by playing 5 animation frames.
target1.fountain = 'red';
fountain1.name = "red";
fountain1.shape = 'image';
fountain1.angle = [0, 360];
fountain1.color = ["white"];
fountain1.limit = 40;
fountain1.lifetime = 140;
fountain1.file = './assets/star1.png';
fountain1.frames = [6, 50,
[0,0,64,64], [64,0,64,64], [64*2,0,64,64],
[0,64,64,64], [64,64,64,64], [64*2,64,64,64],
];
fountain1.wh = [64, 64];
fountain1.size = [1,1];
An animated explosion of 40 stars blowing out in a circular pattern

Bullets

The bullet, or bomb in this case, is a small circle with a diameter of 8 pixels.  It is shot from and at the current mouse location on a mouse click.  Since gravity is turned on, it drops like a rock.

bullet.name = "bullet";
All Fountains have a unique name.
bullet.color = ['red'];
A single color or a list.  Should be white for images.
bullet.shape = "pfill";
Requires a different draw function to sync with the physics engine.
bullet.gravity = 1;
Fraction of gravity that is applied to Particles.
bullet.speed = 1;
Does not need any force.
bullet.limit = 99999;
Maximum number of Particles to generate.
bullet.lifetime = 120;
Number of draw calls (about 4 seconds) until the bullet disappears.  The bullet is deleted on a collision.
bullet.size = [8, 8];
Diameter eight circle.

Physics Properties
bullet.pshape = "circle";
Shape that approximates the perimeter of the object.
bullet.collidesWith ="4";
Collides with the wall and the bottles.

Projectile Properties
bullet.period =1000;
Restrict to one shot per 1000 milliseconds (1 second).
bullet.load = 1;
Only one bullet per shot.

Program Changes

Finally, we detail the program changes in the next table.  We list the functions modified and the code added to each.  The changes are listed in step-wise-composition order.

function startState
defs.vars.score = 0;
Add the variables that will be displayed.  They must be assigned in the startState function because they are reset every time that the game is played.  The targets and totalTargets variables are initialized automatically.
function setup
defs.parts = [bullet, fountain1];
defs.targets = {};
defs.targets.bat = target1;
Add the fountain and target table definitions.
function setup
screen3.targets = [["bat","autoFire",15,4000,
"left",1,-1, 100, 200]];
Define the game's targets.  The Bat Swat game uses a new option "autoFire".  15 "bat" targets are launched one at a time at an interval of 4000 milliseconds (4 seconds).  The direction options are "left", "top", and "right".  The direction change is 1 pixel change in the x direction and -1 pixel change in the y direction per "draw" function call; basically, in a diagonal direction left to right.  The origin of the launch is randomly chosen between y=100 and y=200.
function doState
if (scrollScreen(state, true)) break;
Scroll the mountain scene.
function doClick
var of = bullets[i];
of.location.x = mouseX;
of.location.y = mouseY;
of.Create(mouseX, mouseY);
The function is called after a mouse press/release. 
Fire the bomb from and at the current mouse location.
function hitTarget(body)
bullets[0].Stop();
defs.vars.score += body.score;
doFountain(body);
if (body.sound) body.sound.play();
Called on a target bullet collision.
Destroy the bullet; the target is destroyed automatically.
Increment the score.
Initiate the explosion.
If specified, play the sound.
function doState
if (defs.vars.targets > 15)
      changeState(START);
Change to the start screen if the game is over.


Task 3.9:
  Change the game so that monsters drop from the top of the screen.

Air Ace Game

Game idea
We are not implementing completed games.  Rather, the focus switches to illustrating new implementation options.  In this example, there is a movable hero, an airplane with twin guns, and simultaneous generation of multiple targets.
Scene 1
Splash screen, visual elements are title background image, Play button, Credits button.
Scene 2
Credits screen image.
Scene 3
Play screen with a side-scrolling  background image, randomly-generated ships, which move right to left.
Show the score at the top right.
Move an airplane up and down; click the mouse to shoot.

 




Task 3.10:  Download, execute and study game7.zip.  Change one or more aspects of the game.

Task 3.11:  Watch, study and code your way through the Khan Academy Lessons Object-Oriented Design.

Air Ace Implementation

Step-wise composition is the rule to follow, as always.

Targets

 The following table lists the target definition (the two bullets) with an explanation.  Remember Rule #1: Copy correct code to write correct code.

target1.wh = [70, 70];
target1.type = "box";
target1.static = false;
target1.categories = 4;
target1.gravityScale = 0;
target1.file = "./assets/ships.png";
target1.fileSound = "./assets/pop.mp3";
target1.sound = sound1;
target1.frames = [1, 200, [250,0,70,70]]; //number, ms per frame, x,y,w,h
target1.score = 10;
The big ship is only worth 10 points.


target2.wh = [100, 40];
target2.type = "box";
target2.static = false;
target2.categories = 4;
target2.gravityScale = 0;
target2.file = "./assets/ships.png";
target2.fileSound = "./assets/pop.mp3";
target2.sound = sound1;
target2.frames = [1, 300, [280,110,100,40]]; //number, ms per frame, x,y,w,h
target2.score = 20;

The rocket is harder to hit so it is worth 20 points.

Bullets

The bullet is a small red circle with a diameter of 4 pixels.  It is shot from the current location of the hero (an airplane).

var bullet = {};
bullet.name = "bullet";
bullet.color = ["red"];
bullet.shape = "pfill";
bullet.pshape = "circle";
bullet.gravity = 0;
bullet.speed = 4.5;
bullet.limit = 99999;
bullet.lifetime = 120;
bullet.period =1000;
bullet.load = 1;
bullet.collidesWith ="4";
bullet.size = [4,4];

Program Changes

Finally, we detail the program changes in the next table.  We list the functions modified and the code added to each.  The changes are listed in step-wise-composition order.

function startState
defs.vars.score = 0;
Add the variables that will be displayed.  They must be assigned in the startState function because they are reset every time that the game is played.  The targets and totalTargets variables are initialized automatically.
function setup
defs.parts = [bullet];
defs.targets = {};
defs.targets.ship1 = target1;
defs.targets.ship2 = target2;

Add the target table definitions.
function setup
button4.file = "./assets/plane.png";
button4.xy = [64, 160];
button4Global = button4;

screen3.file = "./assets/gamebg.png";
screen3.buttons = ["plane", "score", "scoretext"];
screen3.scroll = [0, 0.1];  //start X, pixels/ms
//screen3.fileMusic = './assets/endingMusic.m4a';
//screen3.music = music1;
screen3.targets = [
 ["ship1","autoFire",15,4000,"right",-1,0, 100, 240],
 ["ship2","autoFire",15,3000,"right",-1,0, 100, 240]
];
screen3.bullets = [
   ["bullet",[19,-20]],
   ["bullet",[19,20]]
];
The hero (an airplane) is defined as a movable button.  It is assigned to a global variable so that the location can be changed by mouse clicks.








If multiple targets are listed, the software fires multiple objects.  Observe that the velocity is -1, which is a straight line from left to right.



Fires two bullets at once.  The [x,y] positions are offsets from the center of the airplane.
function doState
if (scrollScreen(state, false)) break;
if (mouseIsPressed && mouseX<=128)
      button4Global.xy[1] = mouseY;

Scroll the background image right to left.

Track the airplane to the mouse's Y position, which restricts the motion to vertical.
function doClick
    for (var i=0; i<bullets.length; i++) {
      var of = bullets[i],x=0,y=0;
      if (of.offset) {
        x = of.offset[0];
        y = of.offset[1];
      }
      of.location.x = button4Global.xy[0]+x;
      of.location.y = button4Global.xy[1]+y;
      of.Create(width+30, of.location.y);
    }

The function is called after a mouse press/release. 
Fire dual bullets from the wings at the airplane's current location.
function hitTarget(body)
  for (var i=0; i<bullets.length; i++)
    bullets[i].Stop();
  if (body.sound) body.sound.play();
  doFountain(body);
  defs.vars.score += body.score;

Called on a target bullet collision.
Destroy the bullets; the target is destroyed automatically.
Increment the score.
Initiate the explosion, if listed.
If specified, play the sound.

Task 3.9:
  Change the game so that monsters drop from the top of the screen.

Debugging Program Syntax Errors

Beginning programmers have to learn to pay attention to syntax details by making errors.  I am sure that you have already made a mistake in your code and discovered that the code does not run, which usually results in a blank or frozen screen.  That is not very helpful.

Luckily, many web browsers include JavaScript debuggers.   While in theory a programmer is supposed to keep track of program state (variables and their values); in practice, most of us lose track if there are more than a few variables.  Debuggers support two main features. First, it is very easy to examine program state.  Second, it is possible to set a breakpoint in a program and the to "step" execution by one line at a time.  When program execution reaches a line that is a breakpoint, the debugger halts execution so that the programmer can view the variables and their values.

Given a program's state and a line of code, you should be able to determine the result.  At a breakpoint, you can view the state, then you figure out what the result should be for the current statement, then you step the code one line forward and compare the actual result with your assumption.


FireFox Debugger


  1. Select the Debugger tab next to Console, then click sketch.js under the Sources tab.  Next, click the || icon right above the Sources tab to stop the program.  There are no syntax errors; the program just does not work.  Then, click to the left of line 20 in the blank column to set a breakpoint (a blue circle).  Breakpoints can be removed by just clicking them a second time. Now click the right-pointing triangle above the Sources tab to execute the program.  The program stops at line 20 and highlights with a right-pointing green arrow.
  2. At this point the user has a number of debugging options.
    1. Highlight any global variables or any variables local to the function, hover the mouse, and the value of the variable will be displayed.  If everything looks ok, the breakpoint can be removed.  Click the right-pointing triangle to continue program execution.  There are also three icons above the Sources/CallStack tabs that provide additional execution options.
    2. Click the StepOver icon to execute one statement at a time.  The term "Over" means that if the statement is a function reference, execution will enter the function but will not "break" until control has returned to the next line.
    3. Click the StepInto icon to execute one statement at a time.  The term "Into" means that if the statement is a function reference, execution will enter the function and step to its next line.
    4. The StepOut icon is chosen in situations in which a function has been checked out to be correct but execution has not yet reached the end of the function.  It can be tedious to StepOver multiple statements that are not of interest.  The StepOut option defers the next "break" until the current function has exited.
  3. Click the StepInto icon to trace into the "update" function.  The previous Figure shows that I highlighted the "angle" variable to check its value.
  4. Next, StepOver until line 29 is reached.  The far-right column shows the names and values of all the local variables. Notice that x and y have the value NotANumber, but that cannot be right because width, r and x0 were initialized earlier. Weren't they? Obviously not! These steps illustrate how I found and fixed my error in one of my sketches.