HTML5 Game Development for Windows 8 #1: Getting started

image

Hi and welcome to the first part of the HTML5 Game Development for Windows 8 tutorial series.

Note: This was written on the plane to Las Vegas in a tired condition. Will fix typos at a later stage.

This tutorial will cover how you can get started by creating a working game, and requires that you have Windows 8 installed, with Visual Studio 2012.

Also, to aid the development, we will use a library called CreateJS. This is a very powerfull library that helps you with common tasks that’s needed when creating rich interactive apps like games.

Let’s get started!

Start Visual Studio 2012 and click File->New->Project, and create a new blank Windows Store JavaScript app:
image

Give it a name and click OK to generate a new project based on the Blank template.

The project now contains a lot of different files in a project tree. The first folder is css, containing the apps css stylesheet. It’s quite empty, consisting only of an empty body tag and elements for handling the different layout-modes the app can have.

image

The next folder is the images. It contains the default tile-graphics for the app (change these to modify how the app tile looks like).
image

We will use this folder to include more images when we create the game.

Next we have the js folder. This includes the JavaScript files we want to use in the app.

image

By default this contains one file called “default.js”, it contains the basic startup code-behind for the app.

Last we have the default.html file that contains the markup for the app. Change this to add more content and controlls.

First of all, we want to include the CreateJS library files. In this project, we only need two libraries: PreloadJS and EaselJS. Download these from CreateJS.org.

While these download, create a subfolder in “js” called CreateJS:

image

Unzip the two newly downloaded CreateJS libraries. In the filestructure of each library you will find a lib folder containing a js:

lib/easeljs-0.5.0.min.js
lib/preloadjs-0.2.0.min.js

Copy these two files into the CreateJS folder. Now back in Visual Studio, click on the “Show All Files” icon:
image

Now you can see the entire filesctructure, including the two library files you copied earlier. Rightclick on these and include them in the project:

image

image

Next, we will need to include these two libraries in the default.html file. Open this and you will see the following default code:

   1: <!DOCTYPE html>

   2: <html>

   3: <head>

   4:     <meta charset="utf-8" />

   5:     <title>App3</title>

   6:  

   7:     <!-- WinJS references -->

   8:     <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />

   9:     <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
   1:  

   2:     <script src="//Microsoft.WinJS.1.0/js/ui.js">

   1: </script>

   2:  

   3:     <!-- App3 references -->

   4:     <link href="/css/default.css" rel="stylesheet" />

   5:     <script src="/js/default.js">

</script>

  10: </head>

  11: <body>

  12:     <p>Content goes here</p>

  13: </body>

  14: </html>

Click and drag the new library files into the <!—AppName references –> section in default.html (or you can type it in yourself):

   1: <!DOCTYPE html>

   2: <html>

   3: <head>

   4:     <meta charset="utf-8" />

   5:     <title>App3</title>

   6:  

   7:     <!-- WinJS references -->

   8:     <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />

   9:     <script src="//Microsoft.WinJS.1.0/js/base.js"></script>
   1:  

   2:     <script src="//Microsoft.WinJS.1.0/js/ui.js">

   1: </script>

   2:  

   3:     <!-- App3 references -->

   4:     <link href="/css/default.css" rel="stylesheet" />

   5:     <script src="/js/default.js">

   1: </script>

   2:     <script src="js/CreateJS/easeljs-0.5.0.min.js">

   1: </script>

   2:     <script src="js/CreateJS/preloadjs-0.2.0.min.js">

</script>

  10: </head>

  11: <body>

  12:     <p>Content goes here</p>

  13: </body>

  14: </html>

Now, the libraries are included and ready to ait your quest for game programming! Smilefjes

PreloadJS is a library that will help us load content like images that will be used in the app.

Making the game "Escape!”

Escape is a very simple game where you control a guy trapped in a ghost house. The objective is simple. Stay alive as long as possible! You must control the guy so he doesnt crash into the ghosts. You get points as long as you are awake!

So creating a game requires you to have some graphics. You can download a .zip file containing what you need for this tutorial here.

It contains the images our game will use.

First of all, we need the apps main screen:

LogoScreen_thumb2

The next thing we need is a floor. The game is using a top-down view:

floor_thumb1

Then we need the player:

PlayerIdle_thumb1

And the ghosts that will chase you:

Ghost_thumb1

And thats it for the graphics! Under the images folder in the project tree, add a new folder called “GFX":

image_thumb

And in the same way as we did earlier, copy the imagefiles in to the GFX folder and include them in the project.

image_thumb1

Creating the game loop
The game loop in games is quite different that what you normally have in a game project. We will need to create a function that will initialize the app, then a function that will load the content and prepare everything, and then lastly enter a loop that renders and updates frames every second.

The default.js file will contain the game loop. Initially the default.js code will look like this:

   1: // For an introduction to the Blank template, see the following documentation:

   2: // http://go.microsoft.com/fwlink/?LinkId=232509

   3: (function () {

   4:     "use strict";

   5:  

   6:     WinJS.Binding.optimizeBindingReferences = true;

   7:  

   8:     var app = WinJS.Application;

   9:     var activation = Windows.ApplicationModel.Activation;

  10:  

  11:     app.onactivated = function (args) {

  12:         if (args.detail.kind === activation.ActivationKind.launch) {

  13:             if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {

  14:                 // TODO: This application has been newly launched. Initialize

  15:                 // your application here.

  16:             } else {

  17:                 // TODO: This application has been reactivated from suspension.

  18:                 // Restore application state here.

  19:             }

  20:             args.setPromise(WinJS.UI.processAll());

  21:         }

  22:     };

  23:  

  24:     app.oncheckpoint = function (args) {

  25:         // TODO: This application is about to be suspended. Save any state

  26:         // that needs to persist across suspensions here. You might use the

  27:         // WinJS.Application.sessionState object, which is automatically

  28:         // saved and restored across suspension. If you need to complete an

  29:         // asynchronous operation before your application is suspended, call

  30:         // args.setPromise().

  31:     };

  32:  

  33:     app.start();

  34: })();

 

Let’s start by adding the nessesary functions required by the game loop. I will follow the structure that I’m used to from programming directx and XNA.

Add the following lines into the default.js file, just above the app.oncheckpoint = function (args) { line of code.

   1: function initialize() {

   2: }

   3:  

   4: function loadContent() {

   5: }

   6:  

   7: function gameLoop() {

   8: }

   9:  

  10: function update() {

  11: }

  12:  

  13: function draw() {

  14: }

The entire default.js file now looks like this:

   1: // For an introduction to the Blank template, see the following documentation:

   2: // http://go.microsoft.com/fwlink/?LinkId=232509

   3: (function () {

   4:     "use strict";

   5:  

   6:     WinJS.Binding.optimizeBindingReferences = true;

   7:  

   8:     var app = WinJS.Application;

   9:     var activation = Windows.ApplicationModel.Activation;

  10:  

  11:     app.onactivated = function (args) {

  12:         if (args.detail.kind === activation.ActivationKind.launch) {

  13:             if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {

  14:                 // TODO: This application has been newly launched. Initialize

  15:                 // your application here.

  16:             } else {

  17:                 // TODO: This application has been reactivated from suspension.

  18:                 // Restore application state here.

  19:             }

  20:             args.setPromise(WinJS.UI.processAll());

  21:         }

  22:     };

  23:  

  24:     function initialize() {

  25:     }

  26:  

  27:     function loadContent() {

  28:     }

  29:  

  30:     function gameLoop() {

  31:     }

  32:  

  33:     function update() {

  34:     }

  35:  

  36:     function draw() {

  37:     }

  38:  

  39:     app.oncheckpoint = function (args) {

  40:         // TODO: This application is about to be suspended. Save any state

  41:         // that needs to persist across suspensions here. You might use the

  42:         // WinJS.Application.sessionState object, which is automatically

  43:         // saved and restored across suspension. If you need to complete an

  44:         // asynchronous operation before your application is suspended, call

  45:         // args.setPromise().

  46:     };

  47:  

  48:     app.start();

  49: })();

Now, after initialize is done doing his work, loadContent should start. Once all the content is loaded, we will start the game loop. The gameLoop() will first call the update function, and then call the draw() function. update() will contain the game logic, and draw will handle the drawing.

Update the gameLoop() function to call update() and draw():

   1: function gameLoop() {

   2:     update();

   3:     draw();

   4: }

The last thing we need to do here before creating a drawable canvas is to make sure that our game loop starts once the OS has booted up our app and got the system ready to run it. We do this by using the DOMContentLoaded event. Once the app is ready, it will call the initialize function.

document.addEventListener("DOMContentLoaded", initialize, false);

   1: app.oncheckpoint = function (args) {

   2:     // TODO: This application is about to be suspended. Save any state

   3:     // that needs to persist across suspensions here. You might use the

   4:     // WinJS.Application.sessionState object, which is automatically

   5:     // saved and restored across suspension. If you need to complete an

   6:     // asynchronous operation before your application is suspended, call

   7:     // args.setPromise().

   8: };

   9:  

  10: document.addEventListener("DOMContentLoaded", initialize, false);

  11:  

  12: app.start();

 

 

Creating a drawable surface using the Canvas

Before we can do any drawing, we must add a canvas that we will use to draw on. The canvas will fill the entire screen width and height, making this into a fullscreen app.

Open “default.js” and replace the line <p>Content goes here</p> in the <body> tag with <canvas id="gameCanvas"></canvas>:

   1: <body>

   2:     <canvas id="gameCanvas"></canvas>

   3: </body>

This gives us a canvas with the id gameCanvas. We can use gameCanvas to reference to this canvas from default.js. But how do we draw to it?

Move back to the default.js file and add a few global variables, put these somewhere in the top of the file like below the line var activation = Windows.ApplicationModel.Activation; :

   1: var canvas, context;

Next we need to create a reference to the canvas element gameCanvas and grab the context to it.

This is done in the initialize() function. Make it look like this:

   1: function initialize() {

   2:     canvas = document.getElementById("gameCanvas");

   3:     canvas.width = window.innerWidth;

   4:     canvas.height = window.innerHeight;

   5:     context = canvas.getContext("2d");

   6: }

 

This gets the element gameCanvas, sets the resolution to fill the entire screen and gets the 2d context of it.

Next, we need a stage for our game. A stage is class that comes with CreateJS and helps you create “your world”. It needs a reference to the canvas it will draw to and is used to add items like images and soundeffects to your game.

Add a new variable called gameStage as a global variable:

   1: var canvas, context;

   2: var gameStage;

Below the code that gets the canvas and context, we will create the stage object:

   1: function initialize() {

   2:     canvas = document.getElementById("gameCanvas");

   3:     canvas.width = window.innerWidth;

   4:     canvas.height = window.innerHeight;

   5:     context = canvas.getContext("2d");

   6:  

   7:     gameStage = new createjs.Stage(canvas);

   8: }

 

Loading images

Now that we got a canvas and a stage to draw to, we can start loading images and drawing them in the canvas.

Once the initialize() function is done, it must call loadContent. This function will use PreloadJS to load images, and create objects that you can insert on your gameStage.

Make initialize() call the loadContent() function:

   1: function initialize() {

   2:     canvas = document.getElementById("gameCanvas");

   3:     canvas.width = window.innerWidth;

   4:     canvas.height = window.innerHeight;

   5:     context = canvas.getContext("2d");

   6:  

   7:     gameStage = new createjs.Stage(canvas);

   8:  

   9:     loadContent();

  10: }

Before we can load anything, we need to create a new global variable called “preload”.

   1: var canvas, context;

   2: var gameStage;

   3: var preload;

In loadContent(), we create an instance of the PreloadJS class:

   1: function loadContent() {

   2:     preload = new createjs.PreloadJS();

   3: }

The PreloadJS library works this way. It will need a function that it will call once all the content has been loaded. It will also need a manifest array that contains all the filenames it will load.

   1: function loadContent() {

   2:     preload = new createjs.PreloadJS();

   3:     preload.onComplete = prepareStage;

   4:  

   5:     var manifest = [

   6:         { id: "logoScreen", src: "images/GFX/LogoScreen.png" },

   7:         { id: "floor", src: "images/GFX/floor.png" },

   8:         { id: "ghost", src: "images/GFX/Ghost.png" },

   9:         { id: "playerIdle", src: "images/GFX/PlayerIdle.png" }

  10:     ];

  11:  

  12:     preload.loadManifest(manifest);

  13: }

Once the manifest has been loaded, a function called prepareStage will be called. In this function I will simply use the preload object to get images and create instances of them.

Once the stage is ready, we can start the gameLoop() function.

To add images to the stage, we must create a few more global variables:

   1: var canvas, context;

   2: var gameStage;

   3: var preload;

   4:  

   5: var logoScreenImage, logoScreenBitmap;

The logoScreenImage will containg the file, and the logoScreenBitmap will contain the image the file contained. Create we create a new function called prepareStage. To load an image and insert it into the canvas, we use the preload instance and grab what we want from it:

   1: function prepareStage() {

   2:     logoScreenImage = preload.getResult("logoScreen").result;

   3:     logoScreenBitmap = new createjs.Bitmap(logoScreenImage);

4: gameStage.addChild(logoScreenBitmap);

   5: }

 

Now, the stage contains one image and it’s default located at the position 0,0 (top-left corner of the screen. When you render an image, the top-left corner of the image is rendered at the given coordinate, not the center of the image.

image

The final part of our rendering engine is to make sure that the gameLoop function ticks at a framerate that good enough for a game.

To do this, we can use the Ticker-class from CreateJS. It will help us with the timing of our game.

   1: function prepareStage() {

   2:     logoScreenImage = preload.getResult("logoScreen").result;

   3:     logoScreenBitmap = new createjs.Bitmap(logoScreenImage);

   4:     gameStage.addChild(logoScreenBitmap);

   5:  

   6:     createjs.Ticker.setInterval(window.requestAnimationFrame);

   7:     createjs.Ticker.addListener(gameLoop);

   8: }

This creates a new interval. At each tick of this interval, the gameLoop function is called. the windows.requestAnimationFrame makes sure that we only draw the frames that we need to draw.

Now, the final thing we need to do to render our stage is to update our draw() function so it updates the stage:

   1: function draw() {

   2:     gameStage.update();

   3: }

 

And thats it!

Now you got a working game engine template. You should save this away as a different project, so you wont need to do this entire thing again when you create a new game. Smilefjes

If you compile and run your app, you will first see the splashscreen and then the main screen image rendered accross the entire screen (but it will not scale to all resolutions yet. More on this in the next tutorial).

image

Listing 1 – the entire default.js file containing the engine that makes our game go around and around:

   1: // For an introduction to the Blank template, see the following documentation:

   2: // http://go.microsoft.com/fwlink/?LinkId=232509

   3: (function () {

   4:     "use strict";

   5:  

   6:     WinJS.Binding.optimizeBindingReferences = true;

   7:  

   8:     var app = WinJS.Application;

   9:     var activation = Windows.ApplicationModel.Activation;

  10:  

  11:     var canvas, context;

  12:     var gameStage;

  13:     var preload;

  14:  

  15:     var logoScreenImage, logoScreenBitmap;

  16:  

  17:     app.onactivated = function (args) {

  18:         if (args.detail.kind === activation.ActivationKind.launch) {

  19:             if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {

  20:                 // TODO: This application has been newly launched. Initialize

  21:                 // your application here.

  22:             } else {

  23:                 // TODO: This application has been reactivated from suspension.

  24:                 // Restore application state here.

  25:             }

  26:             args.setPromise(WinJS.UI.processAll());

  27:         }

  28:     };

  29:  

  30:     function initialize() {

  31:         canvas = document.getElementById("gameCanvas");

  32:         canvas.width = window.innerWidth;

  33:         canvas.height = window.innerHeight;

  34:         context = canvas.getContext("2d");

  35:  

  36:         gameStage = new createjs.Stage(canvas);

  37:  

  38:         loadContent();

  39:     }

  40:  

  41:     function loadContent() {

  42:         preload = new createjs.PreloadJS();

  43:         preload.onComplete = prepareStage;

  44:  

  45:         var manifest = [

  46:             { id: "logoScreen", src: "images/GFX/LogoScreen.png" },

  47:             { id: "floor", src: "images/GFX/floor.png" },

  48:             { id: "ghost", src: "images/GFX/Ghost.png" },

  49:             { id: "playerIdle", src: "images/GFX/PlayerIdle.png" }

  50:         ];

  51:  

  52:         preload.loadManifest(manifest);

  53:     }

  54:  

  55:     function prepareStage() {

  56:         logoScreenImage = preload.getResult("logoScreen").result;

  57:         logoScreenBitmap = new createjs.Bitmap(logoScreenImage);

  58:         gameStage.addChild(logoScreenBitmap);

  59:  

  60:         createjs.Ticker.setInterval(window.requestAnimationFrame);

  61:         createjs.Ticker.addListener(gameLoop);

  62:     }

  63:  

  64:     function gameLoop() {

  65:         update();

  66:         draw();

  67:     }

  68:  

  69:     function update() {

  70:     }

  71:  

  72:     function draw() {

  73:         gameStage.update();

  74:     }

  75:  

  76:     app.oncheckpoint = function (args) {

  77:         // TODO: This application is about to be suspended. Save any state

  78:         // that needs to persist across suspensions here. You might use the

  79:         // WinJS.Application.sessionState object, which is automatically

  80:         // saved and restored across suspension. If you need to complete an

  81:         // asynchronous operation before your application is suspended, call

  82:         // args.setPromise().

  83:     };

  84:  

  85:     document.addEventListener("DOMContentLoaded", initialize, false);

  86:  

  87:     app.start();

  88: })();

 

In the next tutorial, we will start on the logic of the game. This means implementing the game itself, input and handling of the player and enemies.

Download the source of the game here:
http://sdrv.ms/T2KTFg

About these ads
This entry was posted in Game programming, Tutorial, Windows 8. Bookmark the permalink.

11 Responses to HTML5 Game Development for Windows 8 #1: Getting started

  1. Pingback: HTML5 Game Starter Kit for Windows 8 | digitalerr0r

  2. Richard Bown says:

    Hi there, nice blog – I’ll be following you! I’m doing the WOWZAPP thing today and noticed a typo. In section “Creating a drawable surface using the Canvas” you want to reference default.html rather than default.js in the first section.

  3. Pingback: Windows 8 Games with CreateJS Tutorials & Resources « skater coder

  4. BeaconEternal says:

    If you got error:
    Stage undefined, Bitmap undefined.
    do this

    replace Stage – > createjs.Stage
    replace Bitmap -> createjs.Bitmap

    and so on.
    if Text undefined / can’t .. object?

    replace Text -> createjs.Text

  5. scramble says:

    whoah this blog is wonderful i really like studying your articles.
    Stay up the great work! You know, lots of people are
    looking round for this info, you could aid them greatly.

  6. Pingback: Game Starterkit for Windows 8 with leaderboard in Windows Azure | digitalerr0r

  7. Magnificent site. Plenty of helpful info here. I am sending it to several buddies ans additionally sharing in delicious.
    And naturally, thank you to your effort!

  8. Pingback: You can lead a dev to... "Game Starter Kit for Windows 8 with leaderboard in Windows Azure" - Windows Azure Blog

  9. It’s amazing in favor of me to have a web page, which is helpful designed for my know-how. thanks admin

  10. Howdy just wanted to give you a quick heads up. The words in your article seem to be running off the screen in Firefox.
    I’m not sure if this is a format issue or something to do with web browser compatibility but I figured I’d post to let you know.
    The style and design look great though! Hope you get the issue resolved soon.
    Kudos

  11. abhinav says:

    i am getting error
    like following.. please help

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s