Build mobile HTML5 Games with Phaser

Build HTML5 Games with Phaser

Phaser

What we are going to cover

Breakout Phaser gameplay
  • The framework
  • Scaling the Canvas
  • Loading the assets
  • Drawing images and text
  • Physics
  • Mobile input
  • Collision detection
  • Winning and losing
  • Animations nad tweens

Table of Contents

  1. The score
  2. Win the game
  3. Extra lives
  4. Animations and tweens
  5. Buttons
  6. Randomizing gameplay
  1. Initialize the framework
  2. Scaling
  3. Load the assets and print them on screen
  4. Move the ball
  5. Physics
  6. Bounce off the walls
  7. Player paddle and controls
  8. Game over
  9. Build the brick field
  10. Collision detection

0. Preparation

1. The framework

  • Frameworks vs pure JavaScript game development
  • Advantages ⁄ disadvantages
  • Why Phaser?
  • Breakout game

HTML structure

          <!DOCTYPE html>
          <html>
          <head>
            <meta charset="utf-8" />
            <title>Gamedev Phaser Workshop - lesson 01: Initialize the framework</title>
            <style>* { padding: 0; margin: 0; }</style>
            <script src="js/phaser.2.4.2.min.js"></script>
          </head>
          <body>
          <script>
          var game = new Phaser.Game(480, 320, Phaser.AUTO, null, {
            preload: preload, create: create, update: update
          });
          function preload() {}
          function create() {}
          function update() {}
          </script>
          </body>
          </html>
        

2. Scaling

        function preload() {
          game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
          game.scale.pageAlignHorizontally = true;
          game.scale.pageAlignVertically = true;
          game.stage.backgroundColor = '#eee';
        }
      

Scale modes: NO_SCALE, EXACT_FIT, SHOW_ALL, RESIZE, USER_SCALE.

3. Load and print the assets

        var ball;
        function preload() {
          // ...
          game.load.image('ball', img_ball);
        }
        function create() {
          ball = game.add.sprite(50, 50, 'ball');
        }
      

Print it

Breakout Phaser gameplay

        ball = game.add.sprite(400,300, 'ball');
      

4. Move the ball

Breakout Phaser gameplay

        function update() {
          ball.x -= 1;
          ball.y -= 1;
        }
      

5. Physics

        function create() {
          game.physics.startSystem(Phaser.Physics.ARCADE);
          ball = game.add.sprite(50, 50, 'ball');
          game.physics.enable(ball, Phaser.Physics.ARCADE);
          ball.body.velocity.set(150, 150);
        }
      

Physics systems: Arcade, P2, Ninja and Box2D.

6. Bounce off the walls

        function create() {
          // ...
          ball.body.collideWorldBounds = true;
          ball.body.bounce.set(1);
        }
      

7. Player paddle and controls

Breakout Phaser gameplay

        var paddle;
        function preload() {
          // ...
          game.load.image('paddle', 'img/paddle.png');
        }
        function create() {
            // ...
          paddle = game.add.sprite(game.world.width*0.5,
          game.world.height-5, 'paddle');
          paddle.anchor.set(0.5,1);
          game.physics.enable(paddle, Phaser.Physics.ARCADE);
          paddle.body.immovable = true;
        }
        function update() {
          game.physics.arcade.collide(ball, paddle);
          paddle.x = game.input.x || game.world.width*0.5;
        }
      

8. Game over

        function create() {
          game.physics.startSystem(Phaser.Physics.ARCADE);
          game.physics.arcade.checkCollision.down = false;
          // ...
          ball.checkWorldBounds = true;
          ball.events.onOutOfBounds.add(function(){
            alert('Game over!');
            location.reload();
          }, this);
        }
      

9. Build the brick field

        var bricks;
        var newBrick;
        var brickInfo;
        function preload() {
          // ...
          game.load.image('brick', 'img/brick.png');
        }
        function create(){
          // ...
          initBricks();
        }
      
        function initBricks() {
          brickInfo = {
            width: 50,
            height: 20,
            count: {
              row: 7,
              col: 3
            },
            offset: {
              top: 50,
              left: 60
            },
            padding: 10
          }
        }
      
        function initBricks() {
          // ...
          bricks = game.add.group();
          for(c=0; c<brickInfo.count.col; c++) {
            for(r=0; r<brickInfo.count.row; r++) {
              var brickX = 0;
              var brickY = 0;
              newBrick = game.add.sprite(brickX, brickY, 'brick');
              game.physics.enable(newBrick, Phaser.Physics.ARCADE);
              newBrick.body.immovable = true;
              newBrick.anchor.set(0.5);
              bricks.add(newBrick);
            }
          }
        }
      

Breakout Phaser gameplay

        var brickX = (r*(brickInfo.width+brickInfo.padding))+brickInfo.offset.left;
        var brickY = (c*(brickInfo.height+brickInfo.padding))+brickInfo.offset.top;
      
        function initBricks() {
          // ...
          bricks = game.add.group();
          for(c=0; c<brickInfo.count.col; c++) {
            for(r=0; r<brickInfo.count.row; r++) {
              var brickX = (r*(brickInfo.width+brickInfo.padding))+brickInfo.offset.left;
              var brickY = (c*(brickInfo.height+brickInfo.padding))+brickInfo.offset.top;
              newBrick = game.add.sprite(brickX, brickY, 'brick');
              game.physics.enable(newBrick, Phaser.Physics.ARCADE);
              newBrick.body.immovable = true;
              newBrick.anchor.set(0.5);
              bricks.add(newBrick);
            }
          }
        }
      

10. Collision detection

Collision

10. Collision detection

        function update() {
          game.physics.arcade.collide(ball, paddle);
          game.physics.arcade.collide(ball, bricks, ballHitBrick);
          paddle.x = game.input.x || game.world.width*0.5;
        }
        function ballHitBrick(ball, brick) {
          brick.kill();
        }
      

11. The score

Points

11. The score

        var scoreText;
        var score = 0;
        function create() {
          // ...
          scoreText = game.add.text(5, 5, 'Points: 0',
            { font: '18px Arial', fill: '#0095DD' });
        }
        function ballHitBrick(ball, brick) {
          brick.kill();
          score += 10;
          scoreText.setText('Points: '+score);
        }
      

12. Win the game

Destroy all the bricks.

        function ballHitBrick(ball, brick) {
          brick.kill();
          score += 10;
          scoreText.setText('Points: '+score);
          if(score === brickInfo.count.row*brickInfo.count.col*10) {
            alert('You won the game, congratulations!');
            location.reload();
          }
        }
      

13. Extra lives

Lives
        var lives = 3;
        var textStyle;
        var livesText;
        var lifeLostText;
      

13. Extra lives

        function create() {
          // ...
          textStyle = { font: '18px Arial', fill: '#0095DD' };
          scoreText = game.add.text(5, 5, 'Points: 0', textStyle);
          livesText = game.add.text(game.world.width-5, 5, 'Lives: '+lives, textStyle);
          livesText.anchor.set(1,0);
          lifeLostText = game.add.text(game.world.width*0.5, game.world.height*0.5,
            'Life lost, click to continue', textStyle);
          lifeLostText.anchor.set(0.5);
          lifeLostText.visible = false;
        }
      
        function create() {
          // ...
          ball.events.onOutOfBounds.add(ballLeaveScreen, this);
        }
        function ballLeaveScreen() {
          lives--;
          if(lives) {
            livesText.setText('Lives: '+lives);
            lifeLostText.visible = true;
            ball.reset(game.world.width*0.5, game.world.height-25);
            paddle.reset(game.world.width*0.5, game.world.height-5);
            game.input.onDown.addOnce(function(){
              lifeLostText.visible = false;
              ball.body.velocity.set(150, -150);
            }, this);
          }
          else {
            alert('You lost, game over!');
            location.reload();
          }
        }
      

14. Animations and tweens

Wobble
        function preload() {
          // ...
          game.load.spritesheet('ball', 'img/wobble.png', 20, 20);
        }
        function create() {
          // ...
          ball = game.add.sprite(50, 250, 'ball');
          ball.animations.add('wobble', [0,1,0,2,0,1,0,2,0], 24);
        }
        function update() {
          game.physics.arcade.collide(ball, paddle, ballHitPaddle);
          // ...
        }
        function ballHitPaddle(ball, paddle) {
          ball.animations.play('wobble');
        }
      

Tweens

Brick
        function ballHitBrick(ball, brick) {
          var killTween = this.add.tween(brick.scale);
          killTween.to({x:0,y:0}, 200, Phaser.Easing.Linear.None);
          killTween.onComplete.addOnce(function(){
            brick.kill();
          }, this);
          killTween.start();
          score += 10;
          scoreText.setText('Points: '+score);
          if(score === brickInfo.count.row*brickInfo.count.col*10) {
            alert('You won the game, congratulations!');
            location.reload();
          }
        }
        // game.add.tween(brick.scale).to({x:2,y:2}, 500, Phaser.Easing.Elastic.Out, true, 100);
      

15. Buttons

Button
        var playing = false;
        var startButton;
        function preload() {
          // ...
          game.load.spritesheet('button', 'img/button.png', 120, 40);
        }
        function create() {
          // ...
          startButton = game.add.button(game.world.width*0.5,
            game.world.height*0.5, 'button', startGame, this, 1, 0, 2);
          startButton.anchor.set(0.5);
        }
      
        function startGame() {
          startButton.destroy();
          ball.body.velocity.set(150, -150);
          playing = true;
        }
        function update() {
          // ...
          if(playing) {
            paddle.x = game.input.x || game.world.width*0.5;
          }
        }
      

16. Randomizing gameplay

        function ballHitPaddle(ball, paddle) {
          ball.animations.play('wobble');
          ball.body.velocity.x = -1*5*(paddle.x-ball.x);
        }
      
Bounce

Thanks! Questions?

Andrzej Mazur

  • Website: end3r.com
  • Twitter: @end3r
  • GitHub: end3r
  • Newsletter: gamedevjsweekly.com
  • Competition: js13kgames.com