Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Stabilize! game, Actionscript 3, Box2D, Flash and Game development.

Here we are with the 3rd step.

Read steps 1 and 2, then continue with this post.

One thing I missed in Stabilize! was the “next” feature, something showing the block we are going do drop after the current one.

The first time I saw this feature was in Tetris… now try to imagine yourself playing Tetris without the “next” piece displayed somewhere on the screen. What a lack of strategy!!

So we are going to introduce the “next” feature in this game.

In order to do this, we must have different crates. So now each crate has a random color (from 1 to 5) and a random weight (from 1 to 9).

The principle of this feature is to randomly generate both the current and the next crate when we start the game, and give the player the current one.

When the player drops the current crate, give him the previously generated “next” one and randomly generate the next “next” one, that will be given to the player once he drops the old “next” one, and so on.

So here it is the commented script:

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import Box2D.Dynamics.*;
	import Box2D.Collision.*;
	import Box2D.Collision.Shapes.*;
	import Box2D.Common.Math.*;
	public class stabilize extends Sprite {
		public var m_sprite: Sprite = new Sprite();
		public var m_world:b2World;
		// the_crate is the crate sprite
		public var the_crate:crate=new crate();
		// next_crate
		public var next_crate:crate=new crate();
		// droppable_area is the sprite representing the area your mouse
		// must overlap to drop a crate
		public var droppable_area:drop_area = new drop_area();
		// this is the weight of the current crate I am dropping
		public var cur_drop:int=Math.ceil(Math.random()*9);
		// this is the color of the current crate I am dropping
		public var cur_color:int=Math.ceil(Math.random()*5);
		// weight and color of "next" crate
		public var next_drop:int=Math.ceil(Math.random()*9);
		public var next_color:int=Math.ceil(Math.random()*5);
		public function stabilize() {
			var gravity:b2Vec2=new b2Vec2(0,9.8);
			var worldAABB:b2AABB = new b2AABB();
			worldAABB.lowerBound.Set(-1000,-1000);
			worldAABB.upperBound.Set(1000,1000);
			m_world=new b2World(worldAABB,gravity,true);
			m_sprite = new Sprite();
			addChild(m_sprite);
			addChild(droppable_area);
			addChild(the_crate);
			// assigning the crate current weight and color
			the_crate.weight.text=cur_drop.toString();
			the_crate.gotoAndStop(cur_color);
			addChild(next_crate);
			// assigning "next" crate weight and color
			next_crate.weight.text=next_drop.toString();
			next_crate.gotoAndStop(next_color);
			next_crate.x=250;
			next_crate.y=385;
			debug_draw();
			AddBox(250/30,350/30,10/30,10/30,0,false);
			AddBox(250/30,350/30,200/30,10/30,20,false);
			addEventListener(Event.ENTER_FRAME,Update);
			stage.addEventListener(MouseEvent.MOUSE_DOWN,mousePressed);
			stage.addEventListener(MouseEvent.MOUSE_MOVE,mouseMoved);
		}
		public function mousePressed(e:MouseEvent) {
			// look at hitTestPoint... the final true value says it's going to to check against the actual pixels
			// instead of the bounding box
			if (droppable_area.hitTestPoint(mouseX,mouseY,true)) {
				// notice the cur_drop parameter, I am passing the weight of the current crate to the AddBox function
				AddBox(mouseX/30,mouseY/30,0.5,0.5,cur_drop,true);
			}
		}
		public function mouseMoved(e:MouseEvent) {
			the_crate.x=mouseX;
			the_crate.y=mouseY;
			if (droppable_area.hitTestPoint(mouseX,mouseY,true)) {
				the_crate.alpha=1;
			} else {
				the_crate.alpha=0.5;
			}
		}
		// function AddBox
		// px: x position
		// py: y position
		// _halfwidth: half of the box width
		// _halfheight: half of the box height
		// density: density of the box (0: static)
		// is_crate: if true, it's a crate (and you should render the proper movieclip
		public function AddBox(px:Number,py:Number,_halfwidth:Number,_halfheight:Number,density:Number,is_crate:Boolean) {
			var bodyDef:b2BodyDef = new b2BodyDef();
			bodyDef.position.Set(px,py);
			var boxDef:b2PolygonDef = new b2PolygonDef();
			boxDef.SetAsBox(_halfwidth,_halfheight);
			boxDef.density=density;
			boxDef.friction=0.3;
			boxDef.restitution=0.2;
			if (is_crate) {
				bodyDef.userData = new crate();
			}
			var body:b2Body=m_world.CreateBody(bodyDef);
			body.CreateShape(boxDef);
			body.SetMassFromShapes();
			if (is_crate) {
				addChild(bodyDef.userData);
				// assigning current weight and color to the Box2D sprite bound to the box I created
				bodyDef.userData.weight.text=cur_drop.toString();
				bodyDef.userData.gotoAndStop(cur_color);
				// updating current weight and color with the next ones
				cur_drop=next_drop;
				cur_color=next_color;
				// changing current crate movieclip according to its weight and color
				the_crate.weight.text=cur_drop.toString();
				the_crate.gotoAndStop(cur_color);
				// calculating next crate weight and color
				next_drop=Math.ceil(Math.random()*9);
				next_color=Math.ceil(Math.random()*5);
				// updating next crate movieclip according to its weight and color
				next_crate.weight.text=next_drop.toString();
				next_crate.gotoAndStop(next_color);
			}
		}
		public function Update(e:Event) {
			m_world.Step(1/30,10);
			for (var bb:b2Body = m_world.m_bodyList; bb; bb = bb.m_next) {
				if (bb.m_userData is Sprite) {
					bb.m_userData.x=bb.GetPosition().x*30;
					bb.m_userData.y=bb.GetPosition().y*30;
					bb.m_userData.rotation = bb.GetAngle() * (180/Math.PI);
				}
			}
		}
		public function debug_draw() {
			var dbgDraw:b2DebugDraw = new b2DebugDraw();
			var dbgSprite:Sprite = new Sprite();
			m_sprite.addChild(dbgSprite);
			dbgDraw.m_sprite=m_sprite;
			dbgDraw.m_drawScale=30;
			dbgDraw.m_alpha=1;
			dbgDraw.m_fillAlpha=0.5;
			dbgDraw.m_lineThickness=1;
			dbgDraw.m_drawFlags=b2DebugDraw.e_shapeBit;
			m_world.SetDebugDraw(dbgDraw);

		}
	}
}

And this is the result:

The “next” crate is the one under the bar. Download the source code

Next time, we’ll see how to remove crates when three or more of them have the same color and collide

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