HTML5 one-button minigame prototype made with Phaser
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.