Flash 8: Shape Based Collision Detection

Most of the Flash 8 demos released so far using BitmapData have been purely visual, so I thought I should release one of my experiments that focuses on function.

One of the things that Flashers have wanted for years is shape based hit detection – that is, the ability to detect if one shape intersects with another shape. The best we’ve been able to do so far is test a single point against a clip’s shape, which obviously isn’t that great for games with complex interactions.

Flash 8 changes all of that. Unfortunately, it doesn’t give you an easy method to do it (mc.hitTestShape(mc2) would be nice), but it does give you all the tools you need to make it work. In the simple demo below (requires Flash Player 8r50, earlier versions will show whacky graphic artifacts), you can see shape based hit detection at work.


I know it’s ugly, but this is a functional demo, not an art piece [grin]. Welcome to the era of cheap, ugly bevels and dropshadows on everything – it’s like PhotoShop 5 (or was it 4?) all over again.

It uses a CollisionDetection class that I’ve built, and will release once Flash 8 is release (we have lots of goodies queued up). This is how the method works, in brief:

1) finds the boundary intersection of both clips

2) creates a bitmap the same size as the intersection

3) draws the first clip into the bitmap in red

4) draws the second clip into the bitmap in white, using a difference blend

5) returns the boundaries of cyan in the bitmap (white difference blended on red makes cyan), or null if there is no cyan

You can see the resultant bitmap in the top left corner of the demo.

Because all of the heavy lifting is done in the player, it runs quite quickly (about 2-3ms per comparison). It also supports color transformations that allow me to set an alpha threshold for comparisons (in this example, I using this feature to avoid collisions with the drop shadow). Before Tinic berates me, there is also a method built into BitmapData that will compare two transparent bitmaps, which would be faster if you were working with bitmaps to start, but runs a little slower when working with movieclips (because it requires the creation of an additional bitmap). The above method also has the advantage that you can run multiple comparisons using the same bitmap, which I have taken advantage of in a CollisionEngine class I wrote that combines shape based collision detection with my grid-based proximity manager to provide the ultimate game-oriented collision system.

UPDATE: The source code is now available here.

Grant Skinner

The "g" in gskinner. Also the "skinner".

@gskinner

35 Comments

  1. This is awesome good news! Thanks for the demo!

  2. This is very cool, very very very cool – the demo seems a bit jerky here (the dragging), I’m hoping that is just your implementation tho. So how does this stack up against just using your prox class on movieclips? I use your prox class on a FP7 life simulation thing I made which has lots of fighting and breeding creatures, to keep it fast the graphics are simple but it works, however I still wish it could get above about 30 creatures before getting really slow. I’m hoping that FP8 will enable me to add more detail and make it faster, so have you any good sample comparisons or stats on this sort of thing? How fast is your prox class demo when exported as FP8? stuff like that would be great to know, might stop me trying to learn Processing for my creatures demo v2.

  3. nice application of the new features, Grant!

  4. Why is it that when i zoom in four times, the bevels is removed on the “bad” area? Is that how filters work?

  5. Fantastic news! And a very clever implementation with colour mixing, v.cool!

  6. Amazing thing for game development! thanks

  7. Nice.

    How would you go about resolving the collision?

  8. Michael Follish October 11, 2005 at 8:31am

    Hey, could you send me the fla?

  9. hi.

    I have some question about

    checkForCollision(p_clip1:MovieClip,p_clip2:MovieClip,p_alphaTolerance:Number,p_scope:MovieClip)

    if I try like this

    CollisionDetection.checkForCollision(_root.a.b, car, 120);

    it don’t work

    why?

  10. I’m having the same problem as lala. Is it a scope thing?

  11. the lack of smoothness when dragging the ball is most likely related to the frame rate of the scene

  12. This is really cool!! I appreciate your work a lot 🙂 Btw, I wonder why this doesn’t work with mc inside another mc.

    For example , I converted a shadow in the red ball (mc2) to a movie clip,and named it shadow_mc

    THen I tried,

    var collisionRect:Rectangle = CollisionDetection.checkForCollision(mc1,mc2.shadow_mc,255);

    It doesn’t work. Please advise..

    Thanks!!

  13. Can you please explain the first paramerter (mask) of

    getColorBoundsRect(mask:Number, color:Number, [findColor:Boolean]) ??

    In your code example, we want to get the rect boundary of cyan, why is the mask set white ?

    var intersection:Rectangle = img.getColorBoundsRect(0xFFFFFFFF,0xFF00FFFF);

    Thanks!!

  14. I used this for a little game and it worked great. I had collision detection on 9 independently moving objects with out a hiccup.

    Thanks for the resource,

    Jeff

  15. MajiD Fatemian May 25, 2007 at 1:48pm

    Thank you gskinner.com team.

    You opened my mind to new views.

    I hope I can work with you someday, but first I should get a little bit closer to you;)

  16. Johann Janos May 30, 2007 at 3:39am

    Any chance of getting this to work with gravity? 😮

  17. I want to thank first for this great example of collision detection and say some words about it. I found some mistakes and here there are:

    1. The first boundary check it could be done by using the default hitTest() method = clip1.hitTest(clip2) but that’s optional

    2. You must change the xMin/xMax and yMin/yMax assignments. It calculates different coordinates and don’t return the real image boundary.

    3. The thing I said in 2. is actually not necessary because you these xMin/xMax and yMin/yMax methods to give the “img” object _width and _height parameters. We’ve got our big error here. Done in this way works perfectly but if the Stage is not zoomed! I mean if it is in its original size, when you make it fullscreen for example it doesn’t work. I’ll explain why after a few lines.

    Here’s my way: you give the “img” object these _width and _height parameters:

    1. You create a movie clip in your flash project with these parameters: _x=0; _y=0; _width=Stage._width; _height=Stage._height (the last two parameters is the original size of your flash project). This movie clip appears as a stage mask or something like that, that’s why I’m giving it this name “stage_mask”

    2. Make the “stage_mask” with 0% _alpha, so it can’t be visible;

    3. Use the path to your “stage_mask” Movie clip in your CollisionDetection.as (e.a. _root.gameclip.stage_mask)

    4. Add this to the “img” initiate in the CollisionDetection.as file:

    _root.gameclip.stage_mask._width, _root.gameclip.stage_mask._height

    instead of the bounds2.xMax-…. I don’t remember it 🙂

    What actually make it don’t work in the previous version:

    when in 200% zoom for example the .getBounds method returns the xMin/xMax and yMin/yMax coordinates of the movie clip on the stage (calculated with these 200% of zoom) which means if your MC’s width is 100 pixels it returns 200 because of the 200% zoom, but when you make flash draw a 200 pixels rectangle on the stage and you’re in 200% it actually appears as 400 pixels because of the zoom! What it actually happens is that the image you want to draw has less size than its movie clips. And so the img.getColorBoundsRect(…) method can’t find anything.

    If someone has some questions about this or want the reworked CollisionDetection can write me an e-mail: ivo_yankulovski@abv.bg

  18. In flash script,how to find out the hittest of tow irregular shape?

  19. I can’t seem to get this working for movieclips that are not in the same place/level. I am trying to test a movieclip against other moveiclips that are in a parent array.

  20. I found this very useful, but now I’m using AS3 Im looking for a good AS3 version. I found this: http://www.snowkit.cn/eblog/Article.aspx?id=41 which seems to be similar in concept/method.

    Comments? Alternatives?

  21. STI San Jose a brand of excellent hehe!!!

  22. He, nice work… I’m reusing your code to make a collision class for AI objects in a game (kind of GTA 2 old school setup). Still heavily under development, but it’s getting there with the help of your code.. especially the part where the intersection is registerd is very handy, now i know the exact force-vectors off each vehicle and i can track how to apply them regarding to the collision normal. Adding a little weight to the vehicle and it’s actually starting to look realistic. THNX. When my class is more finished I’ll surely post a link.

  23. Nicw flash

  24. Hey Grant i was curious about the collision class. You don’t have a constructor function and you call you function based on your class name and then function name. Is method of reference only useable in AS2 or can you refer to functions from their classes in AS3 as well?

  25. Opened this in Flash 8 on a Mac. The provided SWFs work, but the detention does not work when I compile from the included FLAs. Compile w/o error, but the balls don’t trigger a collision!

  26. Same thing as dn, tried to fix the path but..uh! does not work properly.

    Any ideas? Thanks in advance

  27. I’m going to post this here in case other people are spending hours trying to figure out the same crash I was just experiencing…

    If you draw a textfield with BitmapData.draw (which this engine uses) and the blending mode is not Normal (this engine uses Difference), it will cause flash to crash. This may or may not pertain to AS2, I don’t know, but is certainly the case with AS3/Flash 9.

  28. This isn’t collision detection at all.

    Collision detection needs to take into account the velocity, position and size of the objects over time.

    Fer example: imagine a square with two balls in the upper right (r) and left corner (l) with velocity such that the ball r ends up in the bottom left and the ball l ends up in the bottom right.

    As you can see, the balls should collide in the middle of the square but this sort of primitive check at each time slice would not detect it at all.

    What you have is more of an intersection test.

  29. Ändres Vargas January 15, 2009 at 2:39pm

    No entiendo porque el ejemplo que esta montado en esta pagina es diferente al que uno descarga?

    En el que uno descarga si el swf es apliado ya no funciona la colision

    que sucede?

  30. niiiice 😀

    thanks!

  31. Thanks Grant. I’ve been struggling with this for weeks, and this has proved incredibly helpful.

  32. thankyou very much for your colision detection, and comment for fullscreen

  33. Hi, what’s the licence on this? I would like to use it for a client project.

    Thanks

  34. My bad… just read the license in the file.
    Thanks

  35. awesome job
    now what can you suggest to block entering objects into each other?
    like cars and walls.

Leave a Reply

Your email address will not be published. Required fields are marked *