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 (3 votes, average: 4.33 out of 5)
Loading ... Loading ...
If you found this post useful, please consider a small donation.
» 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.

5 Responses

  1. Quintus says:

    Awsome!!! :D emanuele you rock

  2. Hawdon says:

    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…

  3. Dauren Yet says:

    Oh. It’s nice script, thanks

Leave a Reply

flash games company