Flash AS3 Pixel based circle collision engine

After seeing the Lineball video teaser I got some email asking me how did I make the hollow circle with Box2D, and how to get a smooth drawing using box primitives.

Well, I have to say I didn’t use Box2d, but another library called Collision Detection Kit.

I’ll publish some tutorial about it once I’ll complete the game, but it’s not the point of today’s post.

A reader from Argentina, Adolfo Chacon, sent me an AS3 basic engine to do the same thing (maybe even better) using the concepts I explained soooooo long ago in the Create a flash draw game like Line Rider or others series.

It’s a basic, uncommented script because it’s just a prototype… basically Adolfo took my old script, adjusted trigonometry and did the magic dividing the simulation in steps to manage slower speeds.

I resized it, changed variable names (translating from spanish) and some operators since the auto format option gave me errors when trying to format a<-b, forcing me to change into a<b*-1.

Now enjoy the 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
package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	public class pixel_engine extends Sprite {
		public var ball_radius:int;
		public var precision:int=120;
		public var degrees_to_radians:Number=0.0174532925;
		public var x_speed:Number=0;
		public var y_speed:Number=0;
		public var friction:Number=0.9;
		public var max_speed:int=15;
		public var gravity:Number=0.98;
		public var steps=2;
		public var ball:ball_mc = new ball_mc();
		public var terrain:terrain_mc = new terrain_mc();
		public function pixel_engine():void {
			addChild(ball);
			ball.x=250;
			ball_radius=ball.width/2;
			addChild(terrain);
			addEventListener(Event.ENTER_FRAME, update);
			stage.addEventListener(MouseEvent.MOUSE_DOWN, reverse_gravity);
		}
		private function reverse_gravity(event:MouseEvent):void {
			gravity*=-1;
		}
		public function update(e : Event):void {
			if (ball.y>400) {
				ball.y-=400;
			}
			if (ball.y<0) {
				ball.y+=400;
			}
			for (var j:int = 1; j<=steps; j++) {
				var number_of_collisions:int=0;
				var sum_x_collision:Number=0;
				var sum_y_collision:Number=0;
				if (x_speed>max_speed) {
					x_speed=max_speed;
				} else {
					if (x_speed<max_speed*-1) {
						x_speed=- max_speed;
					}
				}
				if (y_speed>max_speed) {
					y_speed=max_speed;
				} else {
					if (y_speed<max_speed*-1) {
						y_speed=- max_speed;
					}
				}
				ball.x=ball.x+x_speed/steps;
				ball.y=ball.y+y_speed/steps;
				y_speed=y_speed+gravity/steps;
				for (var i:int=1; i<=precision; i++) {
					var x_test:Number=ball.x+ball_radius*Math.sin(i*360/precision*degrees_to_radians);
					var y_test:Number=ball.y-ball_radius*Math.cos(i*360/precision*degrees_to_radians);
					if (terrain.hitTestPoint(x_test,y_test,true)) {
						number_of_collisions++;
						sum_x_collision=sum_x_collision+x_test;
						sum_y_collision=sum_y_collision+y_test;
					}
				}
				var average_x:Number=sum_x_collision/number_of_collisions;
				var average_y:Number=sum_y_collision/number_of_collisions;
				if (number_of_collisions>0) {
					var collision_angle:Number=Math.atan2(ball.x-average_x,ball.y-average_y)/degrees_to_radians*-1+90;
					var collision_x:Number = ball.x - ball_radius * Math.sin((collision_angle + 90) * degrees_to_radians);
					var collision_y:Number = ball.y + ball_radius * Math.cos((collision_angle + 90) * degrees_to_radians);
					var delta_x:Number = (collision_x - ball.x) / ball_radius * -1;
					var delta_y:Number = (collision_y - ball.y) / ball_radius * -1;
					var speed:Number=Math.sqrt(x_speed*x_speed+y_speed*y_speed)*friction;
					var bounce:Number=Math.atan2(x_speed,y_speed)/degrees_to_radians*-1;
					var ricochet:Number=2*collision_angle-bounce-180;
					x_speed=Math.sin(ricochet*degrees_to_radians)*speed;
					y_speed=- Math.cos(ricochet*degrees_to_radians)*speed;
					while (terrain.hitTestPoint(collision_x, collision_y,true)) {
						ball.x=ball.x+delta_x;
						ball.y=ball.y+delta_y;
						collision_x=ball.x-delta_x*ball_radius;
						collision_y=ball.y-delta_y*ball_radius;
					}
				}
			}
		}
	}
}

And play with the result… just watch the simulation and press left mouse button to reverse gravity.

Download the source code. Who said draw games are dead?

Rate this post: 1 Star2 Stars3 Stars4 Stars5 Stars (10 votes, average: 4.80 out of 5)
Loading ... Loading ...
Flash Templates provided by Template Monster are pre-made web design products developed using Flash technology.
They can be easily customized to meet the unique requirements of your project.
Be my fan on Facebook and follow me on Twitter! Exclusive content for my Facebook fans and Twitter followers

This post has 10 comments

  1. Quintus

    on February 13, 2010 at 2:24 pm

    Awsome!!! :D emanuele you rock

  2. Giulian Drimba

    on February 13, 2010 at 2:48 pm

    This is great!

  3. Hawdon

    on February 14, 2010 at 12:26 pm

    Now the question is, does the ball keep bouncing when it stops or does it fall trough the lines then? Cant check it out right now cause I don’t have flash on this computer…

  4. Weekly Shared Items – 16. February, 2010 | TOXIN LABS - weblog of a german design student from wuerzburg

    on February 16, 2010 at 8:01 am

    [...] Flash AS3 Pixel based circle collision engine [...]

  5. Dauren Yet

    on February 16, 2010 at 8:23 pm

    Oh. It’s nice script, thanks

  6. Mina

    on July 31, 2010 at 4:41 am

    HELLOOO I NEED SOME HELP .. DONT KNOW HOW TO CONTACT YOU :s

    so just to pay your attintion here is some of how much i want your help

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    anyway …

    if i could ask , iam new in game Dev. iam tring to make a car game , and iam stuck with something maybe u could help me out ………..

    i made a MovieClip car >> inside it AS3.0 code of all its speed accelirationa and stuff .. i didnt use pacage because i dont know much about it … anyway , i made a square on the stage and i was tring to detect the collition by HittestObject and it didnt work , someone gave me a link for a bitmap data and it worked but i dont understand it for sure .. i just replaced names … anyway … right now , i wants to write a function that makes the car Never move over or under that square .. like a wall or a building … i couldnt figure it out , could u help me plz , it sounds like insanly easy ..

  7. Robert

    on October 9, 2010 at 4:34 pm

    Fantastic, works wonderfully with a putt-putt game I’m making. Thanks.

  8. Patrick

    on January 25, 2011 at 2:38 am

    Wow man! That works like a charm… I’ve been working on just trying to get a two circle collision to work correctly for about a week straight. I cannot tell you how stressed it was making me, but this is the simplest and cleanest solution I’ve seen yet! Thank you so much man!

  9. nook

    on February 20, 2011 at 2:55 pm

    I like it! Quite simple and effective. Though it doesn’t handle rolling it seems. Ever thought about looking into that?

  10. mahmut ayd?n

    on September 17, 2011 at 2:17 pm

    thank you.good tutorial…