$30 off During Our Annual Pro Sale. View Details »

Build a Game in JavaScript Starring Your Cat

Matt McKenna
February 16, 2016

Build a Game in JavaScript Starring Your Cat

Have you ever wanted to make a game in JavaScript starring your cat? This tech talk goes over some ideas for how you might make that happen using ES6, canvas, Webpack, and Netlify.

Matt McKenna

February 16, 2016
Tweet

More Decks by Matt McKenna

Other Decks in Programming

Transcript

  1. Build a Game in JavaScript
    Starring Your Cat
    Omada Health
    February 16, 2016
    1
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    [email protected]
    @mattmckenna

    View Slide

  2. Why Build a Game in JS?
    • Haven't you always wanted to make a game?
    • You probably already know JS, so you can get
    started right away.
    • JS apps are relatively easy to deploy.
    • JS apps "work" on all devices.
    • It's fun!
    2
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    Croissant!

    View Slide

  3. Croissant -- this is you!
    Croissant the Pizza Cat
    • Here's a screenshot of a game built in JS, starring Croissant:
    3
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    Pizzas -- touch these for points!
    Cat beds -- jump to avoid these!

    View Slide

  4. Croissant the Pizza Cat
    • Let's play real quick!
    • http://runner.mtmckenna.com/
    • https://github.com/mtmckenna/croissant-runner/
    4
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  5. The Next 30 Minutes
    • Getting started with a toolchain.
    • Create a game loop to draw on the .
    • Animate an image on the .
    • What about audio?
    • Handle user input.
    • Deploy your game!
    5
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  6. Getting Started with a Toolchain
    • We need a toolchain in order to...
    • ... combine and transpile our code (e.g. ES6 to ES5).
    • ... bundle our JS modules into one file.
    • ... create a minified version to deploy.
    • ... live reload your web browser on code changes.
    6
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  7. Let's Use Webpack
    7
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    $ webpack-dev-server --inline
    http://localhost:8080/
    webpack result is served from /
    content is served from /Users/
    mckenna/workspace/croissant-runner
    Hash: 523d4bb3ed182dcd831f
    Version: webpack 1.12.6
    Time: 2575ms
    $ npm start
    ... or create a shortcut!
    https://webpack.github.io/docs/tutorials/getting-started/

    View Slide

  8. What is Webpack?
    • Transforms/processes files like Gulp/Grunt
    • Bundles JS modules together into one file like
    Browserify
    • Turns your static assets (JS, CSS, images) into
    requirable modules e.g. "require('pizza.png');"
    • https://github.com/petehunt/webpack-howto
    8
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    ▾ app/
    ▾ audio/
    jump.wav
    nap.wav
    pizza.wav
    ▾ css/
    app.css
    ▾ html/
    favicon.ico
    index.html
    ▾ images/
    bird.png
    catbed.png
    cloud.png
    croissant-in-catbed.png
    croissant.png
    flower.png
    pizza.png
    ▾ js/
    app.js
    bird.js
    catbed.js
    cloud.js
    croissant.js
    flower.js
    game.js
    pizza.js
    sound-effect.js
    sprite-emitter.js
    sprite.js
    util.js
    ▸ dist/
    ▸ node_modules/
    package.json
    webpack.config.js

    View Slide

  9. The Game Loop
    • The game loop 1) calculates the position of sprites (Croissant, pizzas,
    etc.) and 2) draws them to the screen.
    9
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    setInterval(function() {
    update();
    draw();
    }, 1000.0/60.0);
    We'll do a
    better game
    loop in 4 slides.

    View Slide

  10. update()
    • Update the position of the sprites (e.g. Croissant, the pizzas, cat beds,
    etc.).
    • Check if anything is touching anything (e.g. if Croissant has touched a
    pizza/cat bed) and then do something (e.g. increase the score/end the
    game).
    10
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    update() {
    updateSpritePositions();
    handleCollisions();
    }

    View Slide

  11. draw()
    • Clear the 's context (more on in like 5 seconds).
    • Draw the randomly generated sprites (cat beds, pizzas, flowers, etc.).
    • Draw Croissant.
    11
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    draw() {
    context.clearRect(0, 0, 320, 240);
    drawGround();
    spriteEmitter.draw();
    drawScore();
    croissant.draw();
    }

    View Slide

  12. Draw on the
    • is an HTML element on which you can programmatically draw
    and animate whatever you want free of the DOM.
    • https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/
    Tutorial
    12
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    var canvas = document.createElement('canvas');
    document.body.appendChild(canvas);
    var context = canvas.getContext('2d');
    context.fillStyle = '#4f8f00';
    context.font = '15px Monaco';
    context.fillText('Hi Score: 19', 10, 25);

    View Slide

  13. A Better Game Loop in app.js
    13
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    var canvas = document.createElement('canvas');
    var game = new Game(canvas);
    var animReq;
    document.body.appendChild(canvas);
    function gameLoop() {
    animReq = window.requestAnimationFrame(gameLoop);
    game.update();
    game.draw();
    }
    gameLoop();
    This is what the next slide is about!
    Our game logic lives in here!

    View Slide

  14. requestAnimationFrame
    • Supported in modern browsers.
    • Calls the gameLoop function when the browser
    is ready to repaint the screen.
    • The browser will attempt to call gameLoop 60
    times a second (i.e. 60 FPS). No promises though.
    • requestAnimationFrame is better than
    setInterval.
    14
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  15. setInterval
    15
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    0 seconds 1 second
    0.5 seconds
    gameLoop runs
    gameLoop runs, but the browser isn't ready to redraw

    View Slide

  16. requestAnimationFrame
    16
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    0 seconds 1 second
    0.5 seconds
    gameLoop runs
    gameLoop runs, but the browser isn't ready to redraw

    View Slide

  17. Sprites
    • Nowadays, a sprite is generally a single bitmap graphic, usually with multiple frames
    of animation.
    • Animation is done by flipping through the images' frames like a flipbook or filmstrip.
    17
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    Frame 0
    Frame 1
    0px, 0px 30px, 0px 60px, 0px
    60px, 32px
    Both frames are in one image: croissant.png

    View Slide

  18. Go, Croissant!
    18
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  19. Go, Croissant!
    19
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  20. Go, Croissant!
    20
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  21. Go, Croissant!
    21
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  22. A Sprite ES6 Class
    22
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    export default class {
    constructor(type, context, startingPosition, size, velocity) { ... }
    cacheImage(type) { ... }
    createImage(type) { ... }
    get image() { ... }
    get currentFrame() { ... }
    intersects(anotherSprite) { ... }
    updatePosition() { ... }
    draw() { ... }
    }
    The draw method animates the sprite and
    places it on the . Next slide!

    View Slide

  23. Sprite's Draw Method
    23
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    draw() {
    this.context.drawImage(this.image,
    this.currentFrame * this.size.width, 0,
    this.size.width, this.size.height,
    this.pos.x, this.pos.y,
    this.size.width, this.size.height);
    }This is the part that flips
    between the two frames in
    croissant.png

    View Slide

  24. Audio
    • Audio in Javascript is ughghghhhhhh.
    • You have a couple options: The HTML5 tag
    and the Web Audio API.
    • The tag is simple to use, but nerfed on mobile.
    • So use Web Audio API.
    • https://developer.mozilla.org/en-US/docs/Web/API/
    Web_Audio_API
    24
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  25. A SoundEffect ES6 Class
    25
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    export default class {
    constructor(type, context, loop = false) { ... }
    loadAudio(path) { ... }
    decodeAudio(data) { ... }
    play() { ... }
    stop() { ... }
    }
    Web Audio API rigamarole
    How we'll actually play our audio

    View Slide

  26. Handling Input
    • "keydown" will work for keyboards and "touchstart" will work on mobile.
    • We have to use "bind" to make sure "this" isn't the window object.
    26
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    addInputListeners() {
    window.addEventListener('keydown', this.jump.bind(this));
    window.addEventListener('touchstart', this.jump.bind(this));
    ...
    }

    View Slide

  27. Build Production HTML/JS with Webpack
    27
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    $ webpack -p

    View Slide

  28. Deploying Your Game
    • Deploying JS-only apps is a (relative) breeze:
    no app store approval required and no app
    server to monitor.
    • Hosting options include Amazon S3, another
    CDN, your own web server, Surge.sh, Netlify.
    28
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  29. Netlify Drag and Drop So Easy
    29
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    Click!
    Drag the
    dist folder!
    Click!
    Your game!
    Here!

    View Slide

  30. Takeaways
    • Configure a toolchain before starting.
    • Use and
    requestAnimationFrame for your game
    loop.
    • Use the Web Audio API for audio.
    • Deploy on a static web host.
    30
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  31. Finishing Your Game
    • Our game isn't done!
    • We need tests!
    • We need menus!
    • We need to persist high scores!
    • We need a deploy/rollback strategy!
    • We need mobile and desktop apps!
    31
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  32. We Need...
    32
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    Next week: Build a Game in Ember
    Starring Your Cat!

    View Slide

  33. Links
    • https://developer.mozilla.org/en-US/docs/Games
    • http://ludumdare.com/compo/tools/
    33
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  34. Graphics/Audio Tools
    • Dots (iOS)
    • Pixen (OS X)
    • Pixelmator (OS X)
    • bfxr (web)
    • Audacity (OS X / Windows)
    34
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  35. Croissant Stickers
    35
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide

  36. Thank You!
    36
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    > >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >

    View Slide