HTML5 Game Development and Dojo

Luis Montes
@MONTESLU

September 2011

Web based gaming (previous decade)

In order to play this you must first install...



don't bother clicking here, the plugin isn't available for your Operating System and Hardware

So what changed?

Open Standards!

Typical Game Engine Functionality

Enough talking, Show me some code...

Basic drawing with HTML5 <Canvas>

<canvas id='myCanvas' width='300' height='300' ></canvas>
<script type='text/javascript'> 
     var img = new Image();
     dojo.connect(img,'onload',function(){
	      var canvas = dojo.byId('myCanvas'); 
	      var context = canvas.getContext('2d');
	      
	      context.fillStyle = "#000044"; 
	      context.fillRect(0,0,canvas.width,canvas.height);	      
	      context.drawImage(img,50,120);
     });
     img.src = 'images/dojo_white.png'; 
</script>

Basic drawing with HTML5 <Canvas>

Basic Animation with Canvas

    <script type='text/javascript'>  
          var img = new Image();
          dojo.connect(img,'onload',function(){
              var canvas = dojo.byId('myCanvas'); 
              var context = canvas.getContext('2d');
              for(var i = 0; i < 250; i++){
		          context.fillStyle = "#000044"; 
		          context.fillRect(0,0,canvas.width,canvas.height);		          
		          context.drawImage(img,i,i);
		      }
          });
          img.src = 'images/dojo_white.png'; 
    </script>

Basic Animation with Canvas?

We need a Game Loop!

An Simple HTML5 Game Loop

<script type='text/javascript'>

var prevTime;
function gameLoop() {
    
    var currTime = new Date().getTime();
    elapsedTime = currTime - prevTime;            
    prevTime = currTime;	
	
    handleInput(elapsedTime);
    update(elapsedTime);
    draw(context);		
}
      
</script>

What runs the game loop?

Game Loop Timing

<script type='text/javascript'>
//Paul Irish's shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       || 
		  window.webkitRequestAnimationFrame || 
		  window.mozRequestAnimationFrame    || 
		  window.oRequestAnimationFrame      || 
		  window.msRequestAnimationFrame     || 
		  function(/* function */ callback, /* DOMElement */ element){
               window.setTimeout(callback, 1000 / 60);
		  };
})();
      
(function animloop(){
		  thisgame.gameLoop();
		  requestAnimFrame(animloop, canvas);
		})();		      
</script>

Animation with a game loop

Input Management - Mapping

<script type='text/javascript'>

game.initInput: function(im) {  			  
    im.addKeyAction(dojo.keys.LEFT_ARROW);
    im.addKeyAction(dojo.keys.RIGHT_ARROW);
    im.addKeyAction(dojo.keys.UP_ARROW);
    im.addKeyAction(dojo.keys.DOWN_ARROW);
};

</script>

Input Management - dealing with events

<script type='text/javascript'>
handleInput: function(im){
        /* handle left and right movement */
        if(im.keyActions[dojo.keys.LEFT_ARROW].isPressed()){
		    sprite.dx = sprite.maxVelocity * -1;
		}
		else if(im.keyActions[dojo.keys.RIGHT_ARROW].isPressed()){
		    sprite.dx = sprite.maxVelocity;
		}
		else{
		    sprite.dx = 0;
		}
	/* handle up and down */
	...
};      
</script>

Input Management

Sprite Animations

<script type='text/javascript'>
    //Animation object update
    update: function(elapsedTime) {
        if (this.frames.length > 1) {
            this.animTime += elapsedTime;

            if (this.animTime >= this.totalDuration) {
                this.animTime = this.animTime % this.totalDuration;
                this.currFrameIndex = 0;
            }

            while (this.animTime > this.getFrame(this.currFrameIndex).endTime) {
                this.currFrameIndex++;
            }
        }
    },   
</script>

Sprite Animations

<script type='text/javascript'>
resourceManager = new mwe.ResourceManager({
        			imageDir: 'images/'
        		});
        	  swi = resourceManager.loadImage('walking.png');
        	  
        	  sprite = new mwe.Sprite({x:100,y:100, w:96, h: 96, dx:0, dy: 0,
      		        xStartVelocity: 0.5, yStartVelocity: 0.5
      		        });
        	  sprite.anim = new mwe.Animation().createFromTile(8,100,swi,96,96);   
</script>

Sprite Animations

HTML5 Audio

HTML5 Audio using SoundManager2

<script type='text/javascript'>

soundManager.url = 'swf/';
soundManager.useHTML5Audio = true;
soundManager.debugMode = false;	
soundManager.onready(function() {
// Ready to use; soundManager.createSound() etc. can now be called.

    anvilSound = soundManager.createSound({
        id: 'anvilSound',
        url: 'sounds/anvil.mp3'
        // onload: [ event handler function object ],
        // other options here..
    });

});      
</script>

Physics - Box2D

Box2d simple demo

lanuch

BoxdD rendered using dojo components

<script type='text/javascript'>
dojo.declare("Entity", null, {
        id: 0,
        x: 0,
        y: 0,
        angle: 0,
        center: 0,
        constructor: function(/* Object */args){
            dojo.safeMixin(this, args);
        },
        update: function(state){
            dojo.mixin(this, state);
        },
        draw: function(ctx){
        ...      
</script>

BoxdD rendered using dojo components -demo

lanuch silly demo

3D

Three.js - setting up the secene and renderer

<script type='text/javascript'>

var container = dojo.byId('container');
renderer = new THREE.WebGLRenderer();
camera = new THREE.Camera(VIEW_ANGLE,ASPECT, NEAR, FAR  );
scene = new THREE.Scene();
camera.position.z = 300;
renderer.setSize(WIDTH, HEIGHT);
dojo.place(renderer.domElement,container);

//more setup... create mesh object, setup lighting...

renderer.render(scene, camera);
     
</script>
launch three.js demo

What about mobile?

The state of HTML5 APIs on mobile devices...

CanIUse.com

Quick word on Networking...

Thank you!