Building games for the web

Ash Kyd

How to make games

How to teach yourself to make games

Making games is easy?

Kinda

Sorta

Once you get the hang of it

Making games is easy!

Make something achievable

Work to your strengths

Take ALL of the shortcuts

Some basics

  • 2D Canvas
  • WebGL
  • Then all the libraries on top of those

Some concepts

  • Rendering
  • Interaction
  • Sound
  • Physics
  • Tweening
  • Pathfinding
  • Particles
  • Terrain generation
  • And so much more!

My story: Road Blocks!

Something achievable

Work to your strengths

  • Prototype with familiar tech
  • Programmer art is awesome
  • Polish comes second to function

In my case

  • I'm all about isometric art
  • You can do some cool stuff in 13kb
  • Stacking boxes is fun

Stacking boxes is fun

Code: ~420 bytes

var cubes = [
    [1, 2.0 ,1,1,1,.7,'#C8AF9E'],
    [1, 1.3 ,1,1,1,.3,'#7DD17D'],
    [1, 0.5 ,.1,.1,.1,.1,'#DFA656'],
    [1, 0.45,.3,.3,.3,.05,'#84C171'],
    [1, 0.35,.2,.2,.2,.05,'#84C171'],
    [1, 0.25,.1,.1,.1,.05,'#84C171'],
];

function draw(){
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  var wobble = 1 + Math.max(Math.sin(Date.now()/250), 0)/10;

  var cubeSize = 150;
  cubes.forEach(function(cube){
      drawCube(
        cube[0] * canvas.width/2,
        cube[1] * cubeSize * wobble,
        cube[3] * cubeSize, // x1
        cube[4] * cubeSize, // x2
        cube[5] * cubeSize, // y
        cube[6], // color
        ctx
      );
  });
  requestAnimationFrame(draw);
}
draw();

Take all the shortcuts!

  • NPM is full of goodies
  • You don't need to reinvent the wheel (or the physics)
  • Do what you know best

HEY COOL LET'S USE THIS

Attractive attractors

Code: ~840 bytes

var canvas = document.querySelector('.physics canvas');
canvas.width = window.innerWidth * 0.66;
canvas.height = canvas.width * 0.66;
var ctx = canvas.getContext('2d');

var physics = new Physics();

var radius = 50;
var mass = 25;

var x1 = canvas.width * 0.25;
var x2 = canvas.width * 0.75;
var y = canvas.height / 2;

var a = physics.makeParticle(mass, x1, y);
var b = physics.makeParticle(mass, x2, y);

// Create an attraction between the particles.

// The strength of the bond between two particles.
var strength = 50000;

// The proximity at which the attraction will be enabled.
var minDistance = canvas.width;

// Make the attraction and add it to physics
var attraction = physics.makeAttraction(a, b, strength, minDistance);
var cubeSize = 80;

var update = {};

var render = function() {

    if (canvas.class !== 'active') {
        return;
    }

    ctx.clearRect(0, 0, canvas.width, canvas.height);

    var x1 = a.position.x;
    var y1 = a.position.y;

    var x2 = b.position.x;
    var y2 = b.position.y;

    drawCube(
        x1 - cubeSize * 2,
        y1,
        cubeSize, // x1
        cubeSize, // x2
        cubeSize, // y
        '#ff8888', // color
        ctx
    );

    drawCube(
        x2 - cubeSize * 2,
        y2,
        cubeSize, // x1
        cubeSize, // x2
        cubeSize, // y
        '#8888ff', // color
        ctx
    );

    if (b.resting()) {
        a.position.set(x1, y);
        b.position.set(x2, y);
    }

};

// Bind the render function to when physics updates.
physics.onUpdate(render);

// Render a posterframe.
render();

physics.toggle();

// store our physics object on the canvas so we can access it later
canvas.physics = physics;

Pathfinding

The code: ~770 bytes

function getIsometricPos(x, y, tileWidth) {
    return [
        (x - y) * (tileWidth / 2), (x + y) * (tileWidth / 4)
    ];
}

// Animation function
function draw() {
    // Create a grid
    var grid = new PF.Grid(10, 10);

    // Create some obstacles
    for (var i = 0; i < 10; i++) {
        var x = Math.round(Math.random() * 9);
        var y = Math.round(Math.random() * 9);
        grid.setWalkableAt(x, y, false);
    }

    // Find a path
    var finder = new PF.AStarFinder();
    var path = finder.findPath(0, 0, 9, 9, grid);

    // start drawing
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    var cubeSize = canvas.width / 20;
    grid.nodes.forEach(function(row, x) {
        row.forEach(function(col, y) {
            // Get x and y coords to draw at.
            var pos = getIsometricPos(x, y, cubeSize * 2);

            // Pick a colour
            var color = (x + y) % 2 === 0 ? '#00ff00' : '#66ff66';
            if (col.walkable === false) {
                color = '#333333';
            }

            // Is this point in the path?
            // Todo: make this more efficient.
            path.forEach(function(point) {
                if (point[0] === y && point[1] === x) {
                    color = '#8888ff';
                }
            });

            // Draw the cube
            drawCube(
                canvas.width / 2 + pos[0],
                canvas.height / 4 + pos[1],
                cubeSize,
                cubeSize,
                cubeSize * (col.walkable ? 1 : 1.5),
                color,
                ctx
            );
        });
    });


    setTimeout(draw, 2000);
}
draw();

Point is…

  • You can rapidly prototype stuff
  • without having to learn a framework

Useful libraries

2Dpixi.jsCanvas & WebGL abstraction
2DPhaserGame engine Built on Pixi
3Dthree.jsWebGL engine
3DBabylon.jsWebGL engine
-CordovaGo mobile!

Useful resources

Mozilla HacksArticles & tutorials
phaser.toBunch of tutorials
js13k13 kb game competition
One Game a MonthChallenge to finish a game every month
Global Game JamCreate a game in a team over a weekend

Building games for the web

http://ash.ms/rb - play now

http://ash.ms/rb