Get the full commented source code of

HTML5 Suika Watermelon Game

Talking about One Button Game game, Game development, HTML5, Javascript and Phaser.

Today I am showing you an HTML5 minigame prototype made with Phaser. It was built over the concept of A strange way to move the player with Flash I published more than seven years ago (time passes on planet earth).

The aim of the game is simple: you control the green circle with the rotating arrow. Once you press/tap the screen, arrow will stop its rotation and your power starts charging. You can see your power in the upper left of the screen.

Once you release touch/click on the screen, the green circle will move along arrow direction, according to the power you set.

Collect yellow circles and avoid red circles or you will die

If you die, you can restart the game clicking here

And this is the fully commented source code.

<!doctype html>
<html>
	<head>
    		<script src="phaser.min.js"></script>
    		<style>
    			body{
			    margin:0;
			    background-color:#444444;
			}
    		</style>
    		<script type="text/javascript">
			window.onload = function() {
				
				var game = new Phaser.Game(320,480,Phaser.CANVAS,"",{preload:onPreload, create:onCreate, update:onUpdate});								
                    
				var ball; // the ball! Our hero
                    var arrow; // rotating arrow 
                    var rotateDirection = 1; // rotate direction: 1-clockwise, 2-counterclockwise
                    var power = 0; // power to fire the ball
                    var hudText; // text to display game info
                    var charging=false; // are we charging the power?
                    var degToRad=0.0174532925; // degrees-radians conversion
                    var score = 0; // the score
                    var coin; // the coin you have to collect
                    var deadlyArray = []; // an array which will be filled with enemies
                    var gameOver = false; // flag to know if the game is over
                    
				// these settings can be modified to change gameplay
				var friction = 0.99; // friction affects ball speed
				var ballRadius = 10; // radius of all elements
                    var rotateSpeed = 3; // arrow rotation speed
                    var minPower = 50; // minimum power applied to ball
                    var maxPower = 200; // maximum power applied to ball
                    
                    // when the game preloads, graphic assets are loaded
				function onPreload() {
					game.load.image("ball", "ball.png");
					game.load.image("deadly", "deadly.png");
					game.load.image("coin", "coin.png");
					game.load.image("arrow", "arrow.png");
				}
				
				// function to be executed when the game is created
				function onCreate() {
					
					// center and scale the stage
					game.scale.pageAlignHorizontally = true;
					game.scale.pageAlignVertically = true;
					game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
                    	game.scale.setScreenSize();
                    	
					// add the ball and set its anchor point in the center
					ball = game.add.sprite(game.world.centerX,game.world.centerY,"ball");
					ball.anchor.x = 0.5;
					ball.anchor.y = 0.5;
					
					// ball starting speed
					ball.xSpeed = 0;
					ball.ySpeed = 0;
					
					// the rotating arrow, look at its x registration point
					arrow = game.add.sprite(game.world.centerX,game.world.centerY,"arrow");
					arrow.anchor.x = -1;
					arrow.anchor.y = 0.5;
					
					// place an enemy
					placeDeadly();
					
					// create and place a coin 
					coin = game.add.sprite(Math.random()*400+40,Math.random()*240+40,"coin");
					coin.anchor.x = 0.5;
					coin.anchor.y = 0.5;
					placeCoin();
					
					// create and place the text showing speed and score
					hudText = game.add.text(5,0,"",{ 
						font: "11px Arial",
						fill: "#ffffff", 
						align: "left" 
					});
					
					// update text content
					updateHud();
					
					// listener for input down
					game.input.onDown.add(charge, this);       
				}
				
				// place an enemy
				function placeDeadly(){
					
					// first, create the enemy and set its anchor point in the center
					var deadly = game.add.sprite(0,0,"deadly");
					deadly.anchor.x = 0.5;
					deadly.anchor.y = 0.5;
					
					// add the newly created enemy in the enemy array
					deadlyArray.push(deadly);
					
					// assign it a random position until such position is legal
					do{
						var randomX=Math.random()*(game.width-2*ballRadius)+ballRadius;
						var randomY=Math.random()*(game.height-2*ballRadius)+ballRadius;
						deadlyArray[deadlyArray.length-1].x=randomX;
						deadlyArray[deadlyArray.length-1].y=randomY;
					} while (illegalDeadly());
				}
				
				// determine if an enemy position is illegal
				function illegalDeadly(){
					
					// if the distance between the enemy and the ball is less than three times the radius, it's NOT legal
					if(getDistance(ball,deadlyArray[deadlyArray.length-1])<(ballRadius*3)*(ballRadius*3)){
						return true;
					}
					
					// if the distance between the enemy and any other enemy is less than two times the radius, it's NOT legal
					for(i=0;i<deadlyArray.length-1;i++){
						if(getDistance(deadlyArray[i],deadlyArray[deadlyArray.length-1])<(ballRadius*2)*(ballRadius*2)){
							return true
						}
					}
					
					// otherwise it's legal	
					return false;
				}
				
				// the function to place a coin is similar to the one which places the enemy, but this time we don't need
				// to place it in an array because there's only one coin on the stage
				function placeCoin(){
				
					// assign the coin a random position until such position is legal
					do{
						coin.x=Math.random()*(game.width-2*ballRadius)+ballRadius;
						coin.y=Math.random()*(game.height-2*ballRadius)+ballRadius;
					} while (illegalCoin());
				}
				
				// determine if a coin position is illegal
				function illegalCoin(){
				
					// if the distance between the coin and any ball is less than 2.5 times the radius, it's NOT legal
					if(getDistance(ball,coin)<(ballRadius*2.5)*(ballRadius*2.5)){
						return true;
					}
					
					// if the distance between the coin and any enemy is less than three times the radius, it's NOT legal
					for(i=0;i<deadlyArray.length;i++){
						if(getDistance(deadlyArray[i],coin)<(ballRadius*3)*(ballRadius*3)){
							return true
						}
					}
					
					// otherwise it's legal
					return false;	
				}
				
				// function to be executed each time the game is updated
				function onUpdate() {
				
					// the game is update only if it's not game over
					if(!gameOver){
						
						// when the player is charging the power, this is increased until it reaches the maximum allowed
						if(charging){
							power++;
							power = Math.min(power,maxPower)    
							// then game text is updated
							updateHud();		
						}
						
						// if the player is not charging, keep rotating the arrow
						else{
							arrow.angle+=rotateSpeed*rotateDirection;
						}
						
						// update ball position according to its speed
						ball.x+=ball.xSpeed;
						ball.y+=ball.ySpeed;
						
						// handle wall bounce
						wallBounce();
						
						// reduce ball speed using friction
						ball.xSpeed*=friction;
						ball.ySpeed*=friction;
						
						// update arrow position
						arrow.x=ball.x;
						arrow.y=ball.y;
						
						// if the player picked a coin, then update score and text, change coin position and add an enemy
						if(getDistance(ball,coin)<(ballRadius*2)*(ballRadius*2)){
							score += 1;
							placeDeadly();
							placeCoin();
							updateHud();	
						}
						
						// if the player hits an enemy, it's game over
						for(i=0;i<deadlyArray.length;i++){
							if(getDistance(ball,deadlyArray[i])<(ballRadius*2)*(ballRadius*2)){
								gameOver = true;
							}	
						}
					}
	    			}
	    			
	    			// function to handle bounces. Just check for game boundary collision
	    			function wallBounce(){
					if(ball.x<ballRadius){
						ball.x=ballRadius;
						ball.xSpeed*=-1
					}
					if(ball.y<ballRadius){
						ball.y=ballRadius;
						ball.ySpeed*=-1
					}
					if(ball.x>game.width-ballRadius){
						ball.x=game.width-ballRadius;
						ball.xSpeed*=-1
					}
					if(ball.y>game.height-ballRadius){
						ball.y=game.height-ballRadius;
						ball.ySpeed*=-1
					}    
				}
	    			
	    			// simple function to get the distance between two sprites
	    			// does not use sqrt to save CPU
	    			function getDistance(from,to){
					var xDist = from.x-to.x
					var yDist = from.y-to.y;
					return xDist*xDist+yDist*yDist;
				}
	    			
	    			// when the player is charging, set the power to min power allowed
	    			// and wait the player to release the input to fire the ball
	    			function charge(){
	    				power = minPower;
	    				game.input.onDown.remove(charge, this); 
					game.input.onUp.add(fire, this);  
					charging=true;
				}
				
				// FIRE!!
				// update ball speed according to arrow direction
				// invert arrow rotation
				// reset power and update game text
				// wait for the player to fire again
				function fire(){
					game.input.onUp.remove(fire, this); 
					game.input.onDown.add(charge, this);
					ball.xSpeed += Math.cos(arrow.angle*degToRad)*power/20;
					ball.ySpeed += Math.sin(arrow.angle*degToRad)*power/20;
					power = 0;
					updateHud();
					charging=false; 
					rotateDirection*=-1;
				}
				
				// function to update game text
				function updateHud(){
					hudText.text = "Power: "+power+" * Score: "+score	
				}
				
	    		};
		</script>
    </head>
    <body>
    </body>
</html>

You can also download the entire project, but I would like to know how would you expand the gameplay and what’s your best score.

My best score is 17.

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