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.
Comments (26)
This is awesome good news! Thanks for the demo!
Posted by: sascha of H1DD3N.R350URC3 at August 12, 2005 12:09 PMURL: http://hiddenresource.corewatch.net/
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.
Posted by: Jon B at August 12, 2005 12:41 PMURL: http://www.scrwd.com
nice application of the new features, Grant!
Posted by: Ivan Todorov at August 12, 2005 05:02 PMURL: http://www.ivantodorov.com
Why is it that when i zoom in four times, the bevels is removed on the "bad" area? Is that how filters work?
Posted by: Robert Sköld at August 13, 2005 09:37 AMURL: http://www.madein.se
Fantastic news! And a very clever implementation with colour mixing, v.cool!
Posted by: Jason M at August 14, 2005 06:46 AMURL: http://www.mentalaxis.com
Amazing thing for game development! thanks
Posted by: fandango at August 14, 2005 11:51 PMURL: http://www.fandango.cz
Nice.
How would you go about resolving the collision?
Posted by: Al at August 15, 2005 05:58 PMURL:
Hey, could you send me the fla?
Posted by: Michael Follish at October 11, 2005 08:31 AMURL:
hi.
I have some question about
checkForCollision(p_clip1:MovieClip,p_clip2:MovieClip,p_alphaTolerance:Number,p_scope:MovieClip)
if I try like this
Posted by: lala at November 18, 2005 01:21 AMCollisionDetection.checkForCollision(_root.a.b, car, 120);
it don't work
why?
URL:
I'm having the same problem as lala. Is it a scope thing?
Posted by: rob at November 18, 2005 02:08 AMURL:
the lack of smoothness when dragging the ball is most likely related to the frame rate of the scene
Posted by: anon at May 7, 2006 07:46 PMURL:
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!!
Posted by: yoko at October 26, 2006 08:17 PMURL:
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!!
Posted by: yoko at October 27, 2006 04:32 PMURL:
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
Posted by: Jeff Marshall\ at November 15, 2006 11:57 AMURL:
Thank you gskinner.com team.
Posted by: MajiD Fatemian at May 25, 2007 01:48 PMYou 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;)
URL:
Any chance of getting this to work with gravity? :o
Posted by: Johann Janos at May 30, 2007 03:39 AMURL:
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
Posted by: Pacific at October 22, 2007 02:02 PMURL:
In flash script,how to find out the hittest of tow irregular shape?
Posted by: kumar at November 20, 2007 04:20 AMURL:
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.
Posted by: Seth at December 31, 2007 04:30 PMURL: http://nuigroup.com
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.
Posted by: Lee Bergman at January 19, 2008 09:43 PMComments? Alternatives?
URL: http://mothteeth.com
STI San Jose a brand of excellent hehe!!!
Posted by: lapayag at January 28, 2008 08:54 PMURL:
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.
Posted by: perry at January 29, 2008 07:19 AMURL: http://www.viralgames.nl
Nicw flash
Posted by: Suljee at March 14, 2008 02:33 AMURL:
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?
Posted by: bnns at March 31, 2008 11:21 AMURL:
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!
Posted by: dn at May 16, 2008 05:21 PMURL:
Same thing as dn, tried to fix the path but..uh! does not work properly.
Any ideas? Thanks in advance
Posted by: delfin at June 18, 2008 12:45 PMURL: http://www.segonquart.com