How Ryan Became a Big Time Game Dev

(an introduction to html5 for games)

Presented by Billy Lamberta (Ryan Gosling not affiliated)

Poor Ryan has no one to play with …

“If I make a game, I’ll have lots of friends!”

“But where to start?!”

Researching the many languages, platforms, and frameworks.

“But to run on all my friend’s phones …

I need Obj-C AND Java AND more?!”

Stop your crying!

Let’s try HTML5!

HTML 4.01 and XHTML 1.1
Were Getting Out of Hand

As the web becomes more multi-media focused,
expectations change, and new features are desired.

The Document Object Model

CSS Style Sheets

Fancy clothes for your DOM elements.

JavaScript and the DOM

JavaScript and HTML5

They Make the Cutest Couple

Much of what we’re calling HTML5
are just JavaScript APIs.

Selling Points

  • Write once, run everywhere.
  • Lots of great documentation provided by MDN and others.
  • Lots of examples online and questions answered.

A Minimal HTML5 Document

  <!doctype html>
  <html>
    <head>
      <meta charset="utf-8">
      <title></title>
    </head>
    <body>
      <p>Hey Girl</p>
      <script>
        document.addEventListener('DOMContentLoaded', function () {
          "use strict";
          //our javascript code here ...
        });
      </script>
    </body>
  </html>

Let’s Check Out Some …

HTML5 Media Elements

Typography

  <!doctype html>
  <html>
    <head>
      ...
      <style>
       p {
         font: 400 130px/0.8 'Cookie', sans-serif;
       }
       @font-face {
         font-family: 'Cookie';
         font-style: normal;
         font-weight: 400;
         src: local('Cookie-Regular'), url(http://example.com/font.woff) format('woff');
       }
      </style>
    </head>
    <body>
      <p>Hey Girl</p>
    </body>
  </html>

Hey Girl

Video

  <video controls poster="screenshot.png">
    <source src="hello.webm" type="video/webm;codecs='vp8,vorbis'">
    <source src="hello.mp4" type="video/mp4;codecs='avc1.42E01E,mp4a.40.2'">
    <track src="hello-en.vtt" label="English subtitles" 
           kind="subtitles" srclang="en" default></track>
    <p>Fallback content if browser does not support the video tag.</p>
  </video>

Audio

  <audio id="demo" src="hey-girl.mp3" controls loop></audio>
  <script>
    var audio = document.getElementById('demo');
    audio.play();
  </script>

WebRTC

(Real-Time Communication)

  • Camera and microphone access
  • Peer-to-peer connections
  • Data channels

Voice calls, video chat, file sharing …

“OK! Now I’ll make Flappy MerLion!”

We’ll Need Some HTML5 Animation APIs …

CSS Animations

  @keyframes slidein {
    from {
      margin-left: 100%;
      width: 100%;
    }
    75% {
      font-size: 300%;
      margin-left: 25%;
      width: 150%;
    }
    to {
      margin-left: 0%;
      width: 100%;
    }
  }
  p {
    animation-duration: 2s;
    animation-name: slidein;
    animation-iteration-count: infinite;
    animation-direction: alternate;
  }

Hey Girl

Canvas

2D Direct Drawing API

  <!doctype html>
  <html>
    <head>...</head>
    <body>
      <canvas id="myCanvas" width="512" height="512"></canvas>
      <script>
        document.addEventListener('DOMContentLoaded', function () {
          "use strict";
          var canvas = document.getElementById('myCanvas');
          ...
        });
      </script>
    </body>
  </html>

Canvas

2D Direct Drawing API

  document.addEventListener('DOMContentLoaded', function () {
    "use strict";
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');

    ctx.fillStyle = "#f00";
    ctx.beginPath();
    ctx.moveTo(75, 40);
    ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
    ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
    ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
    ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
    ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
    ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
    ctx.fill();
  });

Canvas

And add an animation loop …

  document.addEventListener('DOMContentLoaded', function () {
    "use strict";
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    var SCREEN_WIDTH = canvas.width;
    var SCREEN_HEIGHT = canvas.height;

    (function drawFrame () {
      window.requestAnimationFrame(drawFrame);
      ctx.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
      ...
    }());
  });

Canvas

And add an animation loop …

  ...
  function drawHeart () {...}
    
  (function drawFrame () {
    window.requestAnimationFrame(drawFrame);
    ctx.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
    var n = centerScale + Math.sin(angle) * range;
      
    for (var i = 0; i < SCREEN_WIDTH; i += 102) {
      ctx.translate(i, i);
      ctx.scale(n, n);
      drawHeart();
      ...
    }

    ctx.translate(centerX, centerY);
    ctx.rotate(j * Math.PI/180);
    ctx.drawImage(img, -img.width/2, -img.height/2);
    ...
  }());

(We'll see the canvas more tomorrow.)

WebGL

GPU programming in the browser

  <script type="x-shader/x-fragment">
    precision mediump float;

    void main(void) {
      gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
  </script>
  <script type="x-shader/x-vertex">
    attribute vec3 aVertexPosition;
    uniform mat4 uMVMatrix;
    uniform mat4 uPMatrix;

    void main(void) {
      gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
    }
  </script>
  var gl = canvas.getContext('webgl');
  gl.shaderSource(shader, shaderScript.textContent);
  gl.compileShader(shader);
  var shaderProgram = gl.createProgram();
  gl.attachShader(shaderProgram, vertexShader);
  gl.linkProgram(shaderProgram);
  gl.useProgram(shaderProgram);
  gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);
  shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
  ...

WebGL

Steep learning curve, but you can do cool stuff.

Better Performance

Binary Data in the Browser

  var i8   = new Int8Array(64);
  var u32  = new Uint32Array(16);
  var f64a = new Float64Array(8);

  var pixels = new Uint8Array(320*240*4); //320x240 RGBA image
  gl.readPixels(0, 0, 320, 240, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

  /*
  struct someStruct {
    unsigned long id;
    char username[16];
    float amountDue;
  };
  */
  var buffer = new ArrayBuffer(24);
  //read data into buffer ...
  var idView = new Uint32Array(buffer, 0, 1);
  var usernameView = new Uint8Array(buffer, 4, 16);
  var amountDueView = new Float32Array(buffer, 20, 1);

Game APIs


  • Gamepad

  • Pointer Lock

  • Fullscreen Mode

Lots of APIs!

  • Geolocation

  • Networking

  • File System

  • Offline Support

  • Vibration

  • Orientation

  • Battery Status

  • Light Events

  • Proximity Events

Share With Your Friends

  • The Simple—but Useful—Link

  • Wrap in a WebView for iOS and Android

  • FirefoxOS

And What Do Ya Know …

The Game is a Hit!

THE END

By Billy Lamberta / lamberta.org