IoT-Gadgets-Logo-272-90

HTML5 Game Development For AppUp - Part 1

By
Sam
 - 
Sep 25, 2011

What follows is a post by Intels Bob Duffy on HTML5 Games Development that Appeared WAY back in May of this year on Intels AppUp Developer Program. The reason that this is getting posted now is that a Part 2 has recently surfaced and hey, How Can I post part 2 without part 1 ?
HTML5-Game-Development-AppUp-MeeGo-MeeGoExperts-1

 

When I heard earlier this year we were going to support HTML5 apps in our store via a tool called encapsulator, it peaked my interest.  I wondered how hard it would be to develop a game using HTML.  I'm a former ColdFusion developer, so I have familiarity with javascript and thought, why not try this.  The following article and subsequent articles in a series will show you my journey and in the process, should show you how you can be a game developer using HTML5.

What we'll cover in this article

  • The Project
  • Intro to Canvas API
  • Game Code Part 1 - Animating A Spaceship

The Project

My game will be available on the Intel AppUp center for Windows and MeeGo netbooks.  At the time of this post, I have not created a touch version but is my intention to convert my key inputs to touch command and release the game for MeeGo tablet.  You can download the game by going to the AppUp.com website and downloading AppUp for your Windows or MeeGo netbook. Then search for "AltMegaRace".

HTML5-Game-Development-AppUp-MeeGo-MeeGoExperts-2

I love old timey arcade games.  Especially vector games. There's something about line vector spaceships that gives a game that super retro feel.  When I was in high school my favorite arcade game was Omega Race.  I would seek out the game at arcades and dropped a lot of gas money on that game. I soon purchased a Commodore Vic20 computer, and my own copy of Omega Race. And after that I had an Amiga computer and I played Omega Race all thru college.  I liked the game 🙂

Thus the first game I thought to replicate is Omega Race.  Omega Race is confined to one game space.  There is no horizontal or vertical scrolling.  Like PacManand Space Invaders the game design and mechanics are very simple.  OmegaRace was often compared to Asteroids because it had you manuever a vector based ship to blow up an onslaught of enemies. OmegaRace differed in that it provided this track made of lasers, and if you hit the edges you'd bounce your ship like a billiard ball. This made for interesting game play and physics of the game.  So OmegaRace is my model for this game.  The parts I decided to create are as follows

  • A space ship that could navigate in space within a confined track and bounce off the walls off the track
  • Wave of enemies that would race around the track and shoot at me with some randomness in their movement and missiles
  • Increasing level of difficulty at each level, more enemies, faster enemies

 

In general there is no winning this game. There is no boss level.  It just gets harder and harder and eventually you lose all your lives. It's a simple premiss and if done well hours of entertainment.

Finished Game:

See a video of my game "AltMegaRace" on YouTube

Canvas API

The Canvas API is the development framework we are using to write this game. Canvas is coded in javascript and sits within an HTML page.  Canvas was developed by many including Apple* and Opera Software* and is now an established part webkits HTML5.  That means any modern web browser supporting HTML5 will support the Canvas API.  From a developers perspective the closest thing to Canvas is Adobe's ActionScript.  Just like with ActionScript you can script an illustration of any shape.  You can draw lines, curves and arcs. You can stroke those lines and provide color fills, gradients & drop shadows.  If you can imagine it, you can draw it with ActionScript and Canvas, in nearly the identical way.  Here is a tutorial comparing ActionScript to Canvas http://www.williammalone.com/articles/flash-vs-html5-canvas-drawing/ (Flash developers you can pick up your jaw now)

I suggest checking out these resources for learning more about Canvas.  They came in handy for me.

Wrapping you brain around Canvas animation

Drawing in canvas is one thing, however animating in canvas is another.  There is a way you have to think about Canvas which is different than other environments. Instead of rotating and moving objects you are rotating and moving your canvas each time you draw an object, then you reposition the canvas between each object being drawn.  This is the basic process for drawing and rotating an object for each frame of animation

  • Erase everything
  • Move canvas origin coordinates to your object
  • Rotate and move objects
  • Move origin back

HTML5-Game-Development-AppUp-MeeGo-MeeGoExperts-2

 

At first it seems funky but you get used to it and occassionally you'll forget to move the origin and the result is your entire games space will rotate instead of a game object. Here's an example of doing this.  The code will draw 1000x500 rectangle that will remain static while a small square rotates and moves down and to the right of the page.  Read comments to the right of each line to understand what is going on.

<html>
<head>
<script type="text/javascript">
var context;
var gamew=1000;
var gameh=500;
var spin=1;
var squarex=50;
var squarey=50;

function fallingsquare(){
context=game_area.getContext('2d');      // context is the variable to envoke all Canvas commands
context.strokeStyle="red"                // Color of the object lines
context.clearRect(0,0,gamew,gameh);      // Clears the entire screen
context.strokeRect(0,0,gamew,gameh);     // Draws a game space rectangle 1000x500
spin++;                                  // Increases the rotation of our object 1 radian
squarex++;                               // Increases the X position of our object - to the right
squarey++;                               // Increases the Y position of our object - down
context.save();                          // Save the canvas location
context.translate(squarex,squarey);      // Move the Canvas Coordinates to the square X & Y position (remember this moves each time)
context.rotate(spin * Math.PI/180);
// Rotates the canvas according to the value of "spin" which is increaseing each frame
context.strokeRect(-10,-10, 20, 20);      // Draws a rectangle -minus 10 points left and up of our squarecenter then 10 points down and to the right
context.stroke();                         // Stroke the objects
context.restore();                        // Restores our canvas (to its X&Y position - that way the game space rectangle is drawn at the same spot next time
}
setInterval(fallingsquare,25);                // waits 25 milliseconds then repeats all of the above

</script>
</head>
<body>
<canvas id="game_area" width="1000" height="500"></canvas> <!--Add your Canvas app to your page-->
</body>
</html>

Try this yourself, play around with it and see if you can change the rate of rotation, movement of the falling square (will work in Opera, Chrome, & Firefox.  Explorer does not support HTML5).   Also remark out the context.restore and or the context.translate lines and see what happens.

Game Code Part 1 - Animating A Spaceship

OK now for the fun part, we get to start coding our game.  Much of the overall animation we are going to deploy follows the above example but now we are going to put some of the core pieces together to create a spaceship and move it around our game space.  In the next parts of this article series we will go over creating enemy ship arrays, collision detection, game levels etc.  But to get startes we are going to cover the following basic of our game.

  • Establishing game and ship variables
  • Drawing the gamespace
  • Drawing our spaceship
  • Event listeners for key commands
  • Refreshing the Game

Variables:  The variables for this stage of the game are pretty simple we want to create the following: Game width and height, size of ship, default position of ship (X&Y).  Also we initiate the main canvas command variable "context".

var context;
var gamew=1000;
var gameh=500;
var spin=1;
var shipx=50;
var shipy=50;
var shipsize=30;

Key commands are also variables we want to set.  We want to set key commands to set certain things in motion like rotation of our ship or movement of our ship.  You can go to this page if you want to get a list of what keys coorespond to what keyCodes. http://www.cambiaresearch.com/c4/702b8cd1-e5b0-42e6-83ac-25f0306e3e25/Javascript-Char-Codes-Key-Codes.aspx.  Here we are going to set our arrow keys (37, 38, 39, 40) to set variables left, up, right, down to true if the key is presses and false if not.  For rotation we will use the "A" and "D" key for left and right rotation of our ship.  Here we set a variable spinr and spinl to  true and then false if up or down.

function keyDown(e) {
if (e.keyCode == 39) right = true;
if (e.keyCode == 37) left = true;
if (e.keyCode == 38) up = true;
if (e.keyCode == 40) down = true;
if (e.keyCode == 68) spinr = true;
if (e.keyCode == 65) spinl = true;
}

function keyUp(e) {
if (e.keyCode == 39) right = false;
if (e.keyCode == 37) left = false;
if (e.keyCode == 38) up = false;
if (e.keyCode == 40) down = false;
if (e.keyCode == 65) spinl = false;
if (e.keyCode == 68) spinr = false;
}

Drawing the gamespace:  This will be the easiest code we deploy.  If you remember we will clear our screen each time we move an object, so even though the game space and track will be static we have to draw it in every frame.  So we will want to recall the instructions to draw our track.  To do this we'll put thie instructions to draw the track in a function, then call that function everytime we refresh the screen. This will be more than a square,like OmegaRace we will have an inner rectangle to create the track shape. Eventually we will add collision detection so the ship will bounce off the walls of the track, but for now that track will be just drawn and not interact with the ship.

function drawracetrack(){
context.beginPath();
context.strokeStyle="yellow";
context.strokeRect(200,200, 600, 100);
context.strokeRect(5,5, gamew-5, gameh-5);
context.closePath();
context.stroke();

HTML5-Game-Development-AppUp-MeeGo-MeeGoExperts-4

 

Drawing the ship: If you are an old timer developer you may remember a language called LOGO.  LOGO was designed to teach kids how to

developer. You started with a turtle on the screen you would say Go to 20 and then the turtle would move forward 10 paces. You could then add a commande; Turn 90, and the go back to the original line in the program and your turtle would draw a 20x20 square.  Well we are going to basically do the same thing when drawing our ship.  We want instuct Canvas how to draw our ship by going from one coordinate to another, however it will be a bit more complicate than a square.

If you recall, whenever we draw our ship we are moving the origin of the cavas the center of the ship, so to draw the ship we will have to consider all of our coordinates in relationship to the center of our ship being at 0,0.  Thus any point of the ship left of the center is a negative number, right is a positive number, above the center is negative and below is positive.  It may help to get out some graph paper to draw a shape and count the position of each point of your drawing in relationship to the center.

For this project I set a shipsize variable, that way I could change the size of the ship as I see fit. So I use the numbers from my graph paper changed them to decimals and multiplied them by my the shipsize.   Below is the code to draw our ship.

function drawship(){
context.strokeStyle="red";
context.beginPath();
context.moveTo(shipsize*-.3, shipsize*.2);
context.lineTo(shipsize*-.4, shipsize*-.1);
context.lineTo(shipsize*.1, shipsize*.4);
context.lineTo(0, shipsize*.5);
context.lineTo(shipsize*-.1, shipsize*.4);
context.lineTo(shipsize*.4, shipsize*-.1);
context.lineTo(shipsize*.3, shipsize*.2);

context.moveTo(shipsize*-.4, shipsize*-.1);
context.lineTo(shipsize*.3, shipsize*-.5);
context.lineTo(0, shipsize*.3);
context.lineTo(shipsize*-.3, shipsize*-.5);
context.lineTo(shipsize*.4, shipsize*-.1);

context.stroke();

Rotating The Ship:  To rotate our ship left or right we only need to tell Canvas to move the Canvas origin to the position of our ship then we rotate the canvas either positive number or negative number.  That number will be calculated with our event listener from our key commands.  Then we draw the ship.  Basically this is exactly what we did in our original code sample.  The only difference here is we seperated the drawing of the ship into its own function then we recalled it in the rotateship function.  In other words each time we rotate the ship or don't rotate the ship we have to draw the ship, so drawship() is part of the rotateship function

function rotateship()
context.save();
context.translate(shipx,shipy);
context.rotate(spin * Math.PI/180);
drawship();
context.restore();

Game Events:   This is the main running part of the game, it will call all the other functions when appropriate listen for keyboard events and calculate the ship position and rotation, the run itself every 25 milliseconds.  This will take a bit of explaination because I'm putting a lot in this part.  First lets look at the ship movement.

The ship movement will move in the direction of the arrows by adding or subtracting to the X or Y position of the ship.  If the ship is at position 100, 100 and I hit the up arrow it should move to position 100, 99.  If I hit the right arrow then to position 101,99, etc.   The only problem is the ship would not float like it should in space. It should move like it has a rocket booster. If I press the up arrow it should accellerate up the screen and when I stop pressing it it should continue to go for a bit as it had momentum.  So to do this I want to create a speed for ship, so as you press on the arrow keys the rate that the ships moves across the x or y access.  So the first part of this code determines if any of the direction keys are pressed and if so it increases or decreases the vertical or horizontal speed.

if(left){
x_speed--;
}
if(right){
x_speed++;
}
if(up){
y_speed--;
}
if(down){
y_speed++;
}

So you can see if I click the right arrow my x_speed increases, while if I hit the left arrow my x_speed starts to reverse.  That sets the rate of direction either left or right or similarly up or down.

Now this does not move the ship yet.  I have not applied the speed to the ships X or Y position.  To do that I need to say that the shipx variable is equal to its current value + the x_speed.  However I'd like that rate to increase rather than one incriment at a time, so I'm multipling the rate by *1.1. In other words as I press the right key, the ship is going to move to the right 10% faster with each frame of animation.  Now I also want to slow it down so it doesn't just keep going forever.  I could put in some command to stop when I let go of the button but would be like a break.  If I want it to act like a rocket boost then I will just slow down over time.  So I also add a calculation that says the x_speed= its currents speed *.97, that means at each frame of animation it reduces its speed by 3%, thus it will slow down pretty quickly

shipx+=x_speed*1.1;
shipy+=y_speed*1.1;
x_speed*=.97;
y_speed*=.97;

Now to rotate the ship we need to see if we are pressing the A or D key which sets our spinl and spinr variables.  And like our movement we want this to be fluid with some.  So you'll see below we are doing the exact same thing.  If A is presses spinl changes our rotatespeed to a negative number while D rotates at a positive number.  The actual spin angle is more strait forward, we don't accelerate it, but after we are done spinning we do have a bit of a winde down, slowing down 10% with each frame of animation

if (spinl){
rotatespeed--;
}
else if (spinr){
rotatespeed++ ;
}
else {
spin+=0;
}
spin+=rotatespeed;
rotatespeed*=.9;

Finally we have to clear the screen and add the functions that draw our ship and racetrack.  And the last bit is to add the event listeners for key commands and interval refresh the game animation. So the end of our code looks like this

function on_enter_frame(){
context=game_area.getContext('2d');      // context is the variable to envoke all Canvas commands

if(left){
x_speed--;
}
if(right){
x_speed++;
}
if(up){
y_speed--;
}
if(down){
y_speed++;
}

shipx+=x_speed*1.1;
shipy+=y_speed*1.1;
x_speed*=.97;
y_speed*=.97;

if (spinl){
rotatespeed--;
}
else if (spinr){
rotatespeed++ ;
}
else {
spin+=0;
}
spin+=rotatespeed;
rotatespeed*=.9;

context.clearRect(0,0,gamew,gameh);
rotateship();
drawracetrack();

document.addEventListener('keydown', keyDown, false);
document.addEventListener('keyup', keyUp, false);

setInterval(on_enter_frame,25);               // waits 25 milliseconds then repeats all of the above

Final Code Part -1

 

Below is the entire code we put together, or check it out here HTML5-Part1  Try it yourself. You should be able to fly and rotate you spaceship around the screen. Be careful, there is no collision detection, yet, so you can fly right out of the game space :-).

<html>
<head>
<script type="text/javascript">
var context;
var left;
var right;
var up;
var down;
var spinl;
var spinr;
var gamew=1000;
var gameh=500;
var spin=1;
var shipx=50;
var shipy=50;
var shipsize=30;
var x_speed=0;
var y_speed=0;
var rotatespeed=0;

function drawracetrack(){
context.beginPath();
context.strokeStyle="yellow";
context.strokeRect(200,200, 600, 100);
context.strokeRect(5,5, gamew-5, gameh-5);
context.closePath();
context.stroke();

}
function drawship(){
context.strokeStyle="red";
context.beginPath();
context.moveTo(shipsize*-.3, shipsize*.2);
context.lineTo(shipsize*-.4, shipsize*-.1);
context.lineTo(shipsize*.1, shipsize*.4);
context.lineTo(0, shipsize*.5);
context.lineTo(shipsize*-.1, shipsize*.4);
context.lineTo(shipsize*.4, shipsize*-.1);
context.lineTo(shipsize*.3, shipsize*.2);

context.moveTo(shipsize*-.4, shipsize*-.1);
context.lineTo(shipsize*.3, shipsize*-.5);
context.lineTo(0, shipsize*.3);
context.lineTo(shipsize*-.3, shipsize*-.5);
context.lineTo(shipsize*.4, shipsize*-.1);

context.stroke();
}

function rotateship(){
context.save();
context.translate(shipx,shipy);
context.rotate(spin * Math.PI/180);
drawship();
context.restore();
}

function keyDown(e) {
if (e.keyCode == 39) right = true;
if (e.keyCode == 37) left = true;
if (e.keyCode == 38) up = true;
if (e.keyCode == 40) down = true;
if (e.keyCode == 68) spinr = true;
if (e.keyCode == 65) spinl = true;
}

function keyUp(e) {
if (e.keyCode == 39) right = false;
if (e.keyCode == 37) left = false;
if (e.keyCode == 38) up = false;
if (e.keyCode == 40) down = false;
if (e.keyCode == 65) spinl = false;
if (e.keyCode == 68) spinr = false;
}
function on_enter_frame(){
context=game_area.getContext('2d');      // context is the variable to envoke all Canvas commands

if(left){
x_speed--;
}
if(right){
x_speed++;
}
if(up){
y_speed--;
}
if(down){
y_speed++;
}

shipx+=x_speed*1.1;
shipy+=y_speed*1.1;
x_speed*=.97;
y_speed*=.97;

if (spinl){
rotatespeed--;
}
else if (spinr){
rotatespeed++ ;
}
else {
spin+=0;
}
spin+=rotatespeed;
rotatespeed*=.9;

context.clearRect(0,0,gamew,gameh);
rotateship();
drawracetrack();

}

document.addEventListener('keydown', keyDown, false);
document.addEventListener('keyup', keyUp, false);

setInterval(on_enter_frame,25);               // waits 25 milliseconds then repeats all of the above

</script>

<style type="text/css">
#game_area{
background-color:#000000;
}
</style>
</head>

<body>
<canvas id="game_area" width="1000" height="500"></canvas>
</body>
</html>

Next time we'll cover collission detection and arrays for creating your missiles and enemies.  As usual if you have any questions comments of feedback I'd love to hear it.

Next time we'll cover collission detection and arrays for creating your missiles and enemies. As usual if you have any questions comments of feedback I'd love to hear it.

 

Source Intel AppUp Developer Program

IoT-Gadgets-Logo-272-90

About us

IoT Gadgets is dedicated to bring you all the Internet of Things IoT news that pertains to gadgets. Simple. We love for you to join us on this journey.

Contact us: [email protected]

FOLLOW US

crossmenu linkedin facebook pinterest youtube rss twitter instagram facebook-blank rss-blank linkedin-blank pinterest youtube twitter instagram