如何测试一个矩形是否在另一个矩形中?

发布于 2024-09-30 17:00:31 字数 711 浏览 2 评论 0原文

好吧,我正在开发一款游戏,我发现我的敌人不喜欢我的碰撞检测,而我的碰撞检测对我的玩家来说非常有效。经过一番调试后,我发现这是因为我的敌人比我的方块大,而我的玩家比我的方块小。

现在我需要能够结交大敌人和老板,所以这是行不通的。所以我需要找到一种更好的方法来测试碰撞检测。这就是我目前正在做的:

向上和向下:

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
}

向左和向右:

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
}

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 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
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

三生一梦 2024-10-07 17:00:31

在 Java 中,使用 相交(矩形 r)

蓝天白云 2024-10-07 17:00:31

以下是如何正确进行分离轴测试(对于定向边界框,就像您所做的那样)。

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

访问此站点,并使用图 3,一次将所有这些都变成真实的。然后一次一个地打破每一项测试。您将根据经验看到它的工作原理,并且非常简单:

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

如果您愿意,请通读整套教程。一旦您开始在游戏中加入更多功能,一切都是值得的:)

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 :)

我的奇迹 2024-10-07 17:00:31

在 .NET 语言中,您可以使用 Rectangle.IntersectsWith(Rectangle other) 方法来执行非常基本的碰撞检测。

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

樱花坊 2024-10-07 17:00:31

对于任何使用 Objective-C 寻找相同答案的人,您可以使用:

bool CGRectIntersectsRect(CGRect rect1, CGRect rect2)

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

bool CGRectIntersectsRect(CGRect rect1, CGRect rect2)
爱她像谁 2024-10-07 17:00:31

我认为问题在于

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

(在第一个代码中),只有当敌人完全位于图块内(高度方向)时,这才会成立,

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

就像您对左+右检查所做的那样。

只是为了澄清这一点意味着您给出的第一个检查将是:

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

}

并且我认为您不需要单独的上/下左/右检查,如果敌人的任何部分在图块内,这应该返回 true

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

花落人断肠 2024-10-07 17:00:31

精灵比图块更宽,但“左右”代码不会检查这种情况。
如果我绘制你的代码,它只是检查敌人左侧或敌人右侧是否位于该图块内:

(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>

但如果整个图块位于敌人区域内,则不会检测到命中:

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

同样,图块较小垂直于敌人,因此有必要检查整个瓷砖是否位于敌人内部。
完整的图/伪代码是:

 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
 ]

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
 ]
请远离我 2024-10-07 17:00:31

.Net中,Rect类中已经有一个名为Intersect(Rect rect)的方法。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文