Creation of a Flash Stabilize! clone using Box2D – part 3
- November 10, 2009 by Emanuele Feronato
- Filed under Actionscript 3, Box2D, Flash, Game design | 4 Comments
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | 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
They can be easily customized to meet the unique requirements of your project.
4 Responses
Leave a Reply
- Una guida completa al gioco del poker online e una selezione dei migliori casino online.
- casino online
- migliori casino online
- BlackJack online
- casinò online
- Giochi casino

(4 votes, average: 4.75 out of 5)



Emanuele, if you’re interested I could send you a Drawing Custom Joints-code. I just couldn’t find your email anywhere so I’ll be needing it if you wish to take a look at my code.
Example can be viewed at: http://0rava.deviantart.com/art/Demolition-X-139603951
Or less complicated (just shapes&joints)-version here: http://0rava.deviantart.com/art/Demolition-jointX-143367977
Forgot to mention that it has all the joints but pulleys. And the code isn’t in almost any way commented, nor do I have the ability to write a proper tutorial, being pretty much a beginner myself. So if you wish to publish it or write a tutorial, please do so and I’d be honoured.
Also, loving the tutorials.
Sure, send your work to info[at]emanueleferonato.com
[...] I am with the 4th part of this prototype. In part 3 we saw the “next” feature, this time we’ll trigger the collision among crates of [...]