Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Way of an Idea game, Actionscript 3, Box2D, Flash and Game development.

Did you enjoy Way of an Idea?

Nice physics game… besides the joints and motors used in level design, the most interesting part is the chalk drawing.

Way of an Idea.

We are going to do it in three steps

Step 1 – Freehand drawing

Let’s start with a simple script with some mouse listeners to let the player draw when he presses and moves the mouse:

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	public class draw extends Sprite {
		public var drawing:Boolean=false;
		public var canvas:Sprite = new Sprite();
		public function draw():void {
			addChild(canvas);
			canvas.graphics.lineStyle(5)
			stage.addEventListener(MouseEvent.MOUSE_DOWN,mouse_pressed);
			stage.addEventListener(MouseEvent.MOUSE_MOVE,mouse_moved);
			stage.addEventListener(MouseEvent.MOUSE_UP,mouse_released);
		}
		public function mouse_pressed(e:MouseEvent):void {
			drawing=true;
			canvas.graphics.moveTo(mouseX,mouseY);
		}
		public function mouse_moved(e:MouseEvent):void {
			if (drawing) {
				canvas.graphics.lineTo(mouseX,mouseY);
			}
		}
		public function mouse_released(e:MouseEvent):void {
			drawing=false;
		}
	}
}

And this is the result:

Draw with the mouse

Step 2 – Segment drawing

Since the idea is converting a freehand drawing into a set of Box2D primitives, we can’t allow the player to draw as free as he wants.

So we must constrain him to draw with segments of at least n pixels. The smaller n, the more realistic the freehand feeling, the more primitives needed to convert drawing into objects.

In this example I am using a 20 minimum length, but you are free to set your own by changing pixel_dist value at line 8

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	public class draw extends Sprite {
		public var drawing:Boolean=false;
		public var canvas:Sprite = new Sprite();
		public var pixel_dist:int=20;
		public var saved_x:int;
		public var saved_y:int;
		public function draw():void {
			addChild(canvas);
			canvas.graphics.lineStyle(5);
			stage.addEventListener(MouseEvent.MOUSE_DOWN,mouse_pressed);
			stage.addEventListener(MouseEvent.MOUSE_MOVE,mouse_moved);
			stage.addEventListener(MouseEvent.MOUSE_UP,mouse_released);
		}
		public function mouse_pressed(e:MouseEvent):void {
			drawing=true;
			canvas.graphics.moveTo(mouseX,mouseY);
			saved_x=mouseX;
			saved_y=mouseY;
		}
		public function mouse_moved(e:MouseEvent):void {
			if (drawing) {
				var dist_x:int=mouseX-saved_x;
				var dist_y:int=mouseY-saved_y;
				if (dist_x*dist_x+dist_y*dist_y>pixel_dist*pixel_dist) {
					canvas.graphics.lineTo(mouseX,mouseY);
					saved_x=mouseX;
					saved_y=mouseY;
				}
			}
		}
		public function mouse_released(e:MouseEvent):void {
			drawing=false;
		}
	}
}

This is the result:

You can draw with the mouse with almost the same freedom as before

Step 3: Box2D conversion

In the final step we render the segments with Box2D rectangles. We just need to save all vertices in an array, determine segments length and angle with some trigonometry and create static rectangles once the player releases the mouse

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 draw extends Sprite {
		public var drawing:Boolean=false;
		public var canvas:Sprite = new Sprite();
		public var points_array:Array;
		public var pixel_dist:int=20;
		public var saved_x:int;
		public var saved_y:int;
		public var m_world:b2World;
		public function draw():void {
			// world creation
			var worldAABB:b2AABB = new b2AABB();
			worldAABB.lowerBound.Set(-100.0, -100.0);
			worldAABB.upperBound.Set(100.0, 100.0);
			m_world=new b2World(worldAABB,new b2Vec2(0,10),true);
			// end world creation
			// debug draw
			var m_sprite:Sprite;
			m_sprite = new Sprite();
			addChild(m_sprite);
			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);
			// debug draw end
			addChild(canvas);
			canvas.graphics.lineStyle(5);
			stage.addEventListener(MouseEvent.MOUSE_DOWN,mouse_pressed);
			stage.addEventListener(MouseEvent.MOUSE_MOVE,mouse_moved);
			stage.addEventListener(MouseEvent.MOUSE_UP,mouse_released);
			addEventListener(Event.ENTER_FRAME, Update, false, 0, true);
		}
		public function mouse_pressed(e:MouseEvent):void {
			drawing=true;
			canvas.graphics.moveTo(mouseX,mouseY);
			points_array=new Array();
			saved_x=mouseX;
			saved_y=mouseY;
			points_array.push(saved_x);
			points_array.push(saved_y);
		}
		public function mouse_moved(e:MouseEvent):void {
			if (drawing) {
				var dist_x:int=mouseX-saved_x;
				var dist_y:int=mouseY-saved_y;
				if (dist_x*dist_x+dist_y*dist_y>pixel_dist*pixel_dist) {
					canvas.graphics.lineTo(mouseX,mouseY);
					saved_x=mouseX;
					saved_y=mouseY;
					points_array.push(saved_x);
					points_array.push(saved_y);
				}
			}
		}
		public function mouse_released(e:MouseEvent):void {
			drawing=false;
			var sx:int;
			var ex:int;
			var sy:int;
			var ey:int;
			var dist_x:int;
			var dist_y:int;
			var dist:Number;
			var angle:Number;
			var segments:int=points_array.length/2-1;
			for (var i:int=0; i

and this is the final result:

Now you can draw with the mouse and create solid objects along your path.

Download the source code.

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