Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                
              
            
!

CSS

              
                body,
canvas
{
  display: block;
  margin: auto;
  background: #16191b;
  max-width: 100%;
}


              
            
!

JS

              
                var config = {
  type: Phaser.AUTO,
  width: 800,
  height: 400,
  transparent: true,
  physics: {
      default: 'arcade',
      arcade: {
          fps: 120,
          gravity: { y: 300 }
      }
  },
  scene: {
      preload: preload,
      create: create,
      update: update
  }
};

var player,
  baddie,
  baddies,
  coins,
  scoreCoin,
  scoreCoinTimeline,
  platforms,
  oneWayPlatforms,
  ladders,
  cursors,
  score = 0,
  scoreText,
  heartOutlines = [],
  hearts = [],
  maxHearts = 3,
  vulnerableTime = 1000,
  acceleration = 600,
  maxPlayerSpeed = 200,
  superPlayerSpeed = 400,
  jumpVelocity = -165,
  jumpVelocitySmall = -165,
  jumpVelocityBig = -330,
  wasStanding = false,
  onLadder = false,
  edgeTimer = 0,
  prevPos = 0,
  yPos = 0,
  touchJump = false,
  touchJumpThreshold = 5,
  touchSlider,
  sliderBar,
  sliderKnob,
  touchMoving = false,
  isTouch = false,
  touchMoveThreshold = 3,
  largeThumbMoveAcross = 25,
  thumbSizeOffset = 60,
  startX,
  shell,
  shellSpeed = 500,
  spikes,
  invicibility,
  mushroom,
  questionMarkBlock,
  emitter,
  heroColor = new Phaser.Display.Color(255, 255, 255),
  invincibleColor = new Phaser.Display.Color(56, 194, 239),
  camera,
  hud,
  coinTweens = [];

var game = new Phaser.Game(config);

function preload() {
  this.load.setBaseURL("https://digitherium.com/codepen/phaserplatformer/");
  this.load.image('ground', 'platform.jpg');
  this.load.image('one-way-platform', 'one-way-platform.jpg');
  this.load.image('one-way-platform-large', 'one-way-platform-large.jpg');
  this.load.image('coin', 'coin.jpg');
  this.load.image('hero', 'hero.jpg');
  this.load.image('hero-small', 'hero-small.jpg');
  this.load.image('baddie', 'baddie.jpg');
  this.load.image('ladder', 'ladder.png');
  this.load.image('shell', 'shell.png');
  this.load.image('powerup', 'powerup.jpg');
  this.load.image('question-mark-block', 'question-mark-block.jpg');
  this.load.image('empty-box', 'empty-box.jpg');
  this.load.image('dust', 'dust.jpg');
  this.load.image('spikes', 'spikes.png');
  this.load.image('heart', 'heart.png');
  this.load.image('heart-filled', 'heart-filled.png');
  this.load.image("logo", "digitherium-logo.jpg");
  this.load.image('touch-slider', 'touch-slider.png');
  this.load.image('touch-knob', 'touch-knob.png');
}

function create() {
  var logo = this.add.sprite(config.width / 2, 240, 'logo');
  logo.alpha = 0.4;
  logo.setScale(0.5);
  logo.setScrollFactor(0.2);

  this.input.addPointer(1);
  platforms = this.physics.add.staticGroup();
  this.physics.world.setBounds(0, 0, 1630, 400);

  platforms.create(1300, 400, 'ground').setScale(2).refreshBody();
  platforms.create(400, 400, 'ground').setScale(2).refreshBody();
  platforms.create(150, 240, 'ground');
  platforms.create(860, 190, 'ground');

  oneWayPlatforms = this.physics.add.staticGroup();
  oneWayPlatforms.create(1400, 352, 'one-way-platform-large');
  oneWayPlatforms.create(1400, 320, 'one-way-platform');

  ladders = this.physics.add.staticGroup();
  ladders.enableBody = true;
  ladder = ladders.create(368, 296, 'ladder');
  ladder.body.immovable = true;

  spikes = this.physics.add.staticGroup();
  spikes.enableBody = true;
  spikes = spikes.create(850, 415, 'spikes');
  spikes.body.immovable = true;

  player = this.physics.add.sprite(40, 350, 'hero-small');
  player.setOrigin(.5, .5);
  player.setDrag(1);
  player.setCollideWorldBounds(true);

  //create and set an invulnerable flag for after the player has been hit
  player.invulnerable = false;
  //and set an invincible flag for the invincibility powerup
  player.invincible = false;
  //set no lives / hearts
  player.hearts = maxHearts;

  //create our baddies group
  baddies = this.physics.add.group();

  baddie = baddies.create(1220, 350, 'baddie');
  baddie.setOrigin(.5, .5);
  baddie.setCollideWorldBounds(true);
  baddie.body.velocity.x = -100;
  baddie.maxDistance = 300;
  baddie.previousX = baddie.x;

  baddie = baddies.create(940, 100, 'baddie');
  baddie.setOrigin(.5, .5);
  baddie.setCollideWorldBounds(true);
  baddie.body.velocity.x = -100;
  baddie.maxDistance = 250;
  baddie.previousX = baddie.x;

  //add a shall and set it to rotate around its center
  shell = this.physics.add.sprite(1400, 360, 'shell');
  shell.setOrigin(.5, .5);
  shell.setCollideWorldBounds(true);

  //add invincibility powerup and set it to rotate around its center
  invicibility = this.physics.add.sprite(256, 214, 'powerup');
  invicibility.setOrigin(.5, .5);

  //add mushroom powerup, set it to rotate around its center and tint it orange
  mushroom = this.physics.add.sprite(520, 310, 'powerup');
  mushroom.setOrigin(.5, .5);
  mushroom.setTintFill(0xff9800);
  //disable physics, hide and turn off gravity
  mushroom.enableBody = false;
  mushroom.visible = false;
  mushroom.body.setAllowGravity(false);

  questionMarkBlock = this.physics.add.sprite(520, 310, 'question-mark-block');
  questionMarkBlock.body.setAllowGravity(false);
  questionMarkBlock.setImmovable(true);
  questionMarkBlock.powerup = mushroom;

  buildTouchSlider(this);
  //Set bounce to 0, so our hero just lands directly
  player.setBounce(0);
  //Set top speeds
  player.body.maxVelocity.x = maxPlayerSpeed;
  player.body.maxVelocity.y = 500;
  player.isBig = false;
  player.isChangingSize = false;

  cursors = this.input.keyboard.createCursorKeys();

  coins = this.physics.add.group({
      key: 'coin',
      repeat: 11,
      setXY: { x: 12, y: 0, stepX: 70 }
  });

  coins.children.iterate(function(child) {
      child.setBounceY(Phaser.Math.FloatBetween(0.4, 0.8));
  });

  scoreCoin = this.add.sprite(30, 32, 'coin');
  scoreCoin.setOrigin(.5, .5);
  scoreCoin.scaleX = .5;
  scoreCoin.scaleY = .5;
  scoreText = this.add.text(46, 20, '0', { fontSize: '24px', fill: '#fff' });
  scoreCoin.setScrollFactor(0);
  //create three heart outlines...
  var heartOutline1 = this.add.sprite(760, 38, 'heart'),
      heartOutline2 = this.add.sprite(720, 38, 'heart'),
      heartOutline3 = this.add.sprite(680, 38, 'heart');

  //and store in an array for easy access later
  heartOutlines = [heartOutline1, heartOutline2, heartOutline3];

  //create three heart fills...
  heart1 = this.add.sprite(760, 38, 'heart-filled');
  heart2 = this.add.sprite(720, 38, 'heart-filled');
  heart3 = this.add.sprite(680, 38, 'heart-filled');
  //and store in an array for easy access later
  hearts = [heart1, heart2, heart3];

  //create a contain for our heads up display and add some sprites
  hud = this.add.container(0, 0, [scoreCoin, scoreText, heart1, heart2, heart3, heartOutline1, heartOutline2, heartOutline3]);
  //lock it to the camera
  hud.setScrollFactor(0);

  //create our particle effects for when in invincible mode
  var particles = this.add.particles('dust');
  emitter = particles.createEmitter();
  emitter.setPosition(player.x, player.y);
  emitter.setSpeed(150);
  emitter.setBlendMode(Phaser.BlendModes.ADD);
  //turn it off for now until we are invincible
  emitter.pause();

  camera = this.cameras.main;
  camera.setBounds(0, 0, 1630, 400);
  camera.startFollow(player, true, 0.05, 0, -200, 120);
  camera.setFollowOffset(-200, 120);

  this.physics.add.collider(player, platforms);
  this.physics.add.collider(player, oneWayPlatforms, null, checkOneWay, this);
  this.physics.add.collider(baddies, platforms);
  this.physics.add.collider(coins, platforms);
  this.physics.add.collider(shell, platforms, shellWallHit, null, this);
  this.physics.add.collider(invicibility, platforms);
  this.physics.add.collider(mushroom, platforms);
  this.physics.add.collider(player, shell, shellHit, null, this);
  this.physics.add.collider(player, spikes, playerHit, null, this);
  this.physics.add.overlap(player, coins, collectCoin, null, this);
  this.physics.add.overlap(player, invicibility, goInvincibile, null, this);
  this.physics.add.overlap(player, mushroom, collectMushroom, null, this);
  this.physics.add.collider(player, questionMarkBlock, hitQuestionMarkBlock, null, this);
  this.physics.add.overlap(player, baddies, hitBaddie, null, this);
  this.physics.add.overlap(player, ladders, isOnLadder, null, this);
  this.physics.add.collider(player, ladders, null, checkLadderTop, this);
  this.physics.add.overlap(shell, baddies, shellHitBaddie, null, this);
  this.physics.add.collider(shell, spikes, destroyShell, null, this);
}

function hitBaddie(player, baddie) {
  if (player.invincible) {
      baddie.disableBody(false, false);
      //play baddies super death animation
      var tween = this.tweens.add({
          targets: baddie,
          alpha: 0.3,
          y: "-=150",
          scaleX: 2.5,
          scaleY: 2.5,
          angle: 180,
          ease: 'Linear',
          duration: 200,
          onComplete: function() {
              destroyGameObject(baddie);
          },
      });
  } else {
      //baddie was hit on the head and hasn't already been hit, and not animating shrink
      if (baddie.body.touching.up && !baddie.hit && !player.isChangingSize) {
          // set baddie as being hit and remove physics
          baddie.disableBody(false, false);
          player.setVelocityY(jumpVelocity);

          //play baddies death animation
          var tween = this.tweens.add({
              targets: baddie,
              alpha: 0.3,
              scaleX: 1.5,
              scaleY: 1.5,
              ease: 'Linear',
              duration: 200,
              onComplete: function() {
                  destroyGameObject(baddie);
              },
          });
      }
      //otherwise you've hit baddie, BUT not on the head. This makes you die
      else {
          playerHit.call(this);
      }
  }
}

function playerHit() {
  //if you are not already invulnerable OR invincible
  if (!player.invulnerable && !player.invincible) {
      //set player as invulnerable
      player.invulnerable = true;
      //get the heart sprites from our arrays we set up earlier
      var currentHeartCount = player.hearts,
          currentHeart = hearts[currentHeartCount - 1],
          currentHeartOutline = heartOutlines[currentHeartCount - 1];

      //fade out the heart fill
      var heartFade = this.tweens.add({
          targets: currentHeart,
          alpha: 0,
          scaleX: 0,
          scaleY: 0,
          ease: 'Linear',
          duration: 200
      });

      //create a timeline of tweens for the heart outline so it shrinks then grows back
      var heartsTimeline = this.tweens.createTimeline();

      //this is the heart outline scaling down
      heartsTimeline.add({
          targets: currentHeartOutline,
          scaleX: 0.5,
          scaleY: 0.5,
          ease: 'Power1',
          duration: 200
      });

      //and then back
      heartsTimeline.add({
          targets: currentHeartOutline,
          scaleX: 1,
          scaleY: 1,
          ease: 'Power1',
          duration: 200
      });
      //play the timeline straight away
      heartsTimeline.play();

      //remove a heart from out count stored on the player object
      player.hearts -= 1;

      //if hearts is 0 or less you're dead as you are out of lives
      if (player.hearts <= 0) {
          //remove physics from player
          player.disableBody(false, false);
          //and play death animation
          var tween = this.tweens.add({
              targets: player,
              alpha: 0.3,
              scaleX: 1.1,
              scaleY: 1.1,
              angle: 90,
              x: player.x - 20,
              y: player.y - 20,
              ease: 'Linear',
              duration: 200,
              onComplete: function() {
                  restartGame(this);
              },
              onCompleteScope: this
          });
      }
      //otherwise you're not dead you've just lost a life so...
      else {
          if (player.isBig) {
              player.body.velocity.x = 0;
              player.body.velocity.y = -220;
              player.isChangingSize = true;

              var tween = this.tweens.add({
                  targets: player,
                  scaleX: 0.8,
                  scaleY: 0.8,
                  alpha: 0.3,
                  yoyo: 2,
                  repeat: 2,
                  ease: 'Linear',
                  duration: 100,
                  onComplete: function() {
                      shrinkHero();
                  },
              });
          } else {
              //make the player stop in their tracks and jump up
              player.body.velocity.x = 0;
              player.body.velocity.y = -220;
              //tween the players alpha to 30%
              var tween = this.tweens.add({
                  targets: player,
                  alpha: 0.3,
                  ease: 'Linear',
                  duration: 200,
                  onCompleteScope: this
              });
          }

          //set a timer for 1 second. When this is up we tween player back to normal and make then vulnerable again
          var timer = this.time.delayedCall(vulnerableTime, playerVulnerable, [this]);
      }
  }
}

function playerVulnerable(game) {
  //tween player back to 100% opacity and reset invulnerability flag
  var death = game.tweens.add({
      targets: player,
      alpha: 1,
      ease: 'Linear',
      duration: 200,
      onComplete: function() {
          player.invulnerable = false;
      },
      onCompleteScope: this
  });
}

function shellHitBaddie(shell, baddie) {
  if (!baddie.hit) {
      // set baddie as being hit and remove physics
      baddie.disableBody(false, false);
      //play baddie death animation
      var tween = this.tweens.add({
          targets: baddie,
          alpha: 0.3,
          scaleX: 1.5,
          scaleY: 1.5,
          ease: 'Linear',
          duration: 200,
          onComplete: function() {
              destroyGameObject(baddie);
          },
      });

      destroyShell.call(this);
  }
}

function shellWallHit(shell, wall) {
  //if shell has hit a wall with either the right of left side of itself it should be destroyed
  if (shell.body.onWall()) {
      destroyShell.call(this);
  }
}

function shellHit(player, shell) {
  //work out the center point of the shell and player
  var threshold = shell.x + (shell.width / 2),
      playerX = player.x + (player.width / 2);

  //if the player has jumped on top of the shell...
  if (shell.body.touching.up) {
      //if player landed on left hand side of shell send shell off to right
      if (playerX < threshold) shell.body.velocity.x = shellSpeed;
      //if player landed on right hand side of shell send shell off to left
      else shell.body.velocity.x = -shellSpeed;
  }
  //player hit shell from left so send right
  if (shell.body.touching.left) {
      shell.body.velocity.x = shellSpeed;
  }
  //player hit shell from right so send left
  if (shell.body.touching.right) {
      shell.body.velocity.x = -shellSpeed;
  }
  //make player react to shell by bouncing slightly
  player.body.velocity.y = -200;
}

function destroyShell() {
  //disable physics of shell
  shell.disableBody(false, false);
  //play shell hit animation
  var destroyShell = this.tweens.add({
      targets: shell,
      alpha: 0.3,
      scaleX: 2,
      scaleY: 2,
      y: "-=100",
      rotation: -360,
      ease: 'Linear',
      duration: 200,
      onComplete: function() {
          destroyGameObject(shell);
      },
  });
}

function restartGame(game) {
  game.scene.restart();
}

function buildTouchSlider(game) {
  sliderBar = game.add.sprite(0, 0, 'touch-slider');
  sliderKnob = game.add.sprite(0, 0, 'touch-knob');

  touchSlider = game.add.container(100, 450);
  touchSlider.add(sliderBar);
  touchSlider.add(sliderKnob);
  touchSlider.alpha = 0;
  touchSlider.setScrollFactor(0);
}

function moveLeft(acceleration) {
  var standing = player.body.blocked.down || player.body.touching.down;
  //if hero is on ground then use full acceleration
  if (standing) {
      player.setAccelerationX(-acceleration);
  }
  //if hero is in the air then accelerate slower
  else {
      player.setAccelerationX(-acceleration / 3);
  }
}

function moveRight(acceleration) {
  var standing = player.body.blocked.down || player.body.touching.down;
  //if hero is on ground then use full acceleration
  if (standing) {
      player.setAccelerationX(acceleration);
  }
  //if hero is in the air then accelerate slower
  else {
      player.setAccelerationX(acceleration / 3);
  }
}

function switchDirection(baddie) {
  //reverse velocity so baddie moves are same speed but in opposite direction
  baddie.body.velocity.x *= -1;
  //reset count
  baddie.previousX = baddie.x;
  //flip sprite
  //baddie.scale.setTo(-baddie.scale.x, 1);
}

//called when player overlaps ladder
function isOnLadder(player, ladder) {
  //set ladder flag to true and remove gravity but only if not at the top of the ladder
  if (Math.floor(player.y) + (player.height / 2) > ladder.y - (ladder.height / 2)) {
      onLadder = true;
      player.body.setAllowGravity(false);
  }
}

//called when player collides with ladder
function checkLadderTop(player, ladder) {
  /* We check here if our player is higher up than the ladder i.e. if the player is on top of the ladder
  the sprites are positioned from their centres, so we have to add or subtract half their height to find the heroes feet and the top of the ladder. 
  With the player we add half the height so we are checking the positon of their feet. With the ladder we add half the height so we are checking the top of the ladder. We also round the two values differently, floor for the player to give us the smallest number possible and ceil for the ladder height to give us the highest number possible. This deals with any subpixel values.
  */
  if (Math.floor(player.y + (player.height / 2)) <= Math.ceil(ladder.y - (ladder.height / 2))) {
      //if pressing the down key, or touch down return false and cancel collision
      if (cursors.down.isDown || (Math.floor(prevPos) < Math.floor(yPos))) return false;
      //return true making our collision happen i.e. the player can walk on top of the ladder
      else return true;
  }
  //otherwise return false which cancels the collision
  else {
      return false;
  }
}


//called when player collides with oneway platforms
function checkOneWay(player, oneway) {
  //if player is higher up the screen then the plaform then enable the collision
  if (player.y < oneway.y) {
      return true;
  }
  //otherwise disable collision
  return false;
}

function update() {
  //loop through any coin tweens
  for (var i = 0; i < coinTweens.length; i++) {
      var tween = coinTweens[i];
      //if we find a tween update it to the new position of the scoreCoin
      if (tween) tween.updateTo("x", camera.scrollX + scoreCoin.x);
  }
  
  //set jump velocity depending on whether we are big or small
  if (player.isBig) jumpVelocity = jumpVelocityBig;
  else jumpVelocity = jumpVelocitySmall;

  emitter.setPosition(player.x, player.y);
  //built in arcade physics functions of blocked and touching to test for collisions in a given direction
  var standing = player.body.blocked.down || player.body.touching.down,
      //get current time in seconds
      d = new Date(),
      time = d.getTime();

  //if left key is down then move left
  if (cursors.left.isDown) {
      moveLeft(acceleration);
  }
  //same deal but for right arrow
  else if (cursors.right.isDown) {
      moveRight(acceleration);
  }

  //loop through baddies group and for each baddie...
  baddies.getChildren().forEach(function(theBaddie) {
      //check if it's time for them to turn around
      if (Math.abs(theBaddie.x - theBaddie.previousX) >= theBaddie.maxDistance) {
          switchDirection(theBaddie);
      }
  }, this);



  //if either touch pointer is down. Two thumbs, two pointers
  if (this.input.pointer1.isDown || this.input.pointer2.isDown) {
      //work out half way point of our game
      var leftHalf = config.width / 2;

      //Left hand side - horizontal movement
      //if thumb is on the left hand side of the screen we are dealing with horizontal movement
      if (this.input.pointer1.x < leftHalf || this.input.pointer2.x < leftHalf) {
          //reset pointer variable
          var myMovePointer = null;
          //here we get the pointer that is being used on the left hand side of screen. Depends which thumb they touched screen with first.
          if (this.input.pointer1.x < leftHalf && this.input.pointer1.isDown) {
              myMovePointer = this.input.pointer1;
          }
          if (this.input.pointer2.x < leftHalf && this.input.pointer2.isDown) {
              myMovePointer = this.input.pointer2;
          }

          //if we have an active touch pointer on the left hand side of the screen then...
          if (myMovePointer) {
              //if touchSlide is not already showing then
              if (!touchSlider.alpha) {
                  //make it visible
                  touchSlider.alpha = 1;
                  //position touchSlider to be where the users thumb or finger is
                  touchSlider.x = myMovePointer.x;
                  //with the Y pos we add a thumbSizeOffset so it's above the users thumb not hidden under it
                  touchSlider.y = myMovePointer.y - thumbSizeOffset;
                  //set our start point and reset slider display
                  startX = myMovePointer.x;
                  sliderKnob.x = 0;
              }

              //if thumb has moved left or right of where we started then move
              if (myMovePointer.x < startX || myMovePointer.x > startX) {
                  //work out how far thumb has moved. Is this a big enough movement?
                  var movement = 0;
                  if (myMovePointer.x < startX) movement = startX - myMovePointer.x;
                  if (myMovePointer.x > startX) movement = myMovePointer.x - startX;
                  //If move is significant enough then move our character
                  if (movement > touchMoveThreshold) {
                      //set flag as we are definitely moving
                      touchMoving = true;
                      //set a flag so we know we are on a mobile device
                      isTouch = true;

                      //set slider knob position to be half way to edge
                      var sliderPos = 0;
                      //left
                      if (myMovePointer.x < startX) sliderPos = -(sliderBar.width / 4);
                      //right
                      if (myMovePointer.x > startX) sliderPos = sliderBar.width / 4;

                      //set acceleration to be an 8th of normal
                      var tmpAcceleration = acceleration / 8;

                      //if thumb has moved quite a lot, then go faster
                      if (movement > largeThumbMoveAcross) {
                          //the knob position should be at the edge as we're at full tilt
                          if (myMovePointer.x < startX) sliderPos = -(sliderBar.width / 2);
                          if (myMovePointer.x > startX) sliderPos = sliderBar.width / 2;
                          //acceleration is normal
                          tmpAcceleration = acceleration;
                      }

                      //tween slider knob to position we just worked out
                      var tween = this.tweens.add({
                          targets: sliderKnob,
                          x: sliderPos,
                          ease: "Power1",
                          duration: 300
                      });
                      if (myMovePointer.x < startX) moveLeft(tmpAcceleration);
                      if (myMovePointer.x > startX) moveRight(tmpAcceleration);
                  } else {
                      //If move is really, really small then we don't count it. Stop moving
                      //set moving flag to false
                      touchMoving = false;
                      //reset slider knob to center position
                      var tween = this.tweens.add({
                          targets: sliderKnob,
                          x: 0,
                          ease: "Power1",
                          duration: 300
                      });
                  }
              }
          }
      }

      //Right hand side - Touch Jumping
      //if thumb is on the right hand side of the screen we are dealing with vertical movement - i.e. jumping.
      if (this.input.pointer1.x > leftHalf || this.input.pointer2.x > leftHalf) {
          //reset pointer variable
          var myJumpPointer = null;

          //get active touch pointer for this side of the screen
          if (this.input.pointer1.x > leftHalf && this.input.pointer1.isDown) {
              myJumpPointer = this.input.pointer1;
          }
          if (this.input.pointer2.x > leftHalf && this.input.pointer2.isDown) {
              myJumpPointer = this.input.pointer2;
          }
          //if we have a touch pointer on right hand side of screen...
          if (myJumpPointer) {
              //store last y position of touch pointer
              prevPos = yPos;
              //get new position of touch pointer
              yPos = myJumpPointer.y;

              //check if we are currently overlapping a ladder. If we are then...
              if (onLadder) {
                  //kill any upwards / downwards velocity from our hero
                  player.setVelocityY(0);

                  //if moving up with thumb then climb up the ladder
                  if (Math.floor(prevPos) > Math.floor(yPos)) {
                      if (!myMovePointer) {
                          //when moving vertically we want the player pefectly lined up
                          player.x = ladder.x;
                          //also kill any x velocity to be sure
                          player.setVelocityX(0);
                          player.setVelocityY(-100);
                      }
                  }
                  //if moving down with thumb then climb down the ladder
                  if (Math.floor(prevPos) < Math.floor(yPos)) {
                      if (!myMovePointer) {
                          //when moving vertically we want the player pefectly lined up
                          player.x = ladder.x;
                          //also kill any x velocity to be sure
                          player.setVelocityX(0);
                          player.setVelocityY(100);
                      }
                  }
              }
              //not on a ladder so go for a standard jump 
              else {
                  //  if we have moved our thump upwards then we set jump flag to true
                  if (prevPos - yPos > touchJumpThreshold) {
                      touchJump = true;
                  }
              }
          }
      }
      //neither thumb is down so reset touch movement variables and hide touchSlider
  } else {
      touchSlider.alpha = 0;
      startX = 0;
      touchMoving = false;

      if (onLadder) {
          //if player is on top of the ladder we reset the velocity, otherwise we leave them be to climb or descend
          if (Math.floor(player.y + (player.height / 2)) <= Math.ceil(ladder.y - (ladder.height / 2))) {
              player.setVelocityY(0);
          }
      }
  }

  //if not moving left or right via keys or touch device...
  if (!cursors.right.isDown && !cursors.left.isDown && !touchMoving) {
      //if hero is close to having no velocity either left or right then set velocity to 0. This stops jerky back and forth as the hero comes to a halt. i.e. as we slow hero down, below a certain point we just stop them moving altogether as it looks smoother
      if (Math.abs(player.body.velocity.x) < 10 && Math.abs(player.body.velocity.x) > -10) {
          player.setVelocityX(0);
          player.setAccelerationX(0);
      } else {
          //if our hero isn't moving left or right then slow them down
          //this velocity.x check just works out whether we are setting a positive (going right) or negative (going left) number
          player.setAccelerationX(
              (player.body.velocity.x > 0 ? -1 : 1) * acceleration / 3
          );
      }
  }

  //get current time in seconds
  var d = new Date();
  var time = d.getTime();

  //if we have just left the ground set edge time for 100ms time
  if (!standing && wasStanding) {
      edgeTimer = time + 100;
  }

  //if we are on a ladder and not on a touch device
  if (onLadder && !isTouch) {
      //kill any upwards / downwards velocity from our hero
      player.setVelocityY(0);

      if (cursors.up.isDown) {
          if (!cursors.left.isDown && !cursors.right.isDown) {
              //when moving vertically we want the player pefectly lined up
              player.x = ladder.x;
              //also kill any x velocity to be sure
              player.setVelocityX(0);
              player.setVelocityY(-100);
          }
      }
      //if JUST down is being pressed then line up player perfectly with ladder. 
      //We do this to make it quicker - but like a firemans pole
      if (cursors.down.isDown && !cursors.left.isDown && !cursors.right.isDown) {
          //when moving vertically we want the player pefectly lined up
          player.x = ladder.x;
          //also kill any x velocity to be sure
          player.setVelocityX(0);
          player.setVelocityY(100);
      }
  }


  //if player is standing, or just fallen off a ledge (within our allowed grace time) and..
  //either up key is press, or touchjump flag is set AND they are not already jumping then jump!
  if (
      (standing || time <= edgeTimer) &&
      (cursors.up.isDown || touchJump) &&
      !jumping && !onLadder
  ) {
      player.setVelocityY(jumpVelocity);
      jumping = true;
  }

  //if not pressing up key...
  if (!cursors.up.isDown) {
      //if player is touching ground / platform then reset jump parametrs
      if (player.body.touching.down) {
          jumping = false;
          touchJump = false;
          prevPos = 0;
      }
  }
  wasStanding = standing;
  //if player is no longer on on ladder then turn gravity back on
  if (!onLadder) player.body.setAllowGravity(true);
  onLadder = false;
}


function collectCoin(player, coin) {
  //stop coin for being collected twice, as it will stick around on the screen as it animnates
  coin.disableBody(false, false);

  //tween coin to score coin in corner shrink
  var collectCoinTween = this.tweens.add({
      targets: coin,
      alpha: 0.3,
      angle: 720,
      x: scoreCoin.x,
      y: scoreCoin.y,
      scaleX: 0.5,
      scaleY: 0.5,
      ease: 'Linear',
      duration: 500,
      onComplete: function() {
          destroyGameObject(coin);
          coinTweens.shift();
      },
  });
  //add the tween to the tweens array
  coinTweens.push(collectCoinTween);

  //check if we already have an animation
  if (scoreCoinTimeline) {
      //if animation isn't currently running, then run again
      if (scoreCoinTimeline.progress == 1) {
          animateScoreCoin(this);
      }
  }
  //no animation to create one
  else {
      animateScoreCoin(this);
  }
  score += 10;
  scoreText.setText(score);
}

function growHero() {
  //change sprite to be our larger one
  player.setTexture("hero");
  //manually change the size
  player.setSize(32, 32);
  //set flag we know the player is in big mode
  player.isBig = true;
  //reset our transitional flag
  player.isChangingSize = false;
}

function shrinkHero() {
  //change player to smaller sprire
  player.setTexture("hero-small");
  //manually resize so physics adjusts
  player.setSize(22, 22);
  //set isBig for false so we know the player is small
  player.isBig = false;
  //reset our transitional flag
  player.isChangingSize = false;
}

function collectMushroom(player, mushroom) {
  //stop the players movement
  player.body.velocity.x = 0;
  player.body.velocity.y = 0;
  //set a flag saying the player is transitioning sizes
  player.isChangingSize = true;

  //disable the mushroom so it can only be triggered once
  mushroom.disableBody(false, false);

  //tween the player scaling up in size
  var tween = this.tweens.add({
      targets: player,
      scaleX: 1.5,
      scaleY: 1.5,
      yoyo: 1,
      repeat: 1,
      ease: 'Linear',
      duration: 100,
      onComplete: function() {
          //when the tween is over call this function
          growHero();
      },
  });

  //tween powerup to scale up and then remove
  var tween = this.tweens.add({
      targets: mushroom,
      alpha: 0.3,
      angle: 90,
      scaleX: 0.3,
      scaleY: 0.3,
      ease: 'Linear',
      duration: 500,
      onComplete: function() {
          destroyGameObject(mushroom);
      },
  });
}

function hitQuestionMarkBlock(player, block) {
  //if the block has been hit from the bottom and is not already hit then...
  if (block.body.touching.down && !block.hit) {
      //mark block as hit
      block.hit = true;
      //make the mushroom visible
      block.powerup.visible = true;

      //animate the rising of the mushroom powerup
      var tween = this.tweens.add({
          targets: block.powerup,
          y: "-=24",
          ease: 'Linear',
          duration: 300,
          onComplete: function() {
              //when the animation completes call this function
              emptyQuestionBlock(block);
          },
      });

      //animate the box being hit and jumping up slightly
      var tween = this.tweens.add({
          targets: block,
          y: "-=5",
          ease: 'Linear',
          yoyo: true,
          duration: 100
      });
  }
}

function emptyQuestionBlock(block) {
  //change the sprite of the question mark box
  block.setTexture("empty-box");
  //enable physics on the mushroom powerup
  block.powerup.enableBody = true;
  //turn mushroom powerups gravity back on
  block.powerup.body.setAllowGravity(true);
  //randomly assign left or right direction to the powerup
  if (Math.floor(Math.random() * 1)) block.powerup.setVelocityX(-80);
  else block.powerup.setVelocityX(80);
}

function goInvincibile(player, invicibility) {
  //stop invicibility for being collected twice, as it will stick around on the screen as it aninimates
  invicibility.disableBody(false, false);

  //change players max velocity so they can go super fast
  player.body.maxVelocity.x = superPlayerSpeed;
  //start our emitter
  emitter.resume();

  //flash animations using a tint
  this.tweens.addCounter({
      from: 0,
      to: 100,
      duration: 500,
      yoyo: true,
      repeat: 5,
      onUpdate: function(tween) {
          var value = Math.floor(tween.getValue());
          var newColorObject = Phaser.Display.Color.Interpolate.ColorWithColor(heroColor, invincibleColor, 100, value);
          var color = Phaser.Display.Color.GetColor(newColorObject.r, newColorObject.g, newColorObject.b);
          player.setTint(color);
      },
      onComplete: function() {
          resetInvincibility();
      }
  });

  //tween powerup to scale up and disappear
  var tween = this.tweens.add({
      targets: invicibility,
      alpha: 0.3,
      angle: 90,
      scaleX: 0.3,
      scaleY: 0.3,
      ease: 'Linear',
      duration: 500,
      onComplete: function() {
          destroyGameObject(invicibility);
      },
  });
  //set players invincible flag to true
  player.invincible = true;
}

function resetInvincibility() {
  //reset the invincible flag
  player.invincible = false;
  //reset max speed of player
  player.body.maxVelocity.x = maxPlayerSpeed;
  //pause emitter and remove any existing particles
  emitter.pause();
  emitter.killAll();
}

//rotate score coin and make bigger before shrinking again
function animateScoreCoin(game) {
  scoreCoinTimeline = game.tweens.timeline({
      targets: scoreCoin,
      duration: 100,
      tweens: [{
              scaleX: 0.8,
              scaleY: 0.8,
              angle: "+=45"
          },
          {
              scaleX: 0.5,
              scaleY: 0.5,
              angle: "+=45"
          }
      ]
  });
}

function destroyGameObject(gameObject) {
  // Removes any game object from the screen
  gameObject.destroy();
}
              
            
!
999px

Console