Managing multiple collision detection with Flash
In all tutorials covered until now, we have always seen how to determine collisions between a single object and the rest of the objects in the stage, or part of them.
No matter if it was performed using hit test or trigonometry, the point is that in every moment of the game we knew all the objects that could be involved in a collision detection.
For example, collision between one ball and the state, or one bullet and enemies, and so on.
Sometimes we have to manage multiple collision detection.
Try to imagine a shoot’em up game, where several projectiles are fired against enemy ships, or a breakout/arkanoid clone where a power up multiplies the number of ball in the stage, or a pool game where every ball can hit every other ball or the table bounds.
Since we do not know how many objects there are in the stage, we need a routine to scan all objects and determine if they collide among each others.
There are two types of multiple collision: the first is when we have two (or more) separate types of objects that can collide. For example, in a shoot’em up we know we do not care about collisions among enemy ships themselves while we care about collisions between enemy ships and bullets.
In the following example we have two classes of objects: the evil red squares and the good blue squares. When a red square hit a blue square, they both die. We won’t care about collisions among squares of the same color.
In the first step, I’ll put on the stage 20 blue squares moving horizontally and 20 red squares moving vertically.
To do this, I created a blue square object linkaged as “blue” and a red square objects linkaged as “red”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | for (x=1; x<=20; x++) {
blue = _root.attachMovie("blue", "blue_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:Math.random()*500, _y:Math.random()*350});
blue.speed = 2+Math.random()*3;
blue.onEnterFrame = function() {
this._x += this.speed;
if (this._x>500) {
this._x -= 500;
}
};
}
for (x=1; x<=20; x++) {
red = _root.attachMovie("red", "red_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:Math.random()*500, _y:Math.random()*350});
red.speed = 2+Math.random()*3;
red.onEnterFrame = function() {
this._y -= this.speed;
if (this._y<0) {
this._y += 350;
}
};
} |
Line 1: Loop to be executed 20 times
Line 2: Attaching the blue movieclip at the next highest depth and placing in a random place of thes tage
Line 3: Giving the blue movieclip a random speed
Line 4: Beginning of the function to be executed at every frame
Line 5: Moving the blue square according to its speed
Lines 6-8: If the blue square reaches the right end of the stage, then have it reappearing from the left side
Lines 11-20: Same routine with red squares execpt they are moving vertically
Now we have a bunch of boxes moving.
What we want is to check if any blue box hits any red box
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 | var blue_array = new Array();
for (x=1; x<=20; x++) {
blue_array.push("blue_"+_root.getNextHighestDepth());
blue = _root.attachMovie("blue", "blue_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:Math.random()*500, _y:Math.random()*350});
blue.speed = 2+Math.random()*3;
blue.onEnterFrame = function() {
this._x += this.speed;
if (this._x>500) {
this._x -= 500;
}
};
}
for (x=1; x<=20; x++) {
red = _root.attachMovie("red", "red_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:Math.random()*500, _y:Math.random()*350});
red.speed = 2+Math.random()*3;
red.onEnterFrame = function() {
this._y -= this.speed;
if (this._y<0) {
this._y += 350;
}
for (x in blue_array) {
if (this.hitTest(_root[blue_array[x]])) {
_root[blue_array[x]].removeMovieClip();
this.removeMovieClip();
blue_array.splice(x, 1);
}
}
};
} |
Line 1: Creation of an array called blue_array that will contain blue boxes instances.
Line 3: Pushing in the array the name of the box we are about to create. It’s very important to place this line before the creation line (line 4) or the getNextHighestDepth() function will return the (obviously) next highest depth. I mean that if you are about to create your first box the next highest depth is n, if you already created it then you next highest depth will be n+1. The push method adds one or more elements to the end of an array and returns the array’s new length.
Line 21: loop that scans all elements in the blue_array array
Line 22: checking if a hit test between the red square and the x-th element in the blue_array (the x-th blue square) happens.
Lines 23-25: if positive, removing the red square movieclip, the blue square movieclip and the element from the blue_array array. The splice method removes n elements (in our case 1) from the m-th position (in our case x) in the array.
You may need to refresh the page to see the code in action
Being the “easy” case, you may notice there are lots of collision detections:in the initial case there are 20 blue squares that may collide with 20 red squares. That is as much as 400 hit test performed on every frame.
In a 30fps shooter, this means 12000 hit tests per second.
Think about it when you are going to make a game.
The “hard” case happens when any movieclip may hit any other movieclip, for example in a pool game, or in this case
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var blue_array = new Array();
for (x=1; x<=40; x++) {
blue = _root.attachMovie("blue", "blue_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:Math.random()*500, _y:Math.random()*350});
blue.xspeed = 2+Math.random()*3;
blue.yspeed = 2+Math.random()*3;
blue.onEnterFrame = function() {
this._x += this.xspeed;
this._y -= this.yspeed;
if (this._x>500) {
this._x -= 500;
}
if (this._y<0) {
this._y += 350;
}
};
} |
This is the same case as the one with blue and red boxes, execpt there are only blue boxes.
Let’s examine now the collision engine:
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 | var blue_array = new Array();
for (x=1; x<=40; x++) {
blue_array.push("blue_"+_root.getNextHighestDepth());
blue = _root.attachMovie("blue", "blue_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:Math.random()*500, _y:Math.random()*350});
blue.xspeed = 2+Math.random()*3;
blue.yspeed = 2+Math.random()*3;
blue.onEnterFrame = function() {
this._x += this.xspeed;
this._y -= this.yspeed;
if (this._x>500) {
this._x -= 500;
}
if (this._y<0) {
this._y += 350;
}
for (x in blue_array) {
if (this != _root[blue_array[x]]) {
if (this.hitTest(_root[blue_array[x]])) {
_root[blue_array[x]].removeMovieClip();
this.removeMovieClip();
blue_array.splice(x, 1);
}
}
}
};
} |
Line 17: In the loop cycling through the array, before performing the hit test I must be sure I am not testing the hit of a movie with itself.
The remaining code is the same as for blue/red boxes.
You may need to refresh the page to see the code in action
Seems to work well but… it doesn’t.
Try to imagine the first movieclip testing the hit with the second one, the third, fourth and so on.
Now we have the second movieclip testing the hit with the first one, the third, fourth, and so on.
As you can see, I checked the hit between the first and the second movieclip two times: one when I check between the 1st and the 2nd and one when I check between the 2nd and the 1st.
What a waste of time!!
To prevent this, we need this fix:
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 | var blue_array = new Array();
for (x=1; x<=40; x++) {
blue_array.push("blue_"+_root.getNextHighestDepth());
blue = _root.attachMovie("blue", "blue_"+_root.getNextHighestDepth(), _root.getNextHighestDepth(), {_x:Math.random()*500, _y:Math.random()*350});
blue.xspeed = 2+Math.random()*3;
blue.yspeed = 2+Math.random()*3;
blue.onEnterFrame = function() {
this._x += this.xspeed;
this._y -= this.yspeed;
if (this._x>500) {
this._x -= 500;
}
if (this._y<0) {
this._y += 350;
}
for (x in blue_array) {
if (this.getDepth()>_root[blue_array[x]].getDepth()) {
if (this.hitTest(_root[blue_array[x]])) {
_root[blue_array[x]].removeMovieClip();
this.removeMovieClip();
blue_array.splice(x, 1);
}
}
}
};
} |
Now line 17 performs the test only if the target movieclip has a depth lower than its own depth. In this case there is no test for the 1st movieclip, the 2nd performs the test only with the 1st, the 3rd with the 2nd and the 1st and so on.
You may need to refresh the page to see the code in action
In the previous case to perform all tests in a frame I needed 40*39 = 1560 tests
In this one I need only 39+38+37…+2+1 = 780 tests
And this is the right way.
That’s all you need to know about multiple collision detection, now we can start planning a good shooter game.
Download the source codes and give me feedback.
They can be easily customized to meet the unique requirements of your project.
14 Responses to “Managing multiple collision detection with Flash”
Leave a Reply
- Get up to $100,000 for your next Flash game with Mochi GAME Developer Fund
- Create a dynamic content animated footer ad for your site in just 9 jQuery lines – 17 lines version
- Sell sitelocked version of your Flash games and even .fla sources to Free Online Games
- Protect your work from ActionScript code theft with SWF Protector
- Create a dynamic content animated footer ad for your site in just 9 jQuery lines
- Understanding Box2D’s one-way platforms, aka CLOUDS
- Triqui MochiAds Arcade plugin for WordPress upgraded to 1.2
- Box2D Flash game creation tutorial – part 2
- 11 Flash isometric engines you can use in your games
- Monetize your Flash games with GamesChart
- Create a Lightbox effect only with CSS - no javascript needed
- Flash game creation tutorial - part 1
- Create a Flash Racing Game Tutorial
- Flash game creation tutorial - part 2
- Make a Flash game like Flash Element Tower Defense - Part 2
- Flash game creation tutorial - part 3
- Make a Flash game like Flash Element Tower Defense - Part 1
- Create a flash draw game like Line Rider or others - part 1
- Triqui MochiAds Arcade plugin for WordPress official page
- Create a flash artillery game - step 1
- Flash game creation tutorial – part 5.2 (4.88/5)
- Create a flash artillery game – step 1 (4.79/5)
- Create a Flash Racing Game Tutorial (4.76/5)
- Create a flash artillery game – step 2 (4.74/5)
- Create a survival horror game in Flash tutorial – part 1 (4.73/5)
- Creation of a Flash arcade site using WordPress – step 2 (4.73/5)
- Flash game creation tutorial – part 2 (4.71/5)
- Flash game creation tutorial – part 1 (4.70/5)
- Create a flash draw game like Line Rider or others – part 1 (4.69/5)
- Creation of a platform game with Flash – step 2 (4.68/5)







it was great tutorial and check your mail, i sent you the 2nd part of my game.
Wow Emmanule.
You must have psychic powers or something because this tutorial is just what I needed at the moment, lol. Yesterday, while waiting for your next tut I decided to create a mini-game where random tanks come flying at you. I just got stuck on finding a way to have the tanks detect if they were shot. You’ve answered my prayers. :P.
Emanuele* Sorry. :D
NICE!!! Came up with another method after looking at http://www.kirupa.com/developer/actionscript/multiple_collision2.htm and your coding.
a rough formula outline, will be posting a sample on my site soon
var num:Number=5;
//loop thru every object except last object
for(var i:Number=0;i
looks like the zombie infection simulation on the internet
Thanks alot Emanuele. I needed to detect collision between multiple homing missiles and this does the job perfectly!!
Thanks, this is cool trick.
this.getDepth()>_root[blue_array[x]].getDepth()
I’m working on a game where 5 different objects fall from the sky…I already have everything falling randomly and duplicating when they hit the ground then falling randomly again. The problem is in the hit test…the results for 3 of the objects should be the same when they hit the object on the ground and the result for the other 2 should be the same. How do I group the three and then the two into a variable so that I just have 2 hittest if and else statements? I’d really appreciate your help…I’m just a flash beginner!
What version of actionscript is this?
Rachel: its AS 2.0
So, could you then refer to the blue boxes as
[blue_array], why do you need to refer to it as [blue_array[x]]?
Wow, you always seem to have just the thing I’m looking for. I’ve looked all around the web and this is the ONLY tutorial about collision detection with mutiple duplicated movieclips.
By the way, will this work for objects like circles?
Always a pleasure to read your tutorials. Straight to the point, easy to follow, perfect results.
LOVE YOU!!!
Thank You!!!
This has helped so much and is what I needed because I am new with arrays, now I just have to test it with my game.
yeah – agree – this is the stuff
this.getDepth()>_root[blue_array[x]].getDepth()
THANK YOU!