Introducing SUPER JUMP in your HTML5 platform games

Read all posts about "" game

Most platform games allow the player to do more than the normal jump. Some feature the double jump, that is the player is able to jump again while jumping (check HTML5 prototype of a Mario Bros game like Lep’s World featuring scrolling, double jump and destructible tiles for more information), some others feature the wall jump.

Yesterday I was playing Super Mario Bros on the Wii with my daughter when I discovered the super jump: if you jump, then once your character touches the ground jump again immediately, Mario will make a bigger jump.

I decided to show you how to add this feature in the prototype I explained in the post Creation of an HTML5 tile based platform game with no engines behind: pure code! so now if you jump, land then jump again in less than 50 milliseconds, you will make an higher jump.

This could add some interesting twists in gameplay, have a look:

Try to reach the upper platform with A and D key to move and W to jump. You won’t be able to reach it, unless you make a super jump.

Jump, and when you touch the ground, jump again as soon as you can!

And this is the source code, with the super jump highlighted:

(function(){
	var canvas = document.getElementById("canvas");   // the canvas where game will be drawn
	var context = canvas.getContext("2d");            // canvas context
	var levelCols=20;							// level width, in tiles
	var levelRows=15;							// level height, in tiles
	var tileSize=32;							// tile size, in pixels
	var playerCol=5;                                  // player starting column
	var playerRow=13;                                  // player starting row
	var playerSize=24;                                // player size
	var sizeDiff=tileSize-playerSize;                 // difference between player and tile size
	var leftPressed=false;                            // are we pressing LEFT arrow key?
	var rightPressed=false;                           // are we pressing RIGHT arrow key?
	var upPressed=false;                              // are we pressing UP arrow key?
	var downPressed=false;                            // are we pressing DOWN arrow key?
	var movementSpeed=3;                              // the speed we are going to move, in pixels per frame
	var playerXSpeed=0;                               // player horizontal speed, in pixels per frame
	var playerYSpeed=0;                               // player vertical speed, in pixels per frame
	var gravityForce=0.5;                             // gravity acceleration, in pixels per frame per frame
	var jumpSpeed=9;                                 	// jump speed
	var superJumpSpeed=15;                            // super jump speed
	var onTheGround=false;                            // Boolean variable which says if we are on the ground
	var jumped=false;                                 // We want to know if the player jumped
	var lastTouch=0                                   // Timestamp of your last Jump, when you touched the ground
	var doubleJumpDelay=50                            // Delay from a jump to another in order to make a double jump, in milliseconds
	var maxFallingSpeed=10;                           // maximum falling speed
	var level = [        						// the 11x9 level - 1=wall, 0=empty space
		[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
		[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],       
		[1,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
		[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1],
		[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
	];
	var playerYPos=playerRow*tileSize+sizeDiff/2;	// converting Y player position from tiles to pixels
	var playerXPos=playerCol*tileSize+sizeDiff/2;    	// converting X player position from tiles to pixels
	canvas.width=640;                                 // canvas width. Won't work without it even if you style it from CSS
	canvas.height=480;                                // canvas height. Same as before
	// simple key listeners
	document.addEventListener("keydown", function(ev){
		switch(ev.keyCode){
			case 65:
				leftPressed=true;
				break;
			case 87:
				// when we jump? when these three conditions are satisfied:
				// 1 - we are on the ground
				// 2 - our vertical speed is equal to zero
				// 3 - the jump button is released
				if(onTheGround && playerYSpeed==0 && !upPressed){
				console.log(new Date().getTime()-lastTouch);
					if(new Date().getTime()-lastTouch<doubleJumpDelay){
						playerYSpeed=-superJumpSpeed;
					}
					else{
						playerYSpeed=-jumpSpeed;
					}
					jumped=true;
					onTheGround=false;
				}
				upPressed=true
				break;
			case 68:
				rightPressed=true;
				break;
			case 83:
				downPressed=true;
				break;
		}
	}, false);

	document.addEventListener("keyup", function(ev){
		switch(ev.keyCode){
			case 65:
				leftPressed=false;
				break;
			case 87:
				upPressed=false;
				break;
			case 68:
				rightPressed=false;
				break;
			case 83:
				downPressed=false;
				break;
		}
	}, false);

	// function to display the level
	function renderLevel(){
		// clear the canvas
		context.clearRect(0, 0, canvas.width, canvas.height);
		// walls = red boxes
		context.fillStyle = "#ff0000";
		for(i=0;i<levelRows;i++){
			for(j=0;j<levelCols;j++){
				if(level[i][j]==1){
					context.fillRect(j*tileSize,i*tileSize,tileSize,tileSize);	
				}
			}
		}
		// player = green box
		context.fillStyle = "#00ff00";
		context.fillRect(playerXPos,playerYPos,playerSize,playerSize);
	}

	// this function will do its best to make stuff work at 60FPS - please notice I said "will do its best"
	window.requestAnimFrame = (function(callback) {
		return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
		function(callback) {
			window.setTimeout(callback, 1000/60);
		};
	})();

	// function to handle the game itself
	function updateGame() {
		// no friction or inertia at the moment, so at every frame initial speed is set to zero
		playerXSpeed=0;
		playerYSpeed+=gravityForce;
		// limiting max vertical speed
		playerYSpeed=Math.min(playerYSpeed,maxFallingSpeed);
		// updating speed according to key pressed
		if(rightPressed){
			playerXSpeed=movementSpeed
		}
		else{
			if(leftPressed){
				playerXSpeed=-movementSpeed;
			}
			else{
				if(upPressed){
					/*playerYSpeed=-movementSpeed;*/
				}
				else{
					if(downPressed){
						/*playerYSpeed=movementSpeed;*/
					}         
				}          
			}         
		}
		// updating player position
		playerXPos+=playerXSpeed;
		playerYPos+=playerYSpeed;

		// check for vertical collisions, got to do it first this time
		var baseCol = Math.floor(playerXPos/tileSize);
		var baseRow = Math.floor(playerYPos/tileSize);
		var colOverlap = playerXPos%tileSize>sizeDiff;
		var rowOverlap = playerYPos%tileSize>sizeDiff;

		if(playerYSpeed>0){
			if((level[baseRow+1][baseCol] && !level[baseRow][baseCol] && rowOverlap) || (level[baseRow+1][baseCol+1] && !level[baseRow][baseCol+1] && colOverlap && rowOverlap)){
				playerYPos = baseRow*tileSize+sizeDiff;
				playerYSpeed=0;
				onTheGround=true;
				if(jumped){
					lastTouch=new Date().getTime();
					jumped=false;
				}
			}	
		}

		if(playerYSpeed<0){
			if((!level[baseRow+1][baseCol] && level[baseRow][baseCol]) || (!level[baseRow+1][baseCol+1] && level[baseRow][baseCol+1] && colOverlap)){
				playerYPos = (baseRow+1)*tileSize;
				playerYSpeed=0;
			}		
		}

		// check for horizontal collisions
		var baseCol = Math.floor(playerXPos/tileSize);
		var baseRow = Math.floor(playerYPos/tileSize);
		var colOverlap = playerXPos%tileSize>sizeDiff;
		var rowOverlap = playerYPos%tileSize>sizeDiff;		

		if(playerXSpeed>0){
			if((level[baseRow][baseCol+1] && !level[baseRow][baseCol] && colOverlap) || (level[baseRow+1][baseCol+1] && !level[baseRow+1][baseCol] && rowOverlap && colOverlap)){
				playerXPos=baseCol*tileSize+sizeDiff;
			}	
		}

		if(playerXSpeed<0){
			if((!level[baseRow][baseCol+1] && level[baseRow][baseCol]) || (!level[baseRow+1][baseCol+1] && level[baseRow+1][baseCol] && rowOverlap)){
				playerXPos=(baseCol+1)*tileSize;
			}	
		}

		// rendering level
		renderLevel();

		// update the game in about 1/60 seconds
		requestAnimFrame(function() {
			updateGame();
		});
	}

	updateGame();

})();

Good super jumping, I hope to see this feature used somehow in your games. Obviously you can also download the source code.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

214 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers