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

Make Games with JavaScript and Phaser

Make Games with JavaScript and Phaser

Shared at ScotlandJS 2014 in Edinburgh.

Gabe Hollombe

May 09, 2014
Tweet

More Decks by Gabe Hollombe

Other Decks in Programming

Transcript

  1. #sjsGabe Load assets • Load files via AJAX • Check

    when everything's done and fire an event
  2. #sjsGabe Draw things • Create a Canvas • Copy bits

    from loaded images onto 
 Canvas at appropriate coordinates
  3. #sjsGabe Animate things • How much time has elapsed since

    the last screen draw? • Which frame we should be on? • Copy that frame's image from my loaded asset to the canvas
  4. #sjsGabe Handle input • Keyboard events (just pressed? held down?)

    • Pointer events (tap? click? drag? multi-touch?) • Gamepad support?
  5. #sjsGabe Check for collisions • Track the width, height, and

    position for each thing • Compare nearby things to each other and look for overlap
  6. #sjsGabe Manage states • Title screen (tap to start) •

    Gameplay (whee!) • Game over (your final score)
  7. #sjsGabe Load assets • Load files via AJAX • Check

    when everything's done and fire an event Draw things • Create a Canvas • Copy bits from loaded images onto Canvas at appropriate coordinates Animate things • How much time has elapsed since the last screen draw? • Which frame we should be on? • Copy that frame's image from my loaded asset to the canvas Check for collisions • Track the width, height, and position for each thing • Compare nearby things to each other and look for overlap Handle input • Keyboard events (just pressed? held down?) • Pointer events (tap? click? drag? multi-touch?) Manage states • Title screen (tap to start) • Gameplay (whee!) • Game over (your final score) Play sounds • Make a new WebAudioContext • Handle multiple sounds playing at once Our Plan Of Attack
  8. #sjsGabe • 2D Game framework • Open Source • HTML5

    / JavaScript • For browser/desktop and mobile
  9. #sjsGabe Built by Photon Storm • Hobbyist game devs since

    2006 • Full-time on HTML5 games since 2012 • Richard Davey is lead dev (@photonstorm) • He was TD of Aardman Digital for 6 years • Phaser is what they use for all their games "[...] if you're saddled with a game framework that is maintained during someone's spare time or is on a slow release cycle, then it doesn't take long before things are very outdated." ! - Richard Davey (@photonstorm)
  10. #sjsGabe game = new Phaser.Game( 800, 600, Phaser.AUTO, '', {

    preload: preload, create: create, update: update })
  11. #sjsGabe game = new Phaser.Game( 800, 600, Phaser.AUTO, '', {

    preload: preload, create: create, update: update }) ! preload = -> game.load.image 'logo', 'phaser.png'
  12. #sjsGabe game = new Phaser.Game( 800, 600, Phaser.AUTO, '', {

    preload: preload, create: create, update: update }) ! preload = -> game.load.image 'logo', 'phaser.png' ! create = -> game.add.sprite(200, 200, 'logo')
  13. #sjsGabe game = new Phaser.Game( 800, 600, Phaser.AUTO, '', {

    preload: preload, create: create, update: update }) ! preload = -> game.load.image 'logo', 'phaser.png' ! create = -> game.add.sprite(200, 200, ‘logo') ! update = -> # things to do on each 'tick'
  14. #sjsGabe Disclaimer Obviously not really Plants vs Zombies (© 2009

    PopCap Games) But I’m using some of their sprites.
  15. #sjsGabe “Texture Atlas” Let you work with many related images

    (like animation frames) without making separate network requests for each image. • One large atlas image composed of many smaller images • Metadata about each small image inside the atlas image • File name • Width / Height • X/Y Position inside the atlas image
  16. #sjsGabe preload: -> this.game.load.atlasJSONHash 'sprites' 'assets/sprites.png' 'assets/sprites.json' ! create: ->

    this.game.add.image 0, 0, 'grass' sprite = game.add.sprite( 400, 400, 'sprites', ‘zombie1.png') !
  17. #sjsGabe preload: -> this.game.load.atlasJSONHash 'sprites' 'assets/sprites.png' 'assets/sprites.json' ! create: ->

    this.game.add.image 0, 0, 'grass' sprite = game.add.sprite( 400, 400, 'sprites', ‘zombie1.png') ! update: -> #nothing here yet...
  18. #sjsGabe game.zombies = game.add.physicsGroup( Phaser.Physics.ARCADE, this.game.world, 'zombies') ! x =

    game.world.width y = game.rnd.integerInRange(0, game.world.height) ! sprite = game.zombies.create(x, y, 'sprites', 'zombie1.png') !
  19. #sjsGabe game.zombies = game.add.physicsGroup( Phaser.Physics.ARCADE, this.game.world, 'zombies') ! x =

    game.world.width y = game.rnd.integerInRange(0, game.world.height) ! sprite = game.zombies.create(x, y, 'sprites', 'zombie1.png') ! sprite.health = 5
  20. #sjsGabe game.plants = game.add.physicsGroup( Phaser.Physics.ARCADE, this.game.world, 'plants') ! game.input.onTap.add ->

    x = game.input.activePointer.position.x y = game.input.activePointer.position.y ! sprite = game.plants.create x, y, 'sprites', 'ps-idle01.png' ! ! !
  21. #sjsGabe game.plants = game.add.physicsGroup( Phaser.Physics.ARCADE, this.game.world, 'plants') ! game.input.onTap.add ->

    x = game.input.activePointer.position.x y = game.input.activePointer.position.y ! sprite = game.plants.create x, y, 'sprites', 'ps-idle01.png' ! idle = sprite.animations.add('idle', ["ps-idle01.png"], 1, false, false) ! ! sprite.animations.play 'idle'
  22. #sjsGabe game.plants = game.add.physicsGroup( Phaser.Physics.ARCADE, this.game.world, 'plants') ! game.input.onTap.add ->

    x = game.input.activePointer.position.x y = game.input.activePointer.position.y ! sprite = game.plants.create x, y, 'sprites', 'ps-idle01.png' ! idle = sprite.animations.add('idle', ["ps-idle01.png"], 1, false, false) ! shoot = sprite.animations.add('shoot', ["ps-shoot1.png", "ps-shoot2.png"], 5, false, false) ! sprite.animations.play 'idle'
  23. #sjsGabe game.plants = game.add.physicsGroup( Phaser.Physics.ARCADE, this.game.world, 'plants') ! game.input.onTap.add ->

    x = game.input.activePointer.position.x y = game.input.activePointer.position.y ! sprite = game.plants.create x, y, 'sprites', 'ps-idle01.png' ! idle = sprite.animations.add('idle', ["ps-idle01.png"], 1, false, false) ! shoot = sprite.animations.add('shoot', ["ps-shoot1.png", "ps-shoot2.png"], 5, false, false) shoot.onComplete.add (-> this.animations.play 'idle'), sprite ! sprite.animations.play 'idle'
  24. #sjsGabe # Imagine we extracted a Plant 'class'... ! update:

    -> this.shoot() if this.zombieAhead() and this.canShoot() ! !
  25. #sjsGabe # Imagine we extracted a Plant 'class'... ! update:

    -> this.shoot() if this.zombieAhead() and this.canShoot() ! shoot: -> this.lastShotAt = new Date().getTime() this.animations.play 'shoot' !
  26. #sjsGabe # Imagine we extracted a Plant 'class'... ! update:

    -> this.shoot() if this.zombieAhead() and this.canShoot() ! shoot: -> this.lastShotAt = new Date().getTime() this.animations.play 'shoot' ! peaSprite = game.projectiles.create( this.position.x, this.position.y, 'sprites', 'pea.png') peaSprite.body.velocity.setTo 150, 0
  27. #sjsGabe # Imagine we extracted a Plant 'class'... ! update:

    -> this.shoot() if this.zombieAhead() and this.canShoot() ! shoot: -> this.lastShotAt = new Date().getTime() this.animations.play 'shoot' ! peaSprite = game.projectiles.create( this.position.x, this.position.y, 'sprites', 'pea.png') peaSprite.body.velocity.setTo 150, 0 peaSprite.checkWorldBounds = true peaSprite.outOfBoundsKill = true
  28. #sjsGabe ! # Add more functions to plant 'class' zombieAhead:

    -> zombiesAhead = (sprite for sprite in game.zombies.children \ when sprite.zombie.row == plant.row \ and sprite.position.x > this.position.x) zombiesAhead.length > 0 ! !
  29. #sjsGabe # An attribute on our plant 'class'... firingRate: 1

    * 1000 ! # Add more functions to plant sprite zombieAhead: -> zombiesAhead = (sprite for sprite in game.zombies.children \ when sprite.zombie.row == plant.row \ and sprite.position.x > this.position.x) zombiesAhead.length > 0 ! canShoot: -> this.timeSinceLastShot() > this.firingRate !
  30. #sjsGabe # An attribute on our plant 'class'... firingRate: 1

    * 1000 ! # Add more functions to plant sprite zombieAhead: -> zombiesAhead = (sprite for sprite in game.zombies.children \ when sprite.zombie.row == plant.row \ and sprite.position.x > this.position.x) zombiesAhead.length > 0 ! canShoot: -> this.timeSinceLastShot() > this.firingRate ! timeSinceLastShot: -> new Date().getTime() - this.lastShotAt
  31. #sjsGabe # Also in our game update function: game.physics.arcade.overlap( game.projectiles,

    game.zombies, handleZombieHit) ! handleZombieHit: (projectile, zombie) -> game.audio.splat.play()
  32. #sjsGabe # Also in our game update function: game.physics.arcade.overlap( game.projectiles,

    game.zombies, handleZombieHit) ! handleZombieHit: (projectile, zombie) -> game.audio.splat.play() zombie.damage(1)
  33. #sjsGabe # Also in our game update function: game.physics.arcade.overlap( game.projectiles,

    game.zombies, handleZombieHit) ! handleZombieHit: (projectile, zombie) -> game.audio.splat.play() zombie.damage(1) projectile.kill()
  34. #sjsGabe There's Lots More In Phaser • Camera Movement /

    Following • Tilemaps • Plugins • Particles • Complex Physics
  35. #sjsGabe Where To Learn More • phaser.io • 300+ Official

    Examples • HTML5 Game Devs Forum
 html5gamedevs.com