Collision Series: AABB to AABB - Separation 09/13/2009
AABB to AABB - SeparationLast time we learned how to check for a collision between two axis aligned rectangles and that collision detection doesnt have to be scary. First, an optomization:Thanks to John Blackburne for pointing out a code optomization: In your code, change any division by 2 to multiplication by .5 (multiplication is faster than division). Helpful, but...While having good collision detection is helpful, its not that useful. If you are making a game (especially a platformer), chances are that you need to do something after they collide. You know, something along the lines of separating them so that they DON'T overlap. A character going through the wall or ground isn't my idea of a good game. So lets do something about it! How this is done:You may say: "Well thats all fine and dandy, but how do you get to that point? The good news is that we already have all the information we need with the last code, so we just need to change it a little. Instead of making a function that returns a boolean, we'll just make a function that DOES something. No returns nessecary. This is what we have right now: function checkAABB(r1:MovieClip, r2:MovieClip, custW1:Number = 0, custH1:Number = 0, custW2:Number = 0, custH2:Number = 0):Boolean{ var fAbs:Function = Math.abs; var overlap:Boolean; var xr1:Number = r1.x; var yr1:Number = r1.y; var xr2:Number = r2.x; var yr2:Number = r2.y; (custW1 == 0) ? wr1 = r1.width*.5 : wr1 = custW1*.5; (custH1 == 0) ? hr1 = r1.height*.5 : hr1 = custH1*.5; (custW2 == 0) ? wr2 = r2.width*.5 : wr2 = custW2*.5; (custH2 == 0) ? hr2 = r2.height*.5 : hr2 = custH2*.5; var maxDistX:Number = wr1 + wr2; var maxDistY:Number = hr1 + hr2; var xDist:Number = xr1 - xr2; var yDist:Number = yr1 - yr2; (fAbs(xDist) <= maxDistX && fAbs(yDist) <= maxDistY) ? overlap = true : overlap = false; return overlap; } This is what we will need to change: function collide(r1:MovieClip, r2:MovieClip, custW1:Number = 0, custH1:Number = 0, custW2:Number = 0, custH2:Number = 0):void{ First, we change the function name. We arent just checking anymore. We're colliding. then we change the return type from Boolean to void. We wont need to return anything. With that in mind, we'll skip to the end and just erase this line: return overlap; Now this is when the real change happens. This is the code that will separate the rectangles if they chould overlap. Change this: (fAbs(xDist) <= maxDistX && fAbs(yDist) <= maxDistY) ? overlap = true : overlap = false; To this: if(r1 != r2){ if(xDist <= maxDistX && yDist <= maxDistY){ if(maxDistX - xDist < maxDistY - yDist){ (r1.x < r2.x) ? r1.x -= maxDistX - xDist : r1.x += maxDistX - xDist; } else if(maxDistY - yDist < maxDistX - xDist){ (r1.y < r2.y) ? r1.y -= maxDistY - yDist : r1.y += maxDistY - yDist; } } } Explanation of changesif(r1 != r2){ All this means is: If r1 is not the same object as r2. This prevents an object from trying to seperate from itself (it does nothing, so it wastes CPU). if(xDist <= maxDistX && yDist <= maxDistY){ You already recognise this code, this just detects if they are overlapping. if(maxDistX - xDist < maxDistY - yDist){ (r1.x < r2.x) ? r1.x -= maxDistX - xDist : r1.x += maxDistX - xDist; } This code checks to see if the distance the recatangles are overlapping is smaller on the x axis than the y axis. To seperate objects realisticlly, you need to use the smallest distance of overlap, and only seperate one axis at a time. After it checks to see if the x axis overlap is smaller than the y axis overlap, then it checks to see which side r1 is on comparitivly to r2. It then pushes it out the exact distance nessecary (determined by taking the maxDistX and subtracting it from the distX. This is the exact amount of overlap). else if(maxDistY - yDist < maxDistX - xDist){ (r1.y < r2.y) ? r1.y -= maxDistY - yDist : r1.y += maxDistY - yDist; } This is the same thing, but it only activates if the y overlap is larger than the x overlap. That was simpleThis is further proof that you dont need to stress over basic collision. It is simple stuff. what we have here is pixel perfect collision detection and seperation for simple axis alligned rectangles. Feel free to use this code as you see fit, of course. Suprisingly, the collision seperation is faster than the checking itself. Strange? Yeah, pretty much. Here is what you end up with: CommentsWarll Sun, 13 Sep 2009 22:52:07 Wow, that is nice. Sadly now that i think about it my game is too simple to use this. I promise though I will try and use it, although bar that I have learned a fair bit from this tutorial. Sidar Mon, 21 Sep 2009 08:01:31 Hi there, Sidar Tue, 22 Sep 2009 01:15:17 Hi there =). Sidar Tue, 22 Sep 2009 02:23:34 Ah ofcourse! Sidar Thu, 24 Sep 2009 01:36:32 Hi, its me again... Makoto Fri, 25 Sep 2009 16:29:00 Aloha, Randall Sat, 26 Sep 2009 18:51:44 You should provide the .fla for download so we can have all the code in one place. Sat, 26 Sep 2009 21:09:14 Thanks for all the comments. Sidar Fri, 09 Oct 2009 02:55:15 Ah, thats unfortunate. Your comment will be posted after it is approved. Leave a Reply |
RSS Feed


