Столкновения в SDL & C ++ - PullRequest
       65

Столкновения в SDL & C ++

0 голосов
/ 28 февраля 2012

Как рассчитать коллизию между двумя ритами в C ++ и SDL и как сделать так, чтобы игрок не мог пройти через этот прямоугольник (т. Е. Убедиться, что один прямоугольник не может пройти через другой)?

Я знаю, что остановить игрока будет playeryvel = 0, делая скорость игрока Y 0, чтобы они не могли пройти через нее.Моя проблема в том, что это остановит ВСЕ вертикальное движение, когда я хочу остановить движение через другой прямоугольник.

Мой текущий код использует функцию с именем check_collision(SDL_Rect, SDL_Rect).Вот мой код для использования и фактическая функция.

// This loops through a vector, containing rects.
for (int i=0; i<MAP::wall.size(); i++)
{
    std::cout << i << std::endl;
    cMap.FillCustomRect(MAP::wall.at(i), 0xFFFFFF);
    if (check_collision(cMap.wall.at(i), cDisplay.getPlayer(playerx, playery)))
    {
        exit(0); // It exits just as an example to show if there actually is a collision
    }
}


bool check_collision( SDL_Rect A, SDL_Rect B )
{
    //The sides of the rectangles
    int leftA, leftB;
    int rightA, rightB;
    int topA, topB;
    int bottomA, bottomB;

    //Calculate the sides of rect A
    leftA = A.x;
    rightA = A.x + A.w;
    topA = A.y;
    bottomA = A.y + A.h;

    //Calculate the sides of rect B
    leftB = B.x;
    rightB = B.x + B.w;
    topB = B.y;
    bottomB = B.y + B.h;

     //If any of the sides from A are outside of B
    if( bottomA <= topB )
    {
        return false;
    }

    if( topA >= bottomB )
    {
        return false;
    }

    if( rightA <= leftB )
    {
        return false;
    }

    if( leftA >= rightB )
    {
        return false;
    }

    //If none of the sides from A are outside B
    return true;
}

Ответы [ 4 ]

2 голосов
/ 28 февраля 2012

Просто отталкивайте игрока от точки столкновения, каждого кадра. Вам не нужны булевы тесты (столкновение или нет), вам нужно отрегулировать положение игрока в случае столкновения.

  1. Обновить позицию игрока (позиция + = скорость * время);
  2. Если происходит столкновение, отодвиньте игрока от точки столкновения, чтобы столкновение не произошло.

Это может работать очень хорошо, потому что вы сможете «скользить» вдоль стен и т. Д. Для этого вам нужно найти точку контакта, глубину пересечения и направление пересечения (то есть, в каком направлении вы должны нажать игрок отойти).

Конечно, вам нужно посчитать, как далеко вы должны переместить игрока, но в 2D это очень легко сделать.

Вам необходимо вычислить, насколько перекрываются два прямоугольника. Затем вы нажимаете на прямоугольник игрока в направлении (x или y), которое больше всего перекрывается (только в направлении x или y, если они не равны).

1 голос
/ 21 июня 2013

Я вижу, вы использовали код Lazyfoo. Я тоже. У меня была такая же проблема, как и у вас, но я решил ее. Вот как я это сделал.

hero.move(true);   // hero is moved in some direction 
if (check_collision(hero.rect(),box.rect()))  // check for collision after movement 
{
    hero.move(false); // if collision happend , move hero back 
}

SDL_flip(screen);

Выглядит так, будто герой остановился на блоке, но в действительности он будет двигаться вперед, а затем, если произойдет столкновение, двигаться назад. После этого он будет отображаться. Аргументы «истина» и «ложь» используются, чтобы сообщить функции, нужно ли герою двигаться вперед (x + = скорость) или назад (x - = скорость). Если вам понадобится код из моего кода столкновения, просто спросите.

1 голос
/ 29 февраля 2012

Добавить проверку коллизии в функции перемещения. Передайте новую позицию (как если бы она была перемещена) для проверки функции коллизии. Если произойдет столкновение, верните false в функции Move, если нет Move, и верните true.

1 голос
/ 28 февраля 2012

Звучит так, как будто вы ловите свои столкновения только после факта.Скорее всего, вы перемещаете игрока в прямоугольник, поэтому последующие проверки столкновений всегда возвращают true.Есть несколько способов исправить это, но я думаю, что проще всего поймать столкновение до , а не после, и предотвратить его.

Допустим, игрок падает, а выобновить позицию игрока в каждом кадре.Перед тем, как вы переместите положение игрока, вы хотите проверить, не пересекает ли прямоугольник новая позиция.Если новая позиция будет пересекать прямоугольник, вы хотите изменить, насколько далеко игрок переместился (назовем это расстояние step ), чтобы он касался края прямоугольника, но не пересекал его.

...