Giving Boxy2D Some Muscle

by Gritfish on July 10, 2011

Last time we took a brief look at the drag and drop physics engine, boxy2d. Now I’m going to show you how easy it is to add a bit of polish to our game and show just how well boxy plays with tweening engines. Here’s an example of the finished file:

Get Adobe Flash player

A word on tweening engines

This post assumes some basic knowledge of tweening. In this example I’m using tweennano, because of its small file size, and small memory usage. There is nothing preventing you from using another engine like tweener or gtween, but some of the code will need to be replaced.

Tweening gravity to make the game feel more “fluid”

If this was a real marble labyrinth game, you’d be able to adjust the angle to make the ball move faster or slower. On a keyboard, there’s only on and off. In the code below, we take the key listeners from before, and replace the code with tweens:

function keyDown_up() {
	TweenNano.to(boxyStage.gravity, 0.3, {y:-0.1});
}
function keyDown_down() {
	TweenNano.to(boxyStage.gravity, 0.3, {y:0.1});
}
function keyDown_left() {
	TweenNano.to(boxyStage.gravity, 0.3, {x:-0.1});
}
function keyDown_right() {
	TweenNano.to(boxyStage.gravity, 0.3, {x:0.1});
}

function keyUp_up() {
	TweenNano.to(boxyStage.gravity, 0.3, {y:0});
}
function keyUp_down() {
	TweenNano.to(boxyStage.gravity, 0.3, {y:0});
}
function keyUp_left() {
	TweenNano.to(boxyStage.gravity, 0.3, {x:0});
}
function keyUp_right() {
	TweenNano.to(boxyStage.gravity, 0.3, {x:0});
}

Adding a second layer to simulate tilting

Another thing that adds depth to a game? Depth! Copy the walls from tour boxy stage into a new movie clip and break them down into shapes. Put the movie clip on your root timeline above the boxy stage clip.

Now to give that sense of depth, we’re going to shift this new layer based on the gravity set by our tweening.

function __oef(e:Event) {
	frontLayer.x=boxyStage.gravity.x*50;
	frontLayer.y=boxyStage.gravity.y*50;
}
addEventListener(Event.ENTER_FRAME, __oef);

Adding animation when the user falls down a hole

Our fields (holes) fire off a function when the ball is completely inside them. Let’s tween the size of the ball so that it looks like it’s falling down.

var resetInt;
function reset() {
	boxyStage.player.x=25;
	boxyStage.player.y=25;
	boxyStage.player.vecX=boxyStage.player.vecY=0;
	boxyStage.player.scaleX=boxyStage.player.scaleY=1;
}
function badHole(target) {
	TweenNano.to(boxyStage.player, 0.3, {y:target.y+target.height/2, x:target.x+target.width/2,scaleX:0,scaleY:0});
	TweenNano.to(boxyStage.player, 0, {delay:0.35, y:20, x:20, vecX:0, vecY:0,scaleX:1.2,scaleY:1.2, overwrite:false});
	TweenNano.to(boxyStage.player, 0.3, {delay:0.4, y:25, x:25,scaleX:1,scaleY:1, overwrite:false});
	frontLayer.x=boxyStage.gravity.x=frontLayer.x=boxyStage.gravity.y=0;
	resetInt=setTimeout(reset,700);
}
function goodHole(target) {
	TweenNano.to(boxyStage.player, 0.3, {y:target.y+target.height/2, x:target.x+target.width/2,scaleX:0,scaleY:0});
	frontLayer.x=boxyStage.gravity.x=frontLayer.x=boxyStage.gravity.y=0;
}

Depending on your tweening engine, this code may break. Why? The field runs that function every frame as long as the ball is over it, which may start the tween over again every frame. So, let’s break that connection first, and remove the ball from collision checking by setting it’s type to static:

var resetInt;
function badHole(target) {
	TweenNano.to(boxyStage.player, 0.3, {y:target.y+target.height/2, x:target.x+target.width/2,scaleX:0,scaleY:0});
	TweenNano.to(boxyStage.player, 0, {delay:0.35, y:20, x:20, vecX:0, vecY:0,scaleX:1.2,scaleY:1.2, overwrite:false});
	TweenNano.to(boxyStage.player, 0.3, {delay:0.4, y:25, x:25,scaleX:1,scaleY:1, overwrite:false});

	frontLayer.x=boxyStage.gravity.x=frontLayer.x=boxyStage.gravity.y=0;
	boxyStage.player.removeRef("ball");
	boxyStage.player.objType = ObjType.STATIC;
	resetInt=setTimeout(reset,700);
}
function goodHole(target) {
	TweenNano.to(boxyStage.player, 0.3, {y:target.y+target.height/2, x:target.x+target.width/2,scaleX:0,scaleY:0});

	frontLayer.x=boxyStage.gravity.x=frontLayer.x=boxyStage.gravity.y=0;
	boxyStage.player.removeRef("ball");
	boxyStage.player.objType = ObjType.STATIC;
}

And reconnect it and reset it to dynamic once our animation has run, and the ball is back at its starting position:

function reset() {
	boxyStage.player.x=25;
	boxyStage.player.y=25;
	boxyStage.player.vecX=boxyStage.player.vecY=0;
	boxyStage.player.scaleX=boxyStage.player.scaleY=1;
	boxyStage.player.addRef("ball");
	boxyStage.player.objType = ObjType.DYNAMIC;
}

Our game is starting to come together! In the next post, we’ll take the game out of the computer and onto a phone using the accelerometer to control the movement!

Download Example Files (.zip)