开发者

How to test if one rect is in another rect?

Alright, so I'm working on a game and I have found out that my enemies don't like my collision detection that works perfectly for my player. After a little debugging I found out it's because my enemies are bigger than my tiles, while my player is smaller than my tiles.

Now I need to be able 开发者_JS百科to make big enemies and bosses, so this just won't do. so I need to figure out a better way to test collision detection. This is how I am currently doing it:

up and down:

if((enemy.left > tile.left && enemy.left < tile.right || enemy.right > tile.left && enemy.right < tile.right) && enemy.top < tile.bottom && enemy.bottom > tile.top){
    //collision
}

left and right:

if((enemy.top > tile.top && enemy.top < tile.bottom || enemy.bottom > tile.top && enemy.bottom < tile.bottom) && enemy.left < tile.right && enemy.right > tile.left){
     //colision
}


In Java, use intersects(Rectangle r).


Here's how to correctly do the separating axis tests (for oriented bounding boxes, like you're doing).

if (firstObject.Left < secondObject.Right && firstObject.Right > secondObject.Left
    && firstObject.Top < secondObject.Bottom && firstObject.Bottom > secondObject.Top)
{
    // Intersecting
}

Go to this site, and play with Figure 3, making all of these true one at a time. Then break each of the tests, one at a time. You'll see empirically that it works, and is about as simple as you can get:

http://www.metanetsoftware.com/technique/tutorialA.html#section1

If you feel like it, read through the whole set of tutorials. It'll be worth it once you start packing more features into your game :)


In .NET languages, you can use the Rectangle.IntersectsWith(Rectangle other) method to perform very basic collision detection.


For anyone working in Objective-C looking for the same answer you can use:

bool CGRectIntersectsRect(CGRect rect1, CGRect rect2)


I think the problem lies in

enemy.top < tile.bottom && enemy.bottom > tile.top

(In first code), this will only be true if enemy is within the tile fully (height-wise)

enemy.top > tile.top && enemy.top < tile.bottom || enemy.bottom > tile.top && enemy.bottom < tile.bottom

Like you have done with the left + right check.

Just to clarify this would mean the first check you gave would be:

if((enemy.left > tile.left && enemy.left < tile.right || enemy.right > tile.left && enemy.right < tile.right) && (enemy.top > tile.top && enemy.top < tile.bottom || enemy.bottom > tile.top && enemy.bottom < tile.bottom)){
//collision

}

And with this I dont think you would need seperate up/down left/right checks, this should return true if ANY part of enemy is within tile


The sprite is wider than the tile, but the "left-right" code doesn't check for that case. If i graph your code, it simply checks whether the enemy left or the enemy right lies within the tile:

(enemy.left > tile.left && enemy.left < tile.right
|| enemy.right > tile.left && enemy.right < tile.right)

// graphed as<br>
// TL EL TR ----- or ----- TL ER TR<br>

but if the entire tile lies within the enemy region, no hit is detected:

//  EL TL ----- and ----- TR ER

Similarly, the Tile is smaller vertially than the enemy, so it is necessary to check the if the entire tile lies within the enemy. The complete graph/pseudo code is:

 is_hit :
 // T{L,R,T,B} => tile, E{L,R,T,B} => enemy
 // left-right:
 [
  TL EL TR ----- or ----- TL ER TR
           . or .
  EL TL ----- and ----- TR ER
 ]
 .and.
 // top-bottom:
 [
  TT ET TB ----- or ----- TT EB TB
           . or .
  ET TT ----- and ----- TB EB
 ]


In .Net there is already a method named Intersect(Rect rect) in Rect class.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜