Dec 9, 2011
Posted on Dec 9, 2011 in Hints and Tips | 10 comments
Stop using static menus! Most players immediately base their initial impression of a Flash game on the menu that they see when they load it. Stand out from the crowd with a dynamic menu!
Final Result Preview
Introduction: Static to Dynamic
The word “static” essentially means lacking in change. The majority of menus we see throughout web games are lacking in change, you simply press Play and the game starts. Menus like that are overused and show little creativity or innovation.
To make a menu “dynamic” we must continuously cause change. So in this tutorial that is exactly what we are going to accomplish: a menu that continuously changes.
Step 1: Setting Up
The first thing we are going to need to create is a new Flash File (ActionScript 3.0). Set its width to 650px, its height to 350px, and the frames per second to 60. The background color can be left as white.
Now save the file; you can name it whatever you please, but I named mine menuSlides.fla.
In the next section we will create the nine MovieClips used in the menu. For reference, here is a list of all the colors used throughout the tutorial:
- White – #FFFFFF
- Gold – #E8A317
- Light Gold – #FBB917
- Blue – #1569C7
- Light Blue – #1389FF
- Green – #347235
- Light Green – #3E8F1B
- Red – #990000
- Light Red – #C10202
- Matte Grey – #222222
Step 2: Creating the Slide MovieClips
To start with we will create the slides used in the transitions, but before we begin let’s turn on some very useful Flash features.
Right-Click the stage and select Grid > Show Grid. By default it will create a 10px by 10px grid across the stage. Next, right-click the stage again and this time select Snapping > Snap to Grid.
Now we can begin drawing! Select the Rectangle Tool and draw a Light Gold rectangle, 650px wide and 350px tall (you can Alt-click on the stage to make this easier). Now change the color to Gold and draw groups of three squares, each 20x20px, to form the shape of an L in each corner,:
Select the whole stage, right-click and choose Convert to Symbol. Name the MovieClip goldSlide and make sure that the type is MovieClip and the registration is top-left.
To save time and make things a whole lot easier, right-click the goldSlide MovieClip in the Library and select Duplicate Symbol three times to make three more copies. Change the colors in the new MovieClips to blue, green and red, then rename the MovieClips to blueSlide, greenSlide and redSlide.
Before we continue we should add some text to each slide. On goldSlide write PLAY, on blueSlide write INSTRUCTIONS, on greenSlide write OPTIONS and on redSlide write CREDITS.
Now that we have the text in place we can break it apart by right-clicking on it and selecting Break Apart twice; this will break the text down to a fill which will transition more smoothly. Plus as a bonus there will be no need to embed a font if you are just using it for the menu!
The Buttons
Now that we have drawn the 4 slides we can focus on the sideButton MovieClip that is used to move the slides either left or right.
First, draw a rectangle 30x60px with only a stroke (no fill), then draw diagonal lines 45 degrees from the top-right and bottom-right corners until they snap together in the middle of the opposite side. Now apply a Matte Grey fill to the triangle:
Next, delete the lines, then right-click the triangle and select Convert to Symbol. Name it sideButton, set the type to Button and make sure the registration is in the top-left corner.
Now insert 3 keyframes in the timeline by right-clicking the timeline and selecting Insert Keyframe. On the Up frame, select the fill of the triangle, go to the Windows tab and select Color. Change the Alpha to 50%. On the Over Frame repeat the same process, but this time set the alpha to 75%.
Now we can begin on the four numbered circle buttons, for jumping directly to a particular slide.
To start draw a white 30px circle with no stroke. Convert it to a symbol, name it circleOne, and set its type to Button and its registration point to the center. Insert three keyframes like we did before and then go to the Up frame.
Draw a black 25px circle with no stroke and center it to the middle through the coordinates or by using the Align menu. Next deselect the black circle, then reselect it and delete it. You should now have a white ring remaining. Now grab the text tool and put a white “1″ in the center of the ring. Then break this number apart until it is a fill.
Go to the Over frame and draw a black “1″. Center it and break it apart until it becomes a fill. Now deselect and reselect the fill, then delete it. Select everything on the frame and copy it, then go to the Down frame, select everything on it and hit delete. Paste in what we have copied.
Now create three more circle MovieClips, following the same process, for the numbers 2, 3 and 4.
Step 3: Positioning the MovieClips
Okay, we’re almost half-way done! First drag all of the slides onto the stage and position them with the following coordinates:
- goldSlide: (0, 0)
- blueSlide: (650, 0)
- greenSlide: (1300, 0)
- redSlide: (1950, 0)
Now drag and drop two copies of the sideButton. The first copy should be positioned at (10,145); before we can position the second copy we must first flip it!
Select the second copy and press Ctrl-T. Change the left-right to -100% and leave the up-down at 100%. Now move the second copy to (640,145).
Finally drag and drop the four circle MovieClips and position them as so:
- circleOne: (30, 320)
- circleTwo: (70, 320)
- circleThree: (110, 320)
- circleFour: (150, 320)
Your stage should now look like this:
The blue, green and red slides are hidden just off to the right of the stage. Now select everything on the stage and convert to a symbol. Name it menuSlidesMC, set the type to MovieClip and the registration to the top-left corner, and export it for ActionScript as MenuSlidesMC.
Before we finish we must give each of the MovieClips inside menuSlidesMC an instance name. Select each slide in the order they appear from the left and name them slide1, slide2, slide3 and slide4 respectively. Name the circle buttons one, two, three and four, and finally name the side buttons left and right.
Step 4: Setting Up the Classes
Now that all of our MovieClips have been created we can start setting up the two classes we are going to use.
First go to your Flash file’s Properties and set its class to menuSlides; then, create a new ActionScript 3.0 file and save it as menuSlides.as.
Now copy the following code into it; I will explain it after:
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class menuSlides extends MovieClip{
public var menuSlidesMC:MenuSlidesMC = new MenuSlidesMC();
public function menuSlides(){
addChild(menuSlidesMC);
}
}
}
Pretty basic – it’s a document class, into which we imported the MovieClips and Events we will use. Then we created an instance of MenuSlidesMC, and added it to the stage.
Now create a new ActionScript 3.0 file for the menuSlidesMC instance. Save it as MenuSlidesMC.as and copy the following code into it:
package{
import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
public class MenuSlidesMC extends MovieClip{
public var speed:Number = new Number();
public var activeSlide:Number = new Number();
public function MenuSlidesMC(){
speed = 10;
activeSlide = 1;
addEventListener(MouseEvent.CLICK, slidesClick);
addEventListener(Event.ENTER_FRAME, slidesMove);
}
}
}
Just like last time, we imported what we are going to need, but we created two number variables. The first variable, speed, is actually how many pixels the slides are moved by each frame. (Note: this number has to evenly divide into your stage’s width to give a smooth transition). The second variable, activeSlide, tells us which slide is currently set to be on screen.
We also added two event listeners for functions we are going to create; one of them is called on a mouse click, and the other is called at the beginning of every frame.
Step 5: Creating the Event Handler Functions
To begin we will get the mouse click function out of the way. Start by creating a public function named slidesClick():
public function slidesClick(event:MouseEvent):void {
}
Next we will create some if-statements regarding the event.target.name. Basically, this property stores the name of the object that was targeted by the mouse click. We can use this to check which button is pressed:
if(event.target.name == "left"){
if(activeSlide>1){
activeSlide-=1;
}
}else if(event.target.name == "right"){
if(activeSlide<4){
activeSlide+=1;
}
}
if(event.target.name == "one"){
activeSlide=1;
}else if(event.target.name == "two"){
activeSlide=2;
}if(event.target.name == "three"){
activeSlide=3;
}else if(event.target.name == "four"){
activeSlide=4;
}
The code above goes in the slidesClick() function. The first set of if-statements are for the left and right side buttons; they increase or decrease the value of activeSlide, but never allow the value to become less than 1 or greater than 4 (since we only have four slides). The second set of if-statements are for the circle buttons; instead of just incrementing or decrementing the value of activeSlide they set it to the selected value.
Now let’s begin with the ENTER_FRAME handler function:
public function slidesMove(event:Event):void {
}
Add the slidesMove() function below your slidesClick() function and we’ll start adding some code to it. First, we’ll use a switch to check which slide should be on the screen, based on the value of activeSlide:
switch (activeSlide){
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
}
Now in each case we will create an if/else block that will check that slide’s current x-position, and move all of the slides either left, right, or not at all, depending on where the desired slide currently sits.
The first case looks like this:
if(slide1.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide1.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
Now all we have to do is repeat the same process for the other cases! After you are done your swtich should look like this:
switch (activeSlide){
case 1:
if(slide1.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide1.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
case 2:
if(slide2.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide2.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
case 3:
if(slide3.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide3.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
case 4:
if(slide4.x<0){
slide1.x+=speed;
slide2.x+=speed;
slide3.x+=speed;
slide4.x+=speed;
}else if(slide4.x>0){
slide1.x-=speed;
slide2.x-=speed;
slide3.x-=speed;
slide4.x-=speed;
}
break;
}
And that’s it! We are all finished with the code and the menu should be working great right now.
Conclusion
Thank you for taking the time to read through the tutorial, I hope it was helpful and that you learned a little something about dynamic menus.



View full post on Activetuts+
Dec 3, 2011
Posted on Dec 3, 2011 in Hints and Tips | 10 comments
So far, we’ve got a never-ending stream of enemies that our avatar must avoid; one touch, and it’s game over. But so what? Since there’s no way to track the player’s progress, they have no idea whether they did better in their latest round than they ever did before. In this tutorial, you’ll learn how to keep score, how to display it on the canvas, and how to let the player know when they’ve beaten their own records.
Refresher
In the first and second parts of this tutorial, we’ve covered a number of concepts: drawing images to the canvas, detecting mouse actions, using if and while statements, storing variables in arrays, and the idea of variable scope.
You can download the source files from the series up to this point if you’d like to dive straight in here, though I recommend reading all parts in order.
Our game’s JavaScript file initialises a bunch of variables (including two arrays to store enemy x- and y-coordinates) outside of all functions, so that their contents are available to all functions. It also contains a function called setUpGame() which is run when the player first clicks the canvas; this loads the images, starts listening for any mouse movements, and sets up a “tick” function to be run every 25 milliseconds.
When the mouse is moved, we move the position of the avatar, as stored in two variables – one for the x-coordinate and one for the y-coordinate – but we don’t immediately redraw the avatar’s image at this new location; all redrawing is handled in the tick function.
The tick function does four things:
- There’s a one-in-twenty chance that it’ll add a new enemy by pushing new x- and y-coordinates onto the relevant arrays.
- It increments the y-coordinates of each enemy by looping through that array.
- It redraws the avatar and enemy images according to their current coordinates.
- It checks for a collision between the avatar and each enemy, giving an alert if one occurs.
All clear?
Warm Up Challenge
If it’s been a while since you read the second part of the series (or if you just want to check that you understand what’s going on), have a go at these little exercises. They’re completely optional and separate to the actual tutorial, so I recommend working on a copy of your project rather than the original. You can complete all of these exercises using only information from the series so far.
Easy
Swap the avatar and enemy images around so that the player controls a smiley face that’s avoiding the falling skulls.
(How many different ways can you figure out how to do this? I can think of three, off the top of my head.)
Medium
At the moment, there’s a flat one-in-twenty chance that a new enemy will be created in any given tick. I want you to make it so that there’s a one-in-one chance on the first tick, a one-in-two chance on the second, a one-in-three chance on the third, and so on.
To make this more challenging, do it in reverse: a one-in-1,000 chance on the first tick, a one-in-999 chance on the second, a one-in-998 chance on the third, and so on. (After the thousandth tick, make it a steady one-in-one chance.)
Hard
Rather than waiting for the enemies to appear one by one, have the game start with twenty enemies already on screen.
To make this more challenging, make them spread out around the canvas, and don’t allow them to overlap the avatar or each other.
Keeping Time
What’s the simplest way to measure how well the player is doing this round? The easiest thing I can think of is to keep track of how long it’s been since they hit an enemy. And since hitting an enemy means game over, we only need to keep track of how long they’ve been playing.
To do this, we’ll just create a variable, set it to 0 when the round starts, and increment it every tick. Let’s call this variable ticksSurvived. And think: since we need to access it over and over again, it needs to be defined outside of all the functions, at the top of the JS file:
var enemyYPositions = []; //empty square brackets means new empty array
var enemyXPositions = [];
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
var ticksSurvived = 0;
Now, we’ll give handleTick() yet another task to do: increment ticksSurvived. Put this after the collision detection; after all, if the avatar hits an enemy, it hasn’t actually survived the tick:
function handleTick() {
//...
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy!");
}
currentEnemyNumber = currentEnemyNumber + 1;
}
ticksSurvived = ticksSurvived + 1;
}
To display this, for now, we’ll just alter the alert that appears when the avatar hits an enemy:
function handleTick() {
//...
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy! Ticks survived: " + ticksSurvived);
}
currentEnemyNumber = currentEnemyNumber + 1;
}
ticksSurvived = ticksSurvived + 1;
}
That’s a bit weird; we’ve used the + operator to add a string to a number. We can add another string to the end:
function handleTick() {
//...
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
}
currentEnemyNumber = currentEnemyNumber + 1;
}
ticksSurvived = ticksSurvived + 1;
}
Maybe this doesn’t seem odd to you, but some programming languages hate this. JavaScript doesn’t care. It knows that "some" + "string" equals "somestring", and assumes that you want to treat ticksSurvived as a string in this situation.
(Some things to try out:
12 + 6
"12" + "6"
"12" + 6
12 + "6"
Do they all do what you expect them to do?)
Anyway, let’s give this new code a try.

Click to try it out.
Great!
As before, when you click OK, the alert box appears again, because all it does is pause the ticks rather than actually stopping them. But note that the number in the box increases by one; this is proof that JavaScript doesn’t turn the number into a string permanently; it only uses it as a string for the purposes of adding it to another string.
While we’re on the subject of this alert box: don’t you find it annoying?
Try Again
At the moment, the only way to start a new round is to refresh the page. Let’s make it easier and less irritating to have another go, by making the “OK” button on the alert box reset the game.
Since the alert effectively pauses the game, whatever we put on the line after the alert will run once the player hits OK. Let’s make it call a new function, startNewGame():
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
startNewGame();
}
currentEnemyNumber = currentEnemyNumber + 1;
}
So what do we need startNewGame() to do?
Perhaps we should just call setUpGame() again – but no, nothing in that needs doing twice: we don’t need to load the images or add the mouse event listener or set up the ticks again.
Have a think about what would be needed, and try out your ideas. My solution is below; take a look when you’re ready.
function startNewGame() {
enemyXPositions = [];
enemyYPositions = [];
ticksSurvived = 0;
}
That’s all. You can do more if you wish, but this is the minimum required.
Note that we don’t have to do anything with the canvas – we don’t need to clear it, or draw anything to it, or manipulate the images – because this is all done in handleTick(). We don’t have to go through all the elements in the arrays, one by one, either, because the arrays are simply a list of coordinates that we use to stamp the enemy images onto the canvas; the enemies don’t exist as actual objects.

Click to try it out.
So this is great – the player can play the game over and over again to keep trying for a better score. Except… how do they know whether they’ve beaten their previous score? At the moment, they just have to remember they top score so far, or write it down. We can do better than that.
Remember the Best Score
How should we store the top score? In another variable, of course!
var enemyYPositions = []; //empty square brackets means new empty array
var enemyXPositions = [];
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
var ticksSurvived = 0;
var mostTicksSurvived = 0;
Naturally, it has to live outside of the functions; by now, I’m sure you understand why.
To begin with, we set it to 0, of course – the player hasn’t even completed a round. When the avatar hits an enemy, let’s update the new score as required:
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
if (ticksSurvived > mostTicksSurvived) {
mostTicksSurvived = ticksSurvived;
}
startNewGame();
}
currentEnemyNumber = currentEnemyNumber + 1;
}
Let’s also tell the player that they beat their old high score:
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
if (ticksSurvived > mostTicksSurvived) {
alert("New high score!");
mostTicksSurvived = ticksSurvived;
}
startNewGame();
}
currentEnemyNumber = currentEnemyNumber + 1;
}
Take a look:

Click to try it out.
Excellent. Now let’s give the player a little more information on how much better they did:
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
if (ticksSurvived > mostTicksSurvived) {
alert("You beat your old high score by " + (ticksSurvived - mostTicksSurvived) + " ticks!");
mostTicksSurvived = ticksSurvived;
}
startNewGame();
}
currentEnemyNumber = currentEnemyNumber + 1;
}
Note here that ticksSurvived and mostTicksSurvived are treated as numbers when subtracting one from the other, but the resulting expression (ticksSurvived - mostTicksSurvived) is treated as a string when added to the other strings! This can get really confusing, if you’re not careful.

Click to try it out.
All right, so now the player knows how well they were doing, after they get game over, we should give them an indication of how well they are doing, while they’re still playing.
Drawing the Score to the Canvas
It’s really easy to write text into a canvas – and no, we don’t need to piece it together from different images of different letters!
Remember that to draw an image to the canvas we call canvas.getContext("2d").drawImage(). Writing text is very similar: we call canvas.getContext("2d").fillText().
We must pass three arguments to fillText():
- A string containing the text to write.
- The x-coordinate at which to write it.
- The y-coordinate at which to write it.
There’s an optional fourth argument:
- The maximum width that the text is allowed to take up on screen.
…but we won’t worry about that for now.
To test this out, head to handleTick(), find the line where we draw the avatar to the canvas, and draw a sample line of text just afterwards:
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").fillText("Testing, testing, one, two, three.", 100, 100);
Try it out:

Click to try it out.
Note that, since this gets drawn after the avatar and before the enemies, the enemies get drawn on top of it, while the avatar goes underneath:

Click to try it out.
Like I say, the first argument required is a string, and – as we’ve seen – we can construct a string by adding a string to a number. So, this should work:
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 100, 100);
…and indeed it does!

Click to try it out.
But it’s a bit of a mess, floating there underneath the enemies with that tiny font. Let’s sort that out.
Tidy Up the Text
First, let’s move the text so that the enemies move underneath it. This just means drawing it after all of the enemies are drawn, so move the relevant line down:
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 100, 100);
Now, let’s move it to the top-left of the screen. That’s, (0, 0) so this should work, right?
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 0);
Hmm. Nope. We can’t see the score at all. This is because it’s using (0, 0) to place the bottom-left corner of the text. We need to move the text down a bit, then:
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
Check it out:

Click to try it out.
Okay, so far so good. Now, let’s change the font itself. We do this by setting the canvas’s context’s font property to a CSS string representing the font. If you’re not familiar with CSS, don’t worry; at this stage, all you need to know is that it contains the font’s size and the fontface:
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.getContext("2d").font = "10px Impact";
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
(“px” stands for “pixels”.)
Note that we have to set the font before drawing the text!
Take a look:

Click to try it out.
It works – but the Impact font is really hard to read at that size. Let’s make it bigger:
gameCanvas.getContext("2d").font = "18px Impact";
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);

Click to try it out.
Unfortunately, this doesn’t work so well, because the font is still 10px from the top of the canvas, but now it’s 16px tall!
We could keep changing the y-position of the font to fix this, but there’s an alternative: we’ll make it so that the position we specify determines the top-left corner of the text, rather than the bottom-left corner. It’s easy:
gameCanvas.getContext("2d").font = "18px Impact";
gameCanvas.getContext("2d").textBaseline = "top";
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 10);
Of course, now, there’s a 10px gap between the top of the text and the top of the canvas:

Click to try it out.
…but that’s easy to fix now:
gameCanvas.getContext("2d").font = "18px Impact";
gameCanvas.getContext("2d").textBaseline = "top";
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 0, 0);
Well, actually, I like a bit of padding, so let’s do this:
gameCanvas.getContext("2d").font = "18px Impact";
gameCanvas.getContext("2d").textBaseline = "top";
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);

Click to try it out.
Much better.
Different Fonts
Perhaps you’re wondering whether there’s a list of fonts we can use. Well, yes and no. See, if you pick a font that the player doesn’t have installed on their computer, then the text will just be displayed in the default font. Remember, JavaScript is drawing the text on the fly, using the player’s computer’s resources.
We’re fine using Impact, because it’s installed on every computer – but does that mean we can’t use any font other than the few in this list?
Fortunately, no. We can use any font we like, as long as we give the user access to it somehow. And for this, we’re going to use that CSS file – you know, the one we haven’t touched since the start of the series.
Suppose we have a font called “Really-Awesome”. This will exist on your computer, somewhere, as a file – probably a .TFF file (“True Type Font”). Let’s suppose that file is called ReallyAwesomeFont.ttf.
Now suppose you upload this font to your website – reallyawesomewebsite.com – so that there’s a direct URL to it: http://reallyawesomewebsite.com/fonts/ReallyAwesomeFont.ttf.
You can then let the player’s browser know about it by adding this to your CSS file:
@font-face {
font-family: 'Really-Awesome';
src: url('http://reallyawesomewebsite.com/fonts/ReallyAwesomeFont.ttf');
}
With this line in your CSS, you can alter your code like so:
gameCanvas.getContext("2d").font = "18px Really-Awesome";
gameCanvas.getContext("2d").textBaseline = "top";
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);
…and it’ll work, because their browser will look up the “Really-Awesome” font in the stylesheet, and find the URL to the TTF. Great!
I’m not going to demonstrate this because I don’t own the redistribution rights to any fonts; if I upload some and give you the link to the TTF as part of this tutorial, that’s not really fair. But there is an alternative…
Google Web Fonts
Google has assembled a large collection of fonts that you can use in your project in your CSS, using a similar principle as above. Take a look at the collection.
There are a few criteria by which you can search for fonts, and you can enter some sample text to see how it’ll be displayed:

Google Web Fonts.
I’m going to choose Iceland. When I click Quick Use, it gives me this HTML:
<link href='http://fonts.googleapis.com/css?family=Iceland' rel='stylesheet' type='text/css'>
If you load http://fonts.googleapis.com/css?family=Iceland in your browser, you’ll see that it’s the same kind of thing as we wrote from scratch before:
@media screen {
@font-face {
font-family: 'Iceland';
font-style: normal;
font-weight: 400;
src: local('Iceland'), local('Iceland-Regular'), url('http://themes.googleusercontent.com/static/fonts/iceland/v1/F6LYTZLHrG9BNYXRjU7RSw.woff') format('woff');
}
}
It has a few more details, and the font is in WOFF format rather than TTF, but you get the idea.
You can use whichever font you like (and it doesn’t have to be a Google Web Font), but for the purpose of this tutorial I’m going to assume that you’re using Iceland. So, edit game.html and paste the font reference into it:
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Avoider Game</title>
<script src="js/main.js"></script>
<link rel="stylesheet" href="css/style.css" />
<link href='http://fonts.googleapis.com/css?family=Iceland' rel='stylesheet' type='text/css'>
</head>
<body>
<canvas id="gameCanvas" onclick="setUpGame();" width="400" height="300"></canvas>
<p>Click inside the box to play. Warning: extremely basic!</p>
<p>Make sure you have <a href="http://google.com/chrome/" rel="external">Chrome</a>.</p>
<p>From <a href="http://active.tutsplus.com/tutorials/html5/html5-avoider-game-tutorial-keeping-score">HTML5 Avoider Game Tutorial: Keeping Score</a>.</p>
</body>
</html>
Now, back in main.js, change the font from Impact to Iceland:
gameCanvas.getContext("2d").font = "18px Iceland";
gameCanvas.getContext("2d").textBaseline = "top";
gameCanvas.getContext("2d").fillText("Score: " + ticksSurvived, 5, 5);
Take a look:

Click to try it out.
Cool!
Challenge: Show the Best Score
Now that the current score is on screen at all times, it’s only natural that the player will want to see what they’re trying to beat.
Using what you’ve learnt, draw their best score at the top-right of the canvas. This is a little trickier than it seems: you’ll have to decide what to do (if anything) when the current score overtakes the current top score!
Saving Scores Between Sessions
You’ve probably noticed by now that the high score is reset when you reload the page. This makes sense – after all, we run this line right at the start:
var mostTicksSurvived = 0;
…but even without that line, the high score still wouldn’t persist. All variables get reset and unassigned when you leave the page.
However, there is an alternative: every browser sets aside 5MB of storage for each web site domain. You can store any string you like in this 5MB storage, and it’ll stay there even if the user closes their browser and restarts their computer.
It’s called local storage, and it’s really easy to use! To save something to it, you just need to give it two strings:
- a name for the item, and
- the value of the item.
To retrieve it, you just need the name that you originally used.
A Quick Example
Here’s a quick example: let’s add something to the local storage right at the start of the setUpGame() function:
function setUpGame() {
localStorage.setItem("exampleItem", "This is a great example.");
Save the file, and load your game. Then close the tab.
Now, edit your JS file again, delete the line you just added, and replace it with a line that should retrieve the item:
function setUpGame() {
alert(localStorage.getItem("exampleItem"));
So, just to be clear, there is now nothing in the code that sets the value of "exampleItem".
When you load the game this time, you should see an alert with "This is a great example." – proof that the string has been saved between sessions.
We can remove this item from the local storage using localStorage.removeItem():
function setUpGame() {
localStorage.removeItem("exampleItem");
I recommend you do this now, and then delete the line entirely.
You can also clear everything in the local storage at once, using localStorage.clear() (no arguments required). Okay – not quite everything. Your page can only affect the local storage space assigned to the domain on which it is hosted; I can’t clear your local storage for google.com from a page hosted at tutsplus.com, and vice-versa.
Saving the Best Score
Now that we’ve seen an example, let’s put it into practice.
Whenever a new high score is set, let’s save it to the local storage. It only gets set in one place: when the avatar collides with an enemy and the current score is higher than the best score. So, add the call to localStorage.setItem() in the appropriate place:
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy! You survived " + ticksSurvived + " ticks.");
if (ticksSurvived > mostTicksSurvived) {
alert("You beat your old high score by " + (ticksSurvived - mostTicksSurvived) + " ticks!");
mostTicksSurvived = ticksSurvived;
localStorage.setItem("bestScore", mostTicksSurvived);
}
startNewGame();
}
currentEnemyNumber = currentEnemyNumber + 1;
}
When the page is first loaded, we should check to see whether there already is a high score saved in the local storage, and assign mostTicksSurvived to that value, if so. (You don’t need to repeat this check once the page is loaded, unless you’re worried about the user playing the game in two separate tabs at once.)
How do we check whether a value exists? All we have to do is put it inside an if condition:
if (localStorage.getItem("thisItemDoesNotExist")) {
alert("This alert will never appear!");
}
The alert() above never gets called because localStorage.getItem("thisItemDoesNotExist") does not exist. Easy, right? So at the start of setUpGame(), we can just write:
function setUpGame() {
if (localStorage.getItem("bestScore")) {
mostTicksSurvived = localStorage.getItem("bestScore");
}
Have a go. Load the page, set a high score, then beat it. Reload the page, then get a lower score – does it tell you you beat your old score?

Click to try it out.
Great! By the way, if you took the challenge earlier then you’ll be able to see your previous best score in the top-right corner of the canvas, and this will now carry over from session to session.
Sidenote: Strong and Weak Typing
We’re about done for this part of the series, but I just want to point out that, once again, we’ve been treating a string as a number and a number as a string: local storage only saves string values, yet we save a number to it when we save the best score, and use the value we retrieve from it as a number later on.
This is acceptable, because JavaScript is what’s called “weakly-typed”. Other programming languages are “strongly-typed”, which means that if you say that something is a number, then it stays a number; if you say something is a string, then it stays a string.
In a strongly-typed language, if you want to add the string "Score: " to the number 32, then you have to explicitly tell the language to treat 32 as a string, perhaps like so:
"Score: " + (32 as String)
Also, in a strongly-typed language, when you define a variable, you also specify what type it is:
var greeting:String = "Hello.";
var score:Number = 1000;
But JavaScript doesn’t worry about these things. This doesn’t make it better or worse than a strongly-typed language, just different.
Wrapping Up
That’s it for this part of the tutorial. Now your game has both a game over condition and a means of keeping score. Plus, you learned about drawing text to a canvas, choosing fonts, and using the local storage.
If you’d like to challenge yourself before the next part, have a go at making these changes:
- Easy: Draw the best score on the canvas, before the player clicks it.
- Medium: Store the player’s top five scores.
- Hard: Save the positions of all the enemies to local storage, and restore them in the next session (you may have to do extra research here! Hint: look into JSON.)
Enjoy!



View full post on Activetuts+
Nov 23, 2011
Posted on Nov 23, 2011 in Hints and Tips | 10 comments
The shell game is a cliché of street corners in black and white movies and modern cities: the hustler puts a pea under one of three shells, and swaps the shells around rapidly, challenging you to pick the shell with the pea underneath. The punter will typically get it correct… right up to the point where big money is at stake, or when the punter isn’t one of the hustler’s cronies.
In this tutorial, exclusive to Premium members, you’ll learn how to create your own version of the shell game – except without the cheating!
Preview
Let’s take a look at the final result we will be working towards:
The tutorial covers both the design and the coding of the game, and uses TweenMax to make the shells move along a curved path.
We run a Premium membership system which periodically gives members access to extra tutorials, like this one! You’ll also get access to Psd Premium, Vector Premium, Audio Premium, Net Premium, Ae Premium, Cg Premium, Photo Premium, and the new Mobile Premium too. If you’re a Premium member, you can log in and download the tutorial. If you’re not a member, you can of course join today!
Also, don’t forget to follow @envatoactive on twitter and grab the Activetuts+ RSS Feed to stay up to date with the latest tutorials and articles.



View full post on Activetuts+
Nov 11, 2011
Posted on Nov 11, 2011 in Hints and Tips | 10 comments
Have you ever dived right in to developing a game, but found yourself having to constantly change aspects of the design or the gameplay due to a lack of planning? You should consider using a game design document: a guiding vision of the game as a whole, pulling together ideas and plans for the design, development, and business sides of your game.
Introduction
To put it simply: we like to tell stories. Some true, some not so much. But the point is that we have been crafting tales for a very long time, and as time went by these tales began to evolve, becoming more complex, with richer details, with more and more fantastic backgrounds and appealing plots. Whole new worlds were born from thin air, hammered into shape in the anvils of the human brain.
And as the stories grew in complexity, so did the tools used in their making. Art diverged into several different categories, music became more elaborated and movies found their way into the world. Technological enhancements allowed sharing of information, spreading art all around the globe. New fantasy worlds were created each day. Worlds so rich made people began to desire becoming a part of them. A new concept was being brought to life.
Although video games were first just about getting the highest score possible when faced with a determined task, developers soon realized the endless possibilities laying ahead of them. Playing a video game is more than simply sitting through another story. For the first time one could have a say in how the tale told itself. Players could take hold of characters and live the hardships of the journey themselves, diving into that particular world and mastering it, making theirs the protagonist’s conquests and failures.
A game has the potential to bond player and story in a way never seen before. This connection can be established in a variety of ways. Be it the fantastic landscapes in which the story unravels, the soundtracks or the well-constructed personality of a particular character. It forces the player to thrive in order to see more of what he wants.
Unfortunately, since a game is composed of so many different elements, different experts from different areas are required in its creation, making the coordination of the development process a rather tricky job. In order to help developers do their job, a document known as a GDD, or Game Design Document, is often employed.
A GDD is a tool that helps merging the components of a game together. It registers the general ideas of every aspect of it, from graphics design to story line. In short it registers the game concept, creating the closer feeling of the finished product.
Although the writing of a GDD is not a vital part of the creation process, it is of major help to the team of developers, especially when in major projects, involving large amounts of personnel. Also, there is not only one way of writing a GDD. In fact, GDDs differ vastly among game development companies, but as a general rule, most games are built around these documents.
So without further ado, here is what you need to know about this important tool.
Overview
A Game Design Document must teach everyone who reads it how the game that you’re talking about works. In order to do this, you need to explain not just the mechanics, but also how the game’s objects (characters, enemies, puzzles, weapons, environment, and so on) interact with each other, what your game is about, and how it looks. In a GDD, these points are discussed in some general sections.
Marketing
Marketing is a big section subdivided in many subsections that explain the major commercial aspects of the game, like public target, deadlines, competitors and selling points. This section is very helpful for business, since it shows what your game has in advantage over others and how it meets the consumer demand. In others words, it shows the game’s appeal.
High Concept
Before you start to tell the reader how your game works, you must clarify the core concept of your game, i.e., you must talk about the major aspects of your game in a very short way, so that the reader can anticipate what will be said in the GDD and pay attention to what is important to the game. For this, there is the High Concept section, which explains all of it, so that the reader won’t have to read many pages of the document just to know what your game is about.
For example: if you tell the reader that your project is a futuristic space shooter game, he will be able to imagine what kind of weapons, movements, enemies and others things will be used in the game.
Gameplay
This section is one of the most important in the GDD, because it explains how to control the objects in the game and how to make them interact with the other parts. Also, it explains how the player will execute the possible moves. Moreover, it’s interesting to comment the way that the game flows and what happens during the course of the game.
First Minutes
This is a subsection of the Gameplay section, and it exposes what the player will see in the game when it has just finished loading. It exposes the actions and reactions between the game and the players during this interval, helping understand the game’s progress throughout the gameplay and give a better idea of how to play it. It’s also an important subsection, since it will determine whether or not the game is fun.
Gameflow
This is a more detailed subsection of the Gameplay than the First Minutes. It describes all the options that the player can choose while he is playing. It’s a kind of flowchart that shows which reaction each option has, giving a picture of the game as a whole. Generally it shows a flow of screens (e.g. from the “Main menu” screen it goes to the “Select level” screen), but you can also put actions and consequences in it (e.g. if the player chooses the “Mage” character, all the backgrounds will have a “magical” feeling). It literally explains the way that the game flows, as the name suggests.
Victory Conditions
You also need to teach the reader in the Victory Conditions subsection, what must be done to win, when the player loses and under which conditions this happens. In other words, this section explains the goals of the game.
Number of Players
It’s important to specify how many people can play, because this implies the type of multiplayer – where applicable – that the game will support; for example: split-screen, LAN connections, Internet connections. Note: this section has influence over the Victory Conditions, since the players will need to do different things to win in a competition than in a cooperative game.
Art
Once you explained how to play your game, it’s import to show how your game will look like and which kind of art is behind it, since it’ll influence how the elements of your game’s universe will coexist, mixing the emotions of who is playing. This is a crucial point in the game’s marketing, because it shows the appearance of the game and the feelings it will pass to the player.
Technical Aspects
Another section that must be put in a GDD is the Technical aspects, since it defines the physical game requirements needed to play and specifies on which platforms the game will be developed, which engines will be used, and more. This affects the Marketing, as the kind of hardware used affects both the fanbase and the public target, i.e., the people who consume the game.
Is There a Formula?
All things said, you need to keep in mind that even if some general subsections are common between the GDDs, there is no static form to make this kind of document, and no such thing as a perfect formula. Every game designer has his own way to do this and you must discover yours. This is a hard job, but in this article we’ll give some tips explaining how to create each subsection of the GDD – however, it’s up to you to decide which of them are necessary to design your game.
Always be clear and concise in your text and use a lot of images, because they give the reader a faster and more real view about the game’s final result and they also ease the explanation about puzzles (if your game has them) and how characters, environment, monsters, screens, weapons and other objects from the game will work.
Moreover, you can also find new topics to add in your GDD, as long as it’s necessary to the understanding of the game’s core. Some things that deserve attention are the innovations and the particularities of your game. For example, if your game project brings up a new way of playing, or a specific graphic concept or if it’s focused in music (like a music game), you should discuss it in the document, to convince everyone why this innovation is a good idea.
Guidelines
A good way to start your Game Design Document is with the Marketing section, because it will be the section that your investor or client is interested in, thus allowing them to gain interest in your game faster. In indie game development, it is not a common section due to the common lack of investors, however, if you think in other projects not related to commercial purposes, such as a free game on App Store of Apple to help a charity institution, it’s important to keep track of plans related to the marketing aspect, since it will be really important to have a publishing plan.
After this, it’s important to put the High Concept, so the reader immediately will understand the core of the game and pay attention in the major aspects. You will figure out that in GDDs it’s common to always start with a basic and summarized definition of the game, and go on to present every detail step-by-step.
In the next section you should write about the Gameplay, which should include, as sub-sections, the First Minutes, the Game Flow, the Victory Conditions and Number of Players.
After that, you need to show how your game will look, so talk about the Art, using as many images as you can. In the end, you can talk about the Specific Sections, which should bring topics that explain: the innovations, the aspects that not necessarily all games have, like story, artificial intelligence, characters and others particulars things.
All the things said above are represented in the flowchart bellow, but it’s just a general schema and you can (and should) adapt to your game. Remember: there isn’t a perfect formula. Now that you have a kind of skeleton of the GDD, you will find in the Composition topic of this tutorial a more detailed explanation about what which section of a GDD holds.
Composition
Although there isn’t such a thing as a perfect formula for composing your GDD sections, it’s important for you to include some crucial topics in it, as well as avoid some major mistakes. This section teaches you how to detail the sections presented in the Overview topic, while showing examples of how it’s done and some common mistakes.
The Marketing Section
There is no correct way of dealing with this subject, since your objectives for it will depend on your game. It’s also not really needed; you can either concatenate it all in a major subsection or spread it across the document, as some of the topics discussed here have much in common with others elsewhere. Despite the way you choose to do it, some topics should always be addressed:
Target Audience
Who will play it? This is no ordinary section, so don’t settle for a simple “for children” description, for example. There are endless ways to “classify” gamers, and you must explore this. Comment on how it will appeal to each category and try not to leave anyone out; they might share little in common with your product, but they still share something.
Right:
Turret Defense will appeal to male gamers of ages 15 – 25 who typically play FPS and RTS PC titles. In particular, fans of Sci-Fi themed games, movies, and books will be immediately attracted to Turret Defense’s space adventure setting and theme.
Turret Defense will have an ESRB rating of T (Teen) for ESRB Content Descriptor of Violence, suitable for ages 13 or older. To conform to the wishes of the publisher, Turret Defense will not use blood or any other content that would lead to further ESRB Content Descriptors related to violence.
Wrong:
Turret Defense will appeal to a large audience. Based on the experience of similar games, it should be a huge financial success in the video games market. We plan to advertise it heavily with ads on games-related websites with huge traffic.
(“A large audience” isn’t a valid fanbase, and it doesn’t explain why they would enjoy it. No mention of the ERSB rating or whether the game has any age-restricted material.)
Another good example:
OrBlitz is expected to receive an ESRB rating of Everyone. The main target market will be puzzle games fans, but the game’s many original aspects will attract a wider audience, including people that prefer to buy action-based games. Real time strategy games fans could also be interested in the game for its tweakability and other similarities with RTS games. Because of the lack of graphic violence and the intuitive interfaces, this game can target women as well as men. The game is relatively cute and colorful, and is expected to appeal to both American and Japanese audiences due to the content in it.
Notice all the classifications in the example: gender, age, nationality and genre. Keep in mind that many more categories may arise depending on your game. Predictions on the ESRB rating are also welcomed, therefore some restrictions regarding violence, sexual content and language should be addressed if needed.
Platform
Extremely straight-forward section. Just enumerate the platforms that your game is being designed for. An estimate of the system requirements are also a good call. If needed, you can comment on porting the game and the difficulties involved.
Competitors
This is a key subsection of your document. In here you must compare your game to others already developed. It is important to give a small description of the game being compared to, and point the similarities between both. This is an excellent opportunity to expand the comparisons that were already made across the GDD and give the reader a better picture of what the game will actually be.
At the end summarise your product’s strong points and convince the reader why would your product sell despite its competitors. This is the trickiest part, because you must pick good opponents, otherwise the reader just won’t know what you are talking about, and still keep your game’s image shining; therefore a good writing is crucial. Your ‘adversaries’ also help on the notion of how big your market can be.
Milestone Schedule
The Milestone Schedule subsection is where you must define each necessary steps in order to develop the game, which is basically a timeline of the intended completion of phases of your game. Through that, not only you, but also the investors, can have a very rough estimate of the interval of time needed to complete the project.
Other Subsections
You may choose to add some heavy market-related topics such as Costs Overview, that can comprehend equipment costs, people costs, additional costs and expected profit.
Future Plans
Sometimes there are so many ideas to complement a game that some of it must be put aside in order to meet the tight schedule of development. This section is specifically made to store those ideas, so that you can work on it later depending on how things work out. DLCs, possible sequels, minor improvements to gameplay, graphics and so on, all comes in here. You can also gather some ideas of what to do with the game once it is finished.
Example:
- Add some side quests.
- Enable the character to jump.
- Make a movie telling your story as a developer.
The Introduction Section
The introduction section should provide the reader with a basic overview of the game itself, first with a light approach with the High Concept subsection and then with a broader one within the Summary subsection. You can also highlight the more innovative aspects of your game in a Key Features subsection.
High Concept
A one paragraph description of what your game is about. This should sound like the summary of a summary. Avoid any technical aspects, graphic or sound designs, complex gameplay features, or marketing details that aren’t strictly required (for example, if you’re making a rhythm game you should mention what kind of music style you will be using, whereas if your game is a puzzle you can just forget about music for now; it’s better to describe what type of puzzle the player will have to solve instead). The idea is to describe your game in the most non-technical and shortest way. A good tip is to use well-known games as examples for comparison, such as “X is a three-dimensional racing game with power-ups like Mario Kart”.
Right:
Scavenger Hunt is a three-dimensional arcade-style game where players race to collect items from a list before their opponents do.
Wrong:
Scavenger Hunt is a three-dimensional arcade game with puzzle elements set in a fictional neighborhood in the 50′s with cartoony graphics and music, where the player races to collect various home-related items from a given list in each stage, while using gags as powerups, before his opponents, which can be either CPU-controlled when in singleplayer mode or human-controlled players in multiplayer mode.
(Keep it short and simple)
Summary Overview
A more detailed description of your game, with less restrictions than the High Concept subsection. Start with the core aspects of the gameplay, describing what role the player will take, what’s his goal, what he will have to do in order to accomplish it, what will hold him back and why the game will be entertaining.
Next, do a quick introduction to the game’s setting and a brief description of the history (if any). It’s always nice to use an image instead of describing what the graphics will look like, so if you don’t have any sketches or conceptual art you should just paste pictures with similar art to what you will be using (that includes screenshots of other games as well!).
Key Features
The best way to compose this is using short topics (i.e. bullet lists) instead of long paragraphs. Basically you should tell the reader right away about all of the creative ideas you had which you thought would make your game a great game.
Right:
– Simple yet powerful physics that provides surprising results from a set of simple rules.
– Amazing Hatched and Cel-Shaded graphics.
– Never seen before paint system where color spreads out to the world as the gameplay picks up speed to a frantic pace.
– Powerful land crafting abilities that allow you to build complex paths the orbs can take, like tunnels and bridges.
– Various game modes and scenarios to choose from, each of which feels like a totally different game, favoring action or reflection.
Wrong:
The game will have simple yet powerful physics that provides surprising results from a set of simple rules, while using amazing Hatched and Cel-Shaded graphics and a never seen before paint system where color spreads out to the world as the gameplay picks up speed to a frantic pace, when players build complex paths by using powerful land crafting abilities which the orbs can take, in various game modes and scenarios.
(Too many ideas at once makes the reader lose the train of thought.)
Third-Party Software Used
A little explanation of the programming languages, libraries and software you will be using to create your game, as well as the programs you will use to adjust your graphics and sound engines and any other engines your game may need (like a networking one for multiplayer games).
If you’re under some heavy software/hardware restrictions, you should specify that in here (i.e. if you’re making a game for Apple devices, you have to tell you’ll be using iOS-compatible technology). Also if your game is aimed at PCs and you have an idea what the minimum requirements will be you should note them here. Although the non-programming people of the project probably won’t understand what the heck a “NVIDIA Cg 1.2.1” is, they’ll have to know it by name since that’s what the game will run on.
The Gameplay Section
This section is designed to describe how the game will effectively work, describing the game’s objective as well as its elements (menus, victory conditions, enemies, powerups, stages, …), and the interaction between each one of these elements with the player. If you feel like one subsection, such as “Enemies”, has too much content to be just a subsection you may promote it to a section of its own.
First Minute
It’s interesting for you to describe what the player’s reaction is going to be like as soon as the game loads, such as describing whether he can start playing right away or if he can navigate through menus to change some options beforehand, whether the player will have to learn the controls by trial and error or a tutorial will be presented to him, whether all stages will be available at the get-go or if he will have to unlock them in progression, and so on. Given you have already planned some stages ahead, you could narrate a short run of the player clearing a stage, describing the enemies and/or puzzles he had to go through in said stage.
Right:
After the title screen the player is presented with a list of games he can join and an option to create a new one. After selecting the option to create a new game a list of predefined levels appears on the right of the screen. (…) After the settings are adjusted three other players join and the game begins. A timer counts down from five while the players get ready, using the small amount of money they start with to place a few blocks. As a simple beat plays in the background, the board rotates around the middle of the screen, revealing the layout of the level. (…) The player’s goals are on each corner of the board. (…) As soon as the count down reaches zero, ‘Go!’ is displayed in the middle of the screen and the orbs start falling from the cloud, creating havoc on their path. (…) The player quickly places a stone corner block on the edge of the level and the orb bounces off it, only to end up in the player’s goal followed by a familiar cashier sound. The player’s score and cash are updated to 200, and he starts going through the blocks he can now place (…).
Wrong:
The game begins with the players facing each other in opposite corners. Player 1 decides to use all his money from the get-go and wins the game by using well-placed stone blocks to earn points.
(Although being essentially how the game will run, it needs more details.)
Gameflow
A nice complement to the “First minute” would be the “Game Flow”, which is usually represented as a flowchart. In contrast to the previous subsection, this one won’t focus on the first impression but rather give an overview of the whole picture, showing step-by-step which actions the player can take from the moment the game is loaded to when the player hits the “exit button” – i.e., ends his gaming session – including the gameplay itself in a somewhat high concept.
Right:
(Example from Drexel Game Design’s Scavenger Hunt GDD.)
Wrong:
(Nothing THIS simple. Include, at least, all the screens that the player will run through!)
Victory Conditions
Here you state what is required for the player to clear a stage, win a match, or advance another level, whether your game is a puzzle, where the player advances to the next level when all pieces are combined in a certain way, or a sidescrolling shooter where the player advances a stage when he defeats the boss at the end, or whatever. Obviously, this depends entirely on what kind of game you’re designing.
Example:
In Space Invaders, the player advances to a new wave each time he destroys all enemies from the current wave. Since the waves are endless, the game will keep going until the player runs out of lives.
Graphics
You can’t really provide the reader with screenshots or video footage of something you may haven’t even designed yet, so in this subsection you should simply describe how do you plan to handle your graphical engine and maybe show some sketches of your game or a few drawings in the art style you intend to use. Planning the game HUD from the beginning will save you a lot of time later on, for example.
HUDs
The head-up-display is the in-game interface the player will have when playing the game. Rather than in-game menus like settings or inventory screens, this refers specifically to the floating windows and bars which don’t normally interact with the game and serve a information-only purpose. This includes health bars, mini-maps, time counters, equipped items and their amounts, money and etc. Although the size of the HUD will vary according to the game type (MMORPGs and RTSs will have big HUDs while sidescrollers and puzzles will have very small ones) keep in mind that a HUD shouldn’t occupy too much of the screen.
Example:
Sounds
On the other hand, one cannot sketch sounds, so you’ll just have to detail your sound engine here, and maybe the style of songs your game will use. Although for most games you will simply state that there will be different background music for different situations, it goes without saying that this subsection is most important for a rhythm game.
Controls
Stating which buttons/keys do what can be troublesome in the case where a single button does more than one action (i.e. The ‘A’ button in any 3D Zelda). Start by putting a simple picture of a controller or a keyboard with each button highlighted with their function in a more general sense. After that, if your game has advanced combos or something similar to that, explain them carefully, stating under which conditions each combo is “activated”.
Example:
(Image from CrunchTime Games Inc’s Shred Nedbula document.)
Game-Specific Subsections
Puzzles could have a “Pieces” subsection, sidescrollers will probably have a “Level Design” one, space shooters may have “Enemies” and so on. As the title in bold above says, each game will have their own specific subsections, and since we can’t compose a subsection for all the possible ones that one GDD can have, we will provide you with the three bold subsections presented here as examples.
Pieces
Suppose we have a puzzle game, where the player rotates different pieces in order to create a line of matching pieces to gain points. This would be a nice subsection to show some sketches of the many different types of pieces, as well as explaining their rotation pattern, stating their points value, and maybe describe their positioning placement. Pictures are welcome as always!
Example:
(Image from Colin Fahey’s Tetris article.)
Level Design
Now let’s pretend we have a typical 2D platformer. One of the core elements of the game is the stages the player has to go through. It’s important that each stage feels unique so the player won’t feel like he’s just repeating the same thing over and over again. On the other hand, the player should still be familiar with the flow of the stage, i.e. if there’s always a checkpoint somewhere halfway through it, or some collectible items along the way.
What are the different types of enemies, terrains, doodads and power ups and do they allow the level designers to come with many different stages? You could present some beta stage diagrams to illustrate how will they be carried out.
Example:
(Map from Super Metroid; image from jansenprice.com.)
Enemies
It’s very popular for space shooters to have many kinds of enemies, each one with different attacks and movement patterns, as well as different values for health, speed and targetable area. As such, it’s no surprise you would need an extra section to present all the game’s foes and their stats. Also, you could state some of their more obscure behaviour like shooting an extra beam when their health is low and so on.
Example:
(Image from CrunchTime Games Inc’s Shred Nedbula document.)
Plot
Many games are set in fictional worlds, each with their own geography, history and characters, in which the player will undoubtedly play a large role as the protagonist. If your game has a particularly interesting setting, it would be interesting to include a little insight on the game’s storyboard, describing the protagonist’s main events during his adventures and details about the lore.
Characters
Lots of games aren’t made of enemies alone. There may be a protagonist and allies to help him overcome his foes. For example, even a tower-defense game without a controlled character can still have side-characters like a tutorial-NPC giving you tips on how to overcome certain challenges at the beginning of each stage. If you do have a protagonist that the player controls, then what’s he like? Does he have any abilities and powers? Keep in mind that this shouldn’t feel like a “How to Play” subsection.
Artificial Intelligence
Any game will need a persisting world to handle all the player’s actions to the game and the other way around. That includes enemy movements, player controls, collision handling, time counting, random number generators and many other things one could need in a game. Although people not directly related to the programming may not understand this subsection entirely, they should at least grasp the basic of it. Most of all, keep the coding out of here and simply state the enemies’ moving patterns, the chain puzzle piece falling algorithm, maybe illustrate the combat system with a flowchart and so on.
Example:
The characters on the board will escape the orbs using simple pathfinding / flocking algorithms. Every level will use up to three different script files to issue commands to the animated characters. (…) Player bots will be used to simulate real players. This will allow any level to be played even if there are more goals than players. The decision process that the A.I. system is trying to solve is this:
– Should I place a new block? If so:
– Where do I place the block?
– What type / material should the block be?
Technical Aspects Section
The technical aspects consist of a series of game data, such as the system requirements on which it will play and the framework in which it was developed, the method or algorithm it was based on, and the maximum number of elements that can be rendered on screen. The graphical technical aspects consists of software used, modeling type, art style and others according to these topics.
The system requirements are the necessary computer settings for the game to be played, like the size it occupies on the computer’s HD and how much RAM is needed.
Another important technical aspect not to forget is the ESRB (Entertainment Software Rating Board) rating (or similar), already explained earlier. Some of the ratings are shown below.
To Include or Not to Include? When? Why?
Technical aspects interest the companies that will distribute it or that will use the technology developed in the game, so always add something in it if you’re showing this to someone that will approve or disapprove the game. There has to be some care when writing technical aspects. You can write something in the wrong subject. For example: limiting the platform and distribution game mode belongs to Marketing Aspects, not to Technical Aspects.
More Examples
For professional examples of Design Documents provided by the developers, we have: Shred Nebula, Play With Fire, Grim Fandango Puzzle Document, and many more avaliable at gamepitches.com.
For more material about the structure and composition of a GDD, one could try the featured Gamasutra article The Anatomy of a Design Document, Part 1 and Part 2; the self explanatory Creating a Great Design Document; and a more general How to write an effective Design Document, which isn’t about GDD, but about software development.
More on Game Design: The Two C’s of Video Game Design.
Moreover, there are other visions of how should documentation be done in the Game Industry, as seen in Game Design Logs and Return of the GDD. Although they seem to contradict what had been told here, this should fall in a case-by-case analysis considering team size, budget and deadlines.
Conclusion
For designers who need the approval of an investor: truth be told, before you can make any progress with an investor, you must first get his attention, and to do so, the following key points of your document must be in excellent shape.
High concept: you never get a second chance to make a first impression, and here is where you will make it. We have already given you the tools to make this section, now just remember to give its construction a high priority and point everything that makes your game more appealing here.
Pictures: do not be fooled that the reader will always go through your entire GDD, there are some documents that surpass a thousand pages (yes, this is true!). But he will surely take a better look if something catches his attention, and what better way of doing so than with pictures? After all, one image is worth a thousand words.
It goes without saying that your document must have a great appearance. Take your time to make everything readable and nice. Also, don’t forget that this article only presented a skeleton structure of a GDD for you; you will have to adapt it to your own game!



View full post on Activetuts+
Oct 30, 2011
Posted on Oct 30, 2011 in Hints and Tips | 10 comments
In the first part of this series, you learned the basics of using JavaScript and the canvas element to make a very simple HTML5 avoider game. But it’s too simple – the single enemy doesn’t even move – there’s no challenge! In this tutorial, you’ll learn how to create a never-ending stream of enemies, all falling from the top of the screen.
Refresher
In the first part of the tutorial we covered quite a few concepts: drawing images to the screen, interacting between HTML and JavaScript, detecting mouse actions, and the if statement. You can download the source files here if you want to dive in to this part of the tutorial, though I recommend reading all parts in order.
Our game’s HTML page contains a canvas element, which triggers a JavaScript function called drawAvatar() when it is clicked. That function is inside a separate file called main.js, and it does two things:
- Draws a copy of
avatar.png to the canvas.
- Sets up an event listener to call another function, called
redrawAvatar(), whenever the mouse moves over the canvas.
The redrawAvatar() function is also inside main.js; unlike drawAvatar() it accepts a parameter – called mouseEvent – which is automatically passed to it by the event listener. This mouseEvent contains information about the mouse’s position. The function does four things:
- Clears the canvas.
- Draws a copy of
avatar.png to the canvas, at the mouse’s position.
- Draws a copy of
enemy.png to the canvas, at a specified position.
- Checks to see whether the avatar and enemy are close enough to each other to be overlapping, and displays an
alert() if so.
All clear? If not, try the warm up challenge.
Warm Up Challenge
If it’s been a while since you read the first part of the series (or if you just want to check that you understand what’s going on), have a go at these little exercises. They’re completely optional and separate to the actual tutorial, so I recommend working on a copy of your project rather than the original. You can complete all of these exercises using only information from the first part of the series.
Easy
Remember that drawImage() works like a potato stamp. Use it to create an unbroken ring of enemies around the edge of your canvas, like this:
(If you get bored of copying and pasting all those statements, feel free to make it a smaller ring – you could resize the canvas, too, if you like.)
Medium
Make the “you hit the enemy” alert appear whenever the avatar hits the edge of the ring. (To test this, remember that you can hit Enter to dismiss the alert; you don’t have to click OK.)
Hard
That alert will come up when you try to move your mouse from outside the canvas to inside it, which is really annoying if you’ve already clicked the canvas. Make it possible to move into the canvas without triggering the alert – but once inside, make the alert appear whenever the avatar touches the ring of enemies.
Make the Enemy Move
We’re going to make the enemy fall down from the top of the screen. For now, we’ll focus on making it move rather than on detecting a collision, so “comment out” the lines in redrawEnemy() that deal with collisions, like so:
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
Remember: two forward slashes tell the browser “ignore everything on this line from here on”. Earlier on we used this to create comments – little reminders of what certain bits of code do – but here we’re using it for another purpose: stopping certain bits of code from running without completely deleting them. This makes it easy for us to put the code back in later.
At the moment, the enemy is redrawn, in the same position, whenever we move the mouse:
gameCanvas.getContext("2d").drawImage(enemyImage, 250, 150);
Do you remember the Math.random() function from the first part of the tutorial? It returns a random number between zero and one; multiplying it by 300 (the height of the canvas) would give us a number between 0 and 300. What happens if we draw the enemy at a random y-position between 0 and 300 every time the mouse was moved? Let’s try it out; modify that line like so:
gameCanvas.getContext("2d").drawImage(enemyImage, 250, Math.random() * 300);
Try it out here!
It looks like the enemy is moving randomly up and down a certain line, but only when the mouse is moved. Of course, it’s not actually moving; it’s “teleporting” from one position to the next, but this gives the illusion of movement.
We’d get a better illusion if it only moved in one direction. We can achieve this by making sure the enemy’s y-position only increases, and never decreases.
Consider the following code:
function redrawAvatar(mouseEvent) {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
var enemyImage = new Image();
var enemyY = 0;
avatarImage.src = "img/avatar.png";
enemyImage.src = "img/enemy.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
See what I’m doing? I set the value of enemyY to 0 at the top of the function, then increased it by one pixel before drawing the enemy. In this way, I’m aiming to make the enemy’s y-position increase by one pixel every time redrawAvatar() is run.
However, there’s a flaw in my logic. The line var enemyY = 0; will reset the enemyY variable to 0 every time redrawAvatar() is run, which means that it’ll always be drawn at a y-position of 1 (because it’ll be increased at line 12).
We need to only set it to 0 once. What if we do that in drawEnemy()? After all, that function is only run once:
function drawAvatar() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
var enemyY = 0;
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", redrawAvatar);
}
function redrawAvatar(mouseEvent) {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
var enemyImage = new Image();
avatarImage.src = "img/avatar.png";
enemyImage.src = "img/enemy.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
Try it out here!
Unfortunately, this doesn’t work at all. The problem lies in a concept called scope. If you use the var keyword to define a variable within a function, then the variable will only be accessible within that function. This means that our redrawAvatar() function cannot access the same enemyY variable that was defined in drawAvatar().
However, if we define a variable outside of all functions, it can be accessed by any one of them! So, try this:
var enemyY = 0;
function drawAvatar() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", redrawAvatar);
}
function redrawAvatar(mouseEvent) {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
var enemyImage = new Image();
avatarImage.src = "img/avatar.png";
enemyImage.src = "img/enemy.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
Try it out here!
It works – the enemy slides down the screen. However, it only does so while we’re moving the mouse. That’s an interesting game mechanic, but it’s not what I was aiming for.
Make the Enemy Move on Its Own
It’d be much better if the enemy appeared to move of its own accord – meaning, it moves regardless of whether or not the player is moving the mouse. We can do this by triggering its movement (its “teleportations”) based on time rather than on mouse movement.
We can do this by using the setInterval() function. It works like this:
setInterval(functionName, period);
Here, functionName is the name of a function we want to run over and over again, and period is the amount of time (in milliseconds) we want to pass between each call to that function.
Let’s see how this looks:
var enemyY = 0;
function drawAvatar() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", redrawAvatar);
setInterval(redrawEnemy, 1000);
}
function redrawAvatar(mouseEvent) {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
avatarImage.src = "img/avatar.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
function redrawEnemy() {
var enemyImage = new Image();
enemyImage.src = "img/enemy.png";
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
}
I’ve moved all the code that deals with moving and drawing the enemy to the new redrawEnemy() function, and I’ve set it to be called every 1,000 milliseconds (every second) using a setInterval() call in drawAvatar(). (Unlike when using an event listener, no parameters automatically get passed to redrawEnemy() when we call it from setInterval().)
Try it out here! Click the canvas, then don’t move your mouse.
There are a few things wrong with this:
- The enemy leaves a trail – this is because the canvas isn’t cleared in
redrawEnemy().
- The enemy moves really slowly – perhaps 1000 milliseconds is too long to wait.
- When the avatar is moved, the enemy disappears – this is because the enemy is only drawn in
redrawEnemy(); in redrawAvatar() the canvas is cleared and the avatar is redrawn, but not the enemy.
Let’s fix these one at a time. First, we’ll clear the canvas in redrawEnemy():
function redrawEnemy() {
var enemyImage = new Image();
enemyImage.src = "img/enemy.png";
gameCanvas.width = 400; //this erases the contents of the canvas
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
}
Try it out here!
Hm. Now the avatar disappears whenever the enemy is drawn, and vice-versa. Of course, this makes sense; we clear the canvas in both redrawEnemy() and redrawAvatar(), but never draw both the enemy and the avatar at the same time.
What if we moved the enemy in redrawEnemy() – by increasing the value of enemyY – but actually drew it in redrawAvatar()?
var enemyY = 0;
function drawAvatar() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", redrawAvatar);
setInterval(redrawEnemy, 1000);
}
function redrawAvatar(mouseEvent) {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
var enemyImage = new Image();
enemyImage.src = "img/enemy.png";
avatarImage.src = "img/avatar.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
function redrawEnemy() {
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
}
Try it out here!
It sort of works, but we’re back to that problem where the enemy only moves while you’re moving the mouse. However, this time it’s slightly different; to make this more obvious, we can increase the enemy’s speed by reducing the period. Set it to 25 (that’s 1/40th of a second, meaning redrawEnemy() will run 40 times per second):
setInterval(redrawEnemy, 25);
Try it out here!
Compare this with the earlier version where the enemy only moved when the mouse was moving. See the difference? In the new one, the enemy’s position keeps changing, but it does so “behind the scenes”; the actual image of the enemy only moves when the mouse is moved. If you wait a second or so before moving the mouse, the enemy image jumps down the screen to catch up with its actual position.
Separating the enemy’s actual position from the enemy’s image’s position like this is going to let us solve our problem.
Before we move on, are you getting confused by the function names? I am. redrawEnemy() isn’t actually drawing the enemy at all. Let’s rename them to something a bit easier to keep track of.
drawAvatar() is run when we start the game, and it sets everything up, so let’s rename it to setUpGame()
redrawAvatar() is run whenever the mouse moves, so let’s rename it to handleMouseMovement()
redrawEnemy() is run every fraction of a second; it’s as if there’s a clock that ticks 40 times a second, and each tick triggers the function. So, let’s rename it to handleTick()
Don’t forget you have to rename all the references to the functions as well, in the event listener and the setInterval(). Here’s what it’ll look like:
var enemyY = 0;
function setUpGame() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", handleMouseMovement);
setInterval(handleTick, 25);
}
function handleMouseMovement(mouseEvent) {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
var enemyImage = new Image();
enemyImage.src = "img/enemy.png";
avatarImage.src = "img/avatar.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
function handleTick() {
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
}
(You’ll also need to change the HTML page, so that the canvas’s onclick attribute is "setUpGame();" rather than "drawAvatar();".
I think this makes it easier to see what’s going on:
- When the mouse moves, we move the avatar’s position, draw the avatar in its current position, and draw the enemy in its current position.
- When the clock ticks, we move the enemy’s position.
- We need to draw the enemy and the avatar at the same time (i.e. in the same function).
- If we only draw the enemy when the mouse moves, then the enemy’s movement is not smooth.
This makes it easier in turn to see a possible solution:
- When the mouse moves, move the avatar’s position.
- When the clock ticks, move the enemy’s position, draw the avatar in its current position, and draw the enemy in its current position.
Let’s implement that. All we need to do is move the drawing code from handleMouseMovement() to handleTick(), right? Like this:
var enemyY = 0;
function setUpGame() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", handleMouseMovement);
setInterval(handleTick, 25);
}
function handleMouseMovement(mouseEvent) {
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
function handleTick() {
var avatarImage = new Image();
var enemyImage = new Image();
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
enemyImage.src = "img/enemy.png";
avatarImage.src = "img/avatar.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, mouseEvent.offsetX, mouseEvent.offsetY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
}
Hmm. That’s not right. We’ve got nothing left in handleMouseMovement(). Ah – but that’s because we haven’t separated the avatar’s image’s position from the avatar’s actual position, like we did with the enemy. So let’s do that:
var enemyY = 0;
var avatarX = 0;
var avatarY = 0;
function setUpGame() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", handleMouseMovement);
setInterval(handleTick, 25);
}
function handleMouseMovement(mouseEvent) {
avatarX = mouseEvent.offsetX;
avatarY = mouseEvent.offsetY;
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var avatarImage = new Image();
var enemyImage = new Image();
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
enemyImage.src = "img/enemy.png";
avatarImage.src = "img/avatar.png";
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
}
We have to create new variables to store the avatar’s actual x- and y-positions, and define those variables outside of any function, so that we can access them from anywhere.
Try it out here!
This works! (If it’s a little jerky, then try closing some tabs or restarting Chrome; that worked for me.) We now have a moving enemy. Took a while to get there, but the actual code we’ve ended up with isn’t too complex, I hope you’ll agree.
If you want a challenge, try re-introducing the collision detection alert box. Don’t worry if you have troubles; we’ll go through this again a bit later.
In the mean time, we’ll look at a problem you probably haven’t come across yet…
Loading the Images From a Server
As I mentioned in the first part of this series, if you put your game onto a web server as it is now, it won’t work correctly, even though they work fine when running from your computer. My demos work because I’ve made a slight modification to the code; here’s how the game runs without that code:
Try it out here.
What’s going on? Well, it’s to do with the images. Every time the clock ticks, we create a new image and set its source to point to an actual image file. This doesn’t cause problems when the image file is on your hard drive, but when it’s on the Internet, the page might try to download the image before drawing it – leading to the flickering that we can see in the demo.
Perhaps you can already guess at a solution, based on what we’ve done in this tutorial so far. Just like with the enemy’s and avatar’s positions, we can move the enemy’s and avatar’s images outside of the functions, and re-use them over and over again, without having to define them and set their values in the handleTick() function each time.
Take a look:
var enemyY = 0;
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
function setUpGame() {
var gameCanvas = document.getElementById("gameCanvas");
avatarImage = new Image();
enemyImage = new Image();
enemyImage.src = "img/enemy.png";
avatarImage.src = "img/avatar.png";
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", handleMouseMovement);
setInterval(handleTick, 25);
}
function handleMouseMovement(mouseEvent) {
avatarX = mouseEvent.offsetX;
avatarY = mouseEvent.offsetY;
//if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
// alert("You hit the enemy!");
//}
}
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
}
Try it out here – no flickering!
In case you’re wondering: we could have moved lines 9-12 outside of the functions as well. I chose to put them in setUpGame() simply because they seemed to be more about, well, setting up the game.
Make Another Enemy
It’s actually really easy to make another enemy appear on the screen. Remember that images are like potato stamps; that means there’s nothing stopping us from drawing the enemy image onto the canvas in two different places within the same tick:
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
gameCanvas.getContext("2d").drawImage(enemyImage, 100, enemyY);
}

Click to try it out.
Simple!
You can put them at different heights, like so:
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
gameCanvas.getContext("2d").drawImage(enemyImage, 100, enemyY - 50);
}

Click to try it out.
This is a bit messy, though. Instead, how about just creating an enemyY2 variable?
var enemyY = 0;
var enemyY2 = -50;
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
//...
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
enemyY2 = enemyY2 + 1;
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
gameCanvas.getContext("2d").drawImage(enemyImage, 100, enemyY2);
}
Now you can set the initial positions of enemyY and enemyY2 to whatever you want, without having to change the code in handleTick().
Make Five Enemies
Try extending what we’ve just done so that there are five enemies, all with different starting points. Take a look at my code if you need to. Here’s a hint: you only need to add code outside of the functions and inside the handleTick() function – no need to touch setUpGame() or handleMouseMovement().
var enemyY = 0;
var enemyY2 = -50;
var enemyY3 = -75;
var enemyY4 = -120;
var enemyY5 = -250;
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
//...
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
enemyY = enemyY + 1; //increase enemyY variable by one pixel. If enemyY is 10, then enemyY + 1 is 11, etc.
enemyY2 = enemyY2 + 1;
enemyY3 = enemyY3 + 1;
enemyY4 = enemyY4 + 1;
enemyY5 = enemyY5 + 1;
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyY);
gameCanvas.getContext("2d").drawImage(enemyImage, 130, enemyY2);
gameCanvas.getContext("2d").drawImage(enemyImage, 300, enemyY3);
gameCanvas.getContext("2d").drawImage(enemyImage, 50, enemyY4);
gameCanvas.getContext("2d").drawImage(enemyImage, 190, enemyY5);
}

Click to try it out.
Make Ten Enemies
Oh, this is going to get tedious, right? Maintaining all those enemies, and adding three lines of code for each one. Yuck.
Allow me to introduce arrays. Take a look at this:
var enemyYPositions = [0, -50, -75, -120, -250];
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
//...
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
enemyYPositions[0] = enemyYPositions[0] + 1;
enemyYPositions[1] = enemyYPositions[1] + 1;
enemyYPositions[2] = enemyYPositions[2] + 1;
enemyYPositions[3] = enemyYPositions[3] + 1;
enemyYPositions[4] = enemyYPositions[4] + 1;
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyYPositions[0]);
gameCanvas.getContext("2d").drawImage(enemyImage, 130, enemyYPositions[1]);
gameCanvas.getContext("2d").drawImage(enemyImage, 300, enemyYPositions[2]);
gameCanvas.getContext("2d").drawImage(enemyImage, 50, enemyYPositions[3]);
gameCanvas.getContext("2d").drawImage(enemyImage, 190, enemyYPositions[4]);
}
This gives us the exact same result as before, but:
- All of the enemies’ y positions are defined in a single line, and
- We get an easy way to refer to any of these positions:
enemyYPosition[enemyNumber].
This type of variable is called an array; it’s a way of holding a list of values (or even of other variables), and lets us retrieve any item from that list using a number. Note that the first element of an array is number 0, the second value is number 1, and so on – we call arrays “zero-based” for this reason.
Looping
Now take a look at this section of code:
enemyYPositions[0] = enemyYPositions[0] + 1;
enemyYPositions[1] = enemyYPositions[1] + 1;
enemyYPositions[2] = enemyYPositions[2] + 1;
enemyYPositions[3] = enemyYPositions[3] + 1;
enemyYPositions[4] = enemyYPositions[4] + 1;
We’re doing the same thing, over and over again, to different items in the array. Each line of code is the same as all of the others, except that the number inside the square brackets changes. This is great, because we can write code to say “do this same thing five times, but changing one number each time”. For example:
var currentNumber = 0;
while (currentNumber < 5) {
alert(currentNumber);
currentNumber = currentNumber + 1;
}
If you put this in your JS file (in setUpGame(), for example), it would make the page display five alert boxes: the first would say “0″; the second would say “1″; and so on up to “4″. In other words, it’s equivalent to doing this:
var currentNumber = 0;
alert(currentNumber);
currentNumber = currentNumber + 1;
alert(currentNumber);
currentNumber = currentNumber + 1;
alert(currentNumber);
currentNumber = currentNumber + 1;
alert(currentNumber);
currentNumber = currentNumber + 1;
alert(currentNumber);
currentNumber = currentNumber + 1;
This is because the while statement acts like a repeated if statement. Remember, if works like this:
if (condition) {
outcome;
}
“If condition is true, then run outcome.”
while works like this:
while (condition) {
outcome;
}
“As long as condition remains true, keep running outcome.”
It’s a subtle difference, but a really important one. An if block will run just once, if the condition is true; a while block will run over and over again until the condition stops condition stops being true.
For this reason, the outcome – the code that’s run inside the while block – usually contains some code that will, eventually, cause condition to stop being true; if it didn’t the code would just repeat itself forever. In our alert box example, we increased the value of currentNumber until it “currentNumber < 5" was no longer true (when currentNumber reached 5, it was no longer less than 5, which is why we never see an alert box containing the number 5).
Running code over and over again like this is called "looping", and the while block is called a "loop". Let's now take this code:
enemyYPositions[0] = enemyYPositions[0] + 1;
enemyYPositions[1] = enemyYPositions[1] + 1;
enemyYPositions[2] = enemyYPositions[2] + 1;
enemyYPositions[3] = enemyYPositions[3] + 1;
enemyYPositions[4] = enemyYPositions[4] + 1;
...and put it into a loop:
var currentEnemyNumber = 0;
while (currentEnemyNumber < 5) {
enemyYPositions[currentEnemyNumber] = enemyYPositions[currentEnemyNumber] + 1;
}
Great! Or is it?
Actually, that's not quite right: we're not changing the value of currentEnemyNumber. This means that we'll just increase the value of enemyYPositions[0] over and over again, forever, without ever changing the other enemies' y-positions or ever exiting the loop.
So, we need to do this:
var currentEnemyNumber = 0;
while (currentEnemyNumber < 5) {
enemyYPositions[currentEnemyNumber] = enemyYPositions[currentEnemyNumber] + 1;
currentEnemyNumber = currentEnemyNumber + 1;
}
Now it's great.
Can we apply the same thinking to our other repetitive code? I'm referring to this:
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyYPositions[0]);
gameCanvas.getContext("2d").drawImage(enemyImage, 130, enemyYPositions[1]);
gameCanvas.getContext("2d").drawImage(enemyImage, 300, enemyYPositions[2]);
gameCanvas.getContext("2d").drawImage(enemyImage, 50, enemyYPositions[3]);
gameCanvas.getContext("2d").drawImage(enemyImage, 190, enemyYPositions[4]);
Unfortunately, something like this won't work:
var currentEnemyNumber = 0;
while (currentEnemyNumber < 5) {
gameCanvas.getContext("2d").drawImage(enemyImage, 250, enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
...because not all enemies have an x-position of 250. But we can make it work, if we move all the enemies x-positions to another array:
var enemyXPositions = [250, 130, 300, 50, 190];
var enemyYPositions = [0, -50, -75, -120, -250];
//...
var currentEnemyNumber = 0;
while (currentEnemyNumber < 5) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
This has the added benefit of keeping all the enemies' x- and y-positions in one neat location, rather than spread out across several lines.
Let's look at the code in context:
var enemyYPositions = [0, -50, -75, -120, -250];
var enemyXPositions = [250, 130, 300, 50, 190];
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
//...
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
while (currentEnemyNumber < 5) {
enemyYPositions[currentEnemyNumber] = enemyYPositions[currentEnemyNumber] + 1;
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < 5) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
}
Note that, on line 22 above, I've reset currentEnemyNumber to 0; if I didn't, the loop for drawing the enemy images wouldn't run even once, as condition would already be false from the earlier loop that moves the enemies. Also note that, when I do this, the loop that draws the enemies doesn't immediately detect that condition is now true again and start moving all the enemies.
It all works just as it did before.

Click to try it out.
The biggest benefit to this is in how easy it is to add another five enemies. We only need to change four lines of code:
var enemyYPositions = [0, -50, -75, -120, -250, -280, -305, -330, -340, -400];
var enemyXPositions = [250, 130, 300, 50, 190, 200, 220, 60, 100, 110];
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
//...
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
while (currentEnemyNumber < 10) {
enemyYPositions[currentEnemyNumber] = enemyYPositions[currentEnemyNumber] + 1;
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < 10) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
}

Click to try it out.
Simple!
Make Fifteen Enemies
Here's another exercise for you: modify the code so that it creates fifteen enemies. Again, you only have to alter four lines of code. Take a look at my code if you're not sure:
var enemyYPositions = [0, -50, -75, -120, -250, -280, -305, -330, -340, -400, -425, -450, -500, -520, -550];
var enemyXPositions = [250, 130, 300, 50, 190, 200, 220, 60, 100, 110, 30, 300, 150, 190, 90];
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
//...
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
while (currentEnemyNumber < 15) {
enemyYPositions[currentEnemyNumber] = enemyYPositions[currentEnemyNumber] + 1;
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < 15) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
}
Obviously we could continue on like this. But I'm already finding it irritating to change lines 14 and 23 above, and have forgotten to do so a couple of times.
Fortunately we can automate this, in a way. The number - 5, 10, 15, or whatever - is equal to the number of items in either the enemyXPositions[] or enemyYPositions[] array. We call this the array's length, and can retrieve it from either array by using the .length property - like so:
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
while (currentEnemyNumber < enemyXPositions.length) {
enemyYPositions[currentEnemyNumber] = enemyYPositions[currentEnemyNumber] + 1;
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < enemyXPositions.length) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
}
Or, to be a bit neater:
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
var numberOfEnemies = enemyXPositions.length;
while (currentEnemyNumber < numberOfEnemies) {
enemyYPositions[currentEnemyNumber] = enemyYPositions[currentEnemyNumber] + 1;
currentEnemyNumber = currentEnemyNumber + 1;
}
gameCanvas.width = 400; //this erases the contents of the canvas
gameCanvas.getContext("2d").drawImage(avatarImage, avatarX, avatarY);
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
gameCanvas.getContext("2d").drawImage(enemyImage, enemyXPositions[currentEnemyNumber], enemyYPositions[currentEnemyNumber]);
currentEnemyNumber = currentEnemyNumber + 1;
}
}
Now you can make as many enemies as you want, just by adding new numbers to the enemyXPositions[] and enemyYPositions[] arrays.
Re-Introduce Collision Detection
Remember how collision detection worked? We've had the code sitting in handleMouseMovement() (though commented out) for a while:
if (mouseEvent.offsetX > 220 && mouseEvent.offsetX < 280 && mouseEvent.offsetY > 117 && mouseEvent.offsetY < 180) {
alert("You hit the enemy!");
}
It's basically checking whether two rectangles - one that moves with the cursor, and one that sits still on the canvas - are overlapping. But it's hard to understand from that code, so let's take a fresh look.
First, let's look at it in terms of horizontal overlap:
Here, the avatar and the enemy are not overlapping. We have: avatarX < avatarX + 30 < enemyX < enemyX + 30
Here, the avatar and the enemy are overlapping. We have: avatarX < enemyX < avatarX + 30 < enemyX + 30
Still overlapping. We have: enemyX < avatarX < enemyX + 30 < avatarX + 30
No longer overlapping. We have: enemyX < enemyX + 30 < avatarX < avatarX + 30
Taking all these together, we can see that the enemy and avatar are overlapping horizontally if:
avatarX < enemyX and enemyX < avatarX + 30
...or:
enemyX < avatarX and avatarX < enemyX + 30
In other words, for horizontal overlap, this condition must be true:
(avatarX < enemyX && enemyX < avatarX + 30) || (enemyX < avatarX && avatarX < enemyX + 30)
(Remember, && means "and"; || means "or".)
It's not hard to come up with a similar condition for vertical overlap:
(avatarY < enemyY && enemyY < avatarY + 33) || (enemyY < avatarY && avatarY < enemyY + 30)
(We use 33 here because the avatar is 33 pixels tall, but only 30 pixels wide.)
For the enemy and avatar to be overlapping, they must be overlapping both horizontally and vertically - so we use the && operator to combine these two conditions:
( (avatarX < enemyX && enemyX < avatarX + 30) || (enemyX < avatarX && avatarX < enemyX + 30) ) && ( (avatarY < enemyY && enemyY < avatarY + 33) || (enemyY < avatarY && avatarY < enemyY + 30) )
That's a long condition! But it's actually quite simple, now that we've broken it down. Let's put it into our code. First, delete the old collision detection code from handleMouseMovement(); we'll put this in handleTick(), after we've moved and redrawn the enemy and avatar, so that it seems fairer.
To start with, we'll just check for a collision between the avatar and the first enemy:
function handleTick() {
//...
if ( ( (avatarX < enemyXPositions[0] && enemyXPositions[0] < avatarX + 30) || (enemyXPositions[0] < avatarX && avatarX < enemyXPositions[0] + 30) ) && ( (avatarY < enemyYPositions[0] && enemyYPositions[0] < avatarY + 33) || (enemyYPositions[0] < avatarY && avatarY < enemyYPositions[0] + 30) ) ) {
alert("You hit the first enemy!");
}
}
It looks messy (so you should probably add a comment to remind yourself of how it works later), but it's got everything we need. Does it work?
Try it out here!
It does work! Now we should make it work for all the enemies - and of course we can use a loop to do that:
currentEnemyNumber = 0;
while (currentEnemyNumber < numberOfEnemies) {
if ( ( (avatarX < enemyXPositions[currentEnemyNumber] && enemyXPositions[currentEnemyNumber] < avatarX + 30) || (enemyXPositions[currentEnemyNumber] < avatarX && avatarX < enemyXPositions[currentEnemyNumber] + 30) ) && ( (avatarY < enemyYPositions[currentEnemyNumber] && enemyYPositions[currentEnemyNumber] < avatarY + 33) || (enemyYPositions[currentEnemyNumber] < avatarY && avatarY < enemyYPositions[currentEnemyNumber] + 30) ) ) {
alert("You hit an enemy!");
}
currentEnemyNumber = currentEnemyNumber + 1;
}
Note that this goes inside handleTick(), at the end, so we have to reset currentEnemyNumber to 0. We also need to change the alert box text, since it might not be the first enemy that causes the alert to appear.
Try it out here!
All right, this is really shaping into a game! Okay, sure, the alert box is kind of annoying, but it serves our purposes for now.
There's one more big addition I'd like us to make in this part...
Make Infinitely Many Enemies
We can add more and more enemy positions to our arrays - a hundred, a thousand, whatever - but eventually the supply will run out, and the player will have no more enemies to dodge. We need to be able to create new enemies and add their positions to the arrays while the game is running.
When we want to change the value of a specific item inside enemyXPositions, it's easy: we just write enemyXPositions[3] = 100, or whatever. But how can we add something to the array? Writing enemyXPositions = [100] (or whatever) will just replace the array with a new one, containing just one item.
The answer is in the arrays' .push() function; this allows us to add an item to an array without creating a new one. To demonstrate this, let's delete all the items from our arrays, and then use .push() to add new ones:
var enemyYPositions = []; //empty square brackets means new empty array
var enemyXPositions = [];
var avatarX = 0;
var avatarY = 0;
var avatarImage;
var enemyImage;
function setUpGame() {
var gameCanvas = document.getElementById("gameCanvas");
avatarImage = new Image();
enemyImage = new Image();
enemyImage.src = "img/enemy.png";
avatarImage.src = "img/avatar.png";
enemyYPositions.push(0);
enemyXPositions.push(250);
gameCanvas.getContext("2d").drawImage(avatarImage, Math.random() * 100, Math.random() * 100);
gameCanvas.addEventListener("mousemove", handleMouseMovement);
setInterval(handleTick, 25);
}

Click to try it out.
It works fine; the enemy still moves and the collision detection still works. It's exactly the same as if we'd started the code with:
var enemyYPositions = [0];
var enemyXPositions = [250];
So what happens if we push the new values onto the arrays inside handleTick(), rather than inside setUpGame()?
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
var numberOfEnemies = enemyXPositions.length;
enemyYPositions.push(0);
enemyXPositions.push(250);

Click to try it out.
Hm. It's creating new enemies in the same positions at such a fast rate that they're overlapping. (The one at the top of the screen appears to be above all of the others because that's the last one to get drawn.)
Let's try to fix this by creating the enemies at random starting x-positions. Remember that Math.random() gets us a random number between 0 and 1, so to get a random number between 0 and 400 - the width of the canvas - we can use Math.random() * 400:
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
var numberOfEnemies = enemyXPositions.length;
enemyYPositions.push(0);
enemyXPositions.push(Math.random() * 400);

Click to try it out.
Argh!
All right, so maybe they're still coming in at too fast a rate...
Less Enemies Per Second, Please
Right now, the enemies are being created at a rate of one new enemy per tick - and since a tick is 25ms, there are 40 ticks per second, and therefore 40 new enemies per second.
Let's reduce this to something more manageable: about two enemies per second.
Since that's 1/20th of our current rate, we could achieve this by keeping track of how many ticks have passed, and creating a new one on tick number 20, tick number 40, tick number 60, and so on. But I think it'll be more fun if instead we make there be a 1/20 chance of a new enemy being creates on any given tick. This way, sometimes we'd create more than two new enemies in one second, and sometimes we'd create less, but it'd average out to two per second. The uncertainty involved would make the game a little more exciting (though perhaps "exciting" is a poor choice of words at this early stage of the game's development...).
How can we do this, then? Well, we know that Math.random() create a random number between 0 and 1. Since these random numbers are evenly spread out between 0 and 1, that means there's a 1/20 change of the number generated being somewhere between 0 and... well, 1/20.
In other words, the chance of Math.random() < 1/20 being true is 1/20.
So, let's change our code to make use of this fact:
function handleTick() {
var gameCanvas = document.getElementById("gameCanvas");
var currentEnemyNumber = 0;
var numberOfEnemies = enemyXPositions.length;
if (Math.random() < 1/20)
{
enemyYPositions.push(0);
enemyXPositions.push(Math.random() * 400);
}

Click to try it out.
Much better! Feel free to experiment with that condition to find a value that works for you.
Wrapping Up
That's it for this part of the series. We've now built a rudimentary game - not a polished game, not a particularly fun game, but a game nonetheless.
If you'd like to challenge yourself before the next part, have a go at making these changes:
- Easy: The enemies 'pop' onto the top of the canvas; make them slide in, instead.
- Easy: Some of the enemies are created partially off the side of the canvas; stop this happening.
- Medium: The enemies all move at exactly the same speed, which is pretty dull; allow them to have different speeds.
- Hard: The avatar can move off the right edge of the canvas, making it impossible for any enemies to touch it (assuming you've completed the second easy challenge). Make sure the avatar stays inside the boundaries.
Enjoy!



View full post on Activetuts+
Page 5 of 19« First«...34567...10...»Last »