Build a Game in JavaScript Starring Your Cat

Fbf1757de2e4b442a65273b6d0469dbd?s=47 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.

Fbf1757de2e4b442a65273b6d0469dbd?s=128

Matt McKenna

February 16, 2016
Tweet

Transcript

  1. Build a Game in JavaScript Starring Your Cat Omada Health

    February 16, 2016 1 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > matt@mtmckenna.com @mattmckenna
  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!
  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!
  4. Croissant the Pizza Cat • Let's play real quick! •

    http://runner.mtmckenna.com/ • https://github.com/mtmckenna/croissant-runner/ 4 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  5. The Next 30 Minutes • Getting started with a toolchain.

    • Create a game loop to draw on the <canvas>. • Animate an image on the <canvas>. • What about audio? • Handle user input. • Deploy your game! 5 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  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 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  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/
  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 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > </workspace/croissant-runner/ ▾ 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
  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.
  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(); }
  11. draw() • Clear the <canvas>'s context (more on <canvas> 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(); }
  12. Draw on the <canvas> • <canvas> 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);
  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!
  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 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  15. setInterval 15 > > > > > > > >

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

    > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 0 seconds 1 second 0.5 seconds gameLoop runs gameLoop runs, but the browser isn't ready to redraw
  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
  18. Go, Croissant! 18 > > > > > > >

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

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

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

    > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  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 <canvas>. Next 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
  24. Audio • Audio in Javascript is ughghghhhhhh. • You have

    a couple options: The HTML5 <audio> tag and the Web Audio API. • The <audio> 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 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  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
  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)); ... }
  27. Build Production HTML/JS with Webpack 27 > > > >

    > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > $ webpack -p
  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 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  29. Netlify Drag and Drop So Easy 29 > > >

    > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Click! Drag the dist folder! Click! Your game! Here!
  30. Takeaways • Configure a toolchain before starting. • Use <canvas>

    and requestAnimationFrame for your game loop. • Use the Web Audio API for audio. • Deploy on a static web host. 30 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  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 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  32. We Need... 32 > > > > > > >

    > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Next week: Build a Game in Ember Starring Your Cat!
  33. Links • https://developer.mozilla.org/en-US/docs/Games • http://ludumdare.com/compo/tools/ 33 > > > >

    > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  34. Graphics/Audio Tools • Dots (iOS) • Pixen (OS X) •

    Pixelmator (OS X) • bfxr (web) • Audacity (OS X / Windows) 34 > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >
  35. Croissant Stickers 35 > > > > > > >

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

    > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >