Create an HTML5 game like Mass Attack with Phaser just using tweens (well, almost)
Talking about Mass Attack game, Game development, HTML5, Javascript and Phaser.
The more I use Phaser, the more I like it.
Today I want to show you how easy is to create an HTML5 game like Mass Attack just using Phaser’s tweens and some JavaScript.
Mass Attack is a very old but fun game based on the very simple idea of balancing weights on a scale. Just press the mouse button to create a spheric weight. The longer you hold down the mouse the larger the weight that is created.
It does not feature any physics engine so I will improve my Flash AS2 prototype I made seven years ago using Phaser’s tweens.
Have a look at the final project (you can also play it with your mobile phone from this link):
Click-touch and hold to create a sphere, release to drop the sphere, watch it bounce on the balance and move it accordingly. It shouldn’t be hard to perfectly create the original game out of this.
And the script was very easy to do, like all Phaser stuff I made so far. Look at the fully commented code:
<!doctype html>
<html>
<head>
<script src="phaser.min.js"></script>
<style>
body{margin:0}
</style>
<script type="text/javascript">
window.onload = function() {
var game = new Phaser.Game(320,480,Phaser.CANVAS,"",{preload:onPreload, create:onCreate, update:onUpdate});
// this array will handle the balance itself along with its graphics and data
var balance = [];
// are we making the ball grow?
var growBall = false;
// the ball itself
var ball;
// changing these variables will affect gameplay
// ball growing speed, in pixels per frame
var ballGrowingSpeed = 0.5;
// variable to limit balance movement
var balanceFriction = 400;
// maximum ball radius
var maxDiameter = 50;
// preloading images
function onPreload() {
game.load.image("balance","assets/balance.png");
game.load.image("ball","assets/ball.png");
}
// blueprint function to scale the game, you will want to use it in all your projects
function scaleGame(){
game.scale.pageAlignHorizontally = true;
game.scale.pageAlignVertically = true;
game.scale.scaleMode = Phaser.ScaleManager.SHOW_ALL;
game.scale.setScreenSize();
}
function onCreate() {
scaleGame();
// balance[0] will be the left balance
balance[0] = game.add.group();
// set left balance weight to zero
balance[0].weight = 0;
// balance[1] will be the right balance
balance[1] = game.add.group();
// set right balance weight to zero
balance[1].weight = 0;
// adding the balance sprite to left balance, a 160x20 rectangle
var balanceSprite = game.add.sprite(80,240,"balance");
balanceSprite.anchor.x = 0.5;
balanceSprite.anchor.y = 0.5;
balance[0].add(balanceSprite);
// adding the balance sprite to right balance
balanceSprite = game.add.sprite(240,240,"balance");
balanceSprite.anchor.x = 0.5;
balanceSprite.anchor.y = 0.5;
balance[1].add(balanceSprite);
// waiting for the player to click/touch the screen, then call placeBall function
game.input.onDown.add(placeBall, this);
}
// the player clicked/touched the screen, so we are going to create a ball
function placeBall(){
// add ball sprite at coordinates ("x input",0)
ball = game.add.sprite(game.input.worldX,0,"ball");
ball.anchor.x = 0.5;
ball.anchor.y = 0.5;
// setting ball width and height to 1
ball.width=1;
ball.height=1;
// ball.balance = 0 if placed on the left half of the screen, else = 1
ball.balance = Math.floor(ball.x/(game.width/2))
// adding the ball to the proper group
balance[ball.balance].add(ball);
// placing the ball 30 pixels from the top of the stage, no matter group y position
ball.y = 30-balance[ball.balance].y
// don't wait anymore for the player to click/touch the screen
game.input.onDown.remove(placeBall, this);
// wait for the player to release click/touch, then call dropBall function
game.input.onUp.add(dropBall, this);
// make ball grow
growBall=true;
}
// at every frame, we just make ball grow if the ball should grow and it still has not reached its maximum diameter
function onUpdate() {
if(growBall && ball.width<maxDiameter){
ball.width+=ballGrowingSpeed;
ball.height+=ballGrowingSpeed;
}
}
// function to be executed when the player released the click/touck, time to make the ball fall
function dropBall(){
// the ball stops growing
growBall = false;
// the listener is removed
game.input.onUp.remove(dropBall, this);
// now it's time to calculate ball destination.
// it have to land on the top of the balance, whose top side is at y=230
// ball radius is ball.height/2
// so the final destination is 230+1-radius
// the +1 is to give a slight overlap effect not to make the ball seem to actually touch the balance
var ballDestination = 231-ball.height/2;
console.log(balance[ball.balance].y+" , "+(ball.height/2)+" -> "+ballDestination)
// increase balance weight according to ball volume formula
// volume = 4/3*PI*radius^3
balance[ball.balance].weight+=(4/3)*Math.PI*(ball.width/2)*(ball.width/2)*(ball.width/2);
// tween the ball to its destination during two seconds with a bounce easing effect
var ballTween = game.add.tween(ball).to({
y: ballDestination
}, 2000, Phaser.Easing.Bounce.Out, true);
// call adjustBalances function once the tween is over
ballTween.onComplete.add(adjustBalances,this);
}
// function to adjust balances position according to weights
function adjustBalances(){
// finding the weight difference between the balances and divide it by the friction
var weightDifference = (balance[0].weight-balance[1].weight)/balanceFriction;
// limit weight difference to prevent balances fly off the screen
if(weightDifference>game.height/3){
weightDifference = game.height/3;
}
if(weightDifference<-game.height/3){
weightDifference = -game.height/3;
}
// adding tween to balances
var balanceTween = game.add.tween(balance[0]).to({
y: weightDifference
}, 2000, Phaser.Easing.Quadratic.Out, true);
var balanceTween2 = game.add.tween(balance[1]).to({
y: -weightDifference
}, 2000, Phaser.Easing.Quadratic.Out, true);
// once the tween is over, you should check if the level has been completed.
// I'll just let the ball fall again
balanceTween.onComplete.add(allowBallFalling)
}
// this function will just add another listener to create next ball
function allowBallFalling(){
game.input.onDown.add(placeBall, this);
}
};
</script>
</head>
<body>
</body>
</html>
I plan to make a couple of commercial games with Phaser, I am enjoying it every day a little more.
Download the source code of the prototype.
Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.
