Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about Spring Ninja game, Game development, HTML5, Javascript and Phaser.

Here we are talking about Spring Ninja prototype again.

What about adding a double jump feature to the final HTML5 prototype I showed you in this post.

First, let’s have a look at the result:

Click and hold to jump, and do the same thing while in the air to perform a double jump.

Let’s now have a look at the source code, with the new lines highlighted:

window.onload = function() {	
	var game = new Phaser.Game(640, 480, Phaser.CANVAS);
	var ninja;
	var ninjaGravity = 800;
	var ninjaJumpPower;    
	var score=0;
	var scoreText;
     var topScore;
     var powerBar;
     var powerTween;
     var placedPoles;
	var poleGroup; 
     var minPoleGap = 100;
     var maxPoleGap = 300; 
     var ninjaJumping;
     var ninjaFallingDown; 
	var jumps; 
	var maxExtraJumps = 1;   
     var play = function(game){}     
     play.prototype = {
		preload:function(){
			game.load.image("ninja", "ninja.png"); 
			game.load.image("pole", "pole.png");
               game.load.image("powerbar", "powerbar.png");
		},
		create:function(){
			ninjaJumping = false;
			ninjaFallingDown = false;
			score = 0;
			placedPoles = 0;
			jumps = 0;
			poleGroup = game.add.group();
			topScore = localStorage.getItem("topFlappyScore")==null?0:localStorage.getItem("topFlappyScore");
			scoreText = game.add.text(10,10,"-",{
				font:"bold 16px Arial"
			});
			updateScore();
			game.stage.backgroundColor = "#87CEEB";
			game.physics.startSystem(Phaser.Physics.ARCADE);
			ninja = game.add.sprite(80,0,"ninja");
			ninja.anchor.set(0.5);
			ninja.lastPole = 1;
			game.physics.arcade.enable(ninja);              
			ninja.body.gravity.y = ninjaGravity;
			addPole(80);
		},
		update:function(){
			game.physics.arcade.collide(ninja, poleGroup, checkLanding);
			if(ninja.y>game.height){
				die();
			}
		}
	}     
     game.state.add("Play",play);
     game.state.start("Play");
	function updateScore(){
		scoreText.text = "Score: "+score+"\nBest: "+topScore;	
	}     
	function prepareToJump(){
		if(ninja.body.velocity.y==0 || jumps<maxExtraJumps){
			jumps++;
	          powerBar = game.add.sprite(ninja.x,ninja.y-50,"powerbar");
	          powerBar.width = 0;
	          powerTween = game.add.tween(powerBar).to({
			   width:100
			}, 1000, "Linear",true); 
			game.input.onDown.remove(prepareToJump, this);
			game.input.onUp.add(jump, this);
          }        	
	}     
     function jump(){
          ninjaJumpPower= -powerBar.width*3-100
          powerBar.destroy();
          game.tweens.removeAll();
          ninja.body.velocity.y = ninjaJumpPower*2;
          ninjaJumping = true;
          powerTween.stop();
          game.input.onUp.remove(jump, this);
		if(jumps<maxExtraJumps){  
			game.input.onDown.add(prepareToJump, this);     
		}  
     }     
     function addNewPoles(){
     	var maxPoleX = 0;
		poleGroup.forEach(function(item) {
			maxPoleX = Math.max(item.x,maxPoleX)			
		});
		var nextPolePosition = maxPoleX + game.rnd.between(minPoleGap,maxPoleGap);
		addPole(nextPolePosition);			
	}
	function addPole(poleX){
		if(poleX<game.width*2){
			placedPoles++;
			var pole = new Pole(game,poleX,game.rnd.between(250,380));
			game.add.existing(pole);
	          pole.anchor.set(0.5,0);
			poleGroup.add(pole);
			var nextPolePosition = poleX + game.rnd.between(minPoleGap,maxPoleGap);
			addPole(nextPolePosition);
		}
	}	
	function die(){
		localStorage.setItem("topFlappyScore",Math.max(score,topScore));	
		game.state.start("Play");
	}
	function checkLanding(n,p){
		game.input.onDown.remove(prepareToJump, this);
		if(n.body.touching.down){
			var border = n.x-p.x
			if(Math.abs(border)>23){
				n.body.velocity.x=border*2;
				n.body.velocity.y=-200;	
			}
			else{
				jumps=0;          
               	game.input.onDown.add(prepareToJump, this);
			}
			var poleDiff = p.poleNumber-n.lastPole;
			if(poleDiff>0){
				score+= Math.pow(2,poleDiff);
				updateScore();	
				n.lastPole= p.poleNumber;
				ninja.x=80;
			}
			if(ninjaJumping){
               	ninjaJumping = false;    
          	}
		}
		else{
			ninjaFallingDown = true;
			poleGroup.forEach(function(item) {
				item.body.velocity.x = 0;			
			});
		}			
	}
	Pole = function (game, x, y) {
		Phaser.Sprite.call(this, game, x, y, "pole");
		game.physics.enable(this, Phaser.Physics.ARCADE);
          this.body.immovable = true;
          this.poleNumber = placedPoles;
	};
	Pole.prototype = Object.create(Phaser.Sprite.prototype);
	Pole.prototype.constructor = Pole;
	Pole.prototype.update = function() {
          if(ninjaJumping && !ninjaFallingDown){
               this.body.velocity.x = ninjaJumpPower;
          }
          else{
               this.body.velocity.x = 0
          }
		if(this.x<-this.width){
			this.destroy();
			addNewPoles();
		}
	}	
}

Since the game engine has been already built in the previous step, there are only a few new lines to see:

Line 17: defining jumps variable to keep track of consecutive jumps

Line 18: we’ll define another variable to make the script more universal: now you can decide how many extra jumps are allowed

Line 31: at the start of the game, jumps is set to zero

Line 60: we have to add another condition to let the player jump, that is we didn’t reach the extra jumps cap already

Line 61: now let’s increment jump by 1

Line 79: if we did not reach the maximum amount of extra jumps…

Line 80: … we add the listener to trigger mouse/touch input

Line 107: as soon as we touch the ground, re remove the listener

Line 114: if the player landed safely on the ground…

Line 115: reset jumps variable to zero

Line 116: add input listener once again

And we developed double jump. Download the full source code.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.