Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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
  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 > > > > > > >

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