Как проверить, находится ли один прямоугольник в другом? - PullRequest
3 голосов
/ 08 ноября 2010

Хорошо, я работаю над игрой и обнаружил, что моим врагам не нравится мое обнаружение столкновений, которое идеально подходит для моего игрока. После небольшой отладки я обнаружил, что мои враги больше моих фишек, а мой игрок меньше моих фишек.

Теперь мне нужно уметь делать больших врагов и боссов, так что это просто не сработает. поэтому мне нужно найти лучший способ проверить обнаружение столкновений. Вот как я сейчас это делаю:

вверх и вниз:

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
}

Ответы [ 7 ]

5 голосов
/ 08 ноября 2010

В Java используйте intersects(Rectangle r).

3 голосов
/ 08 ноября 2010

Вот как правильно выполнить тесты с разделительной осью (для ориентированных ограничивающих рамок, как вы делаете).

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

Если вам так хочется, прочитайте весь набор учебников. Это будет стоить того, как только вы начнете добавлять в игру больше функций:)

2 голосов
/ 08 ноября 2010

Для тех, кто работает в Objective-C и ищет тот же ответ, вы можете использовать:

bool CGRectIntersectsRect(CGRect rect1, CGRect rect2)
2 голосов
/ 08 ноября 2010

В языках .NET вы можете использовать метод Rectangle.IntersectsWith(Rectangle other) для базового обнаружения коллизий.

1 голос
/ 08 ноября 2010

Я думаю, что проблема заключается в

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, если ЛЮБАЯ часть врага находится в пределах плитки

0 голосов
/ 14 ноября 2010

В .Net уже существует метод с именем Intersect(Rect rect) в Rect классе.

0 голосов
/ 08 ноября 2010

Спрайт шире, чем тайл, но «левый-правый» код не проверяет в этом случае.Если я отображаю ваш код на графике, он просто проверяет, находится ли левый враг или правый враг в тайле:

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