2016-04-13 1 views
3

Просто для предисловия к этому вопросу учтите, что я не прошу «исправить свой код», а какие методы я использовал бы, чтобы исправить эту проблему. Я также извиняюсь, если мое правописание не очень хорошо.2D C++ Обнаружение столкновений почти идеально, но не совсем?

Хорошо, поэтому у меня есть 2D-платформа, которая сравнивает позицию игроков со всеми плитами (в цикле), соответственно разрешает столкновение. Это в значительной степени структура основного игрового цикла:

  1. Проверьте все столкновения (и дает возможность прыгать, если столкновение пыльника с игрока произошло)
  2. Получить вход и скорость игрока изменений соответственно
  3. Добавить тяжести скорость Y
  4. Нанести скорость и трение в положение игроков
  5. рисовать игру
  6. повторить

Но, несмотря на эту работу, существуют две незначительные, но заметные проблемы с системой столкновений (я предоставил изображения, чтобы упростить их). Есть две проблемы: первая не так уж плоха, но вторая рендеринга игра почти неиграбельная!

Проблема 1. Когда вы двигаетесь влево и вправо по полу в игре, иногда игрок теряет всю полученную скорость, а затем должен повторно накапливать эту скорость. Я думаю, это потому, что время от времени моя функция обнаружения столкновений не возвращается должным образом. вот изображение:

The prblem that is occuring

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

Задача 2 (Это еще хуже) Проблема заключается в том, что игрок может по существу прыгать вверх по стенам, потому что, если вы скажете, например, удерживая левую стрелку и удерживая прыжок, игрок будет прыгать вверх по стене. Я предполагаю, что это потому, что функция обнаружения столкновений возвращается true, если столкновение идет со стороны (хотя это не должно). Вот еще одна картина (текст небольшой, извините): Edge collision bug

Так вот моя функция обнаружения столкновений, которая должна в двух «объектов», то возвратите от первого объекта, на котором произошло столкновение, я думаю, что проблема вызывает, когда речь идет об определении направления, как это вызывает проблемы, как показано выше:

//Find the collision vectors 
     float vectorX = (a.Position.x + (a.Scale.x/2)) - (b.Position.x + (b.Scale.x/2)); 
     float vectorY = (a.Position.y + (a.Scale.y/2)) - (b.Position.y + (b.Scale.y/2)); 

     //Find the distance between the two objects 
     float deltaWidth = (a.Scale.x/2) + (b.Scale.x/2); 
     float deltaHeight = (a.Scale.y/2) + (b.Scale.y/2); 

     //Stores the direction of collision 
     Direction collisionDir = Direction::None; 

     //Check if the two objects are intersecting on the x and y axis 
     if (fabs(vectorX) < deltaWidth && fabs(vectorY) < deltaHeight) 
     { 
      //The direction of collision 
      float directionX = deltaWidth - fabs(vectorX); 
      float directionY = deltaHeight - fabs(vectorY); 

      //Check for vertical collision 
      if (directionX >= directionY) 
      { 
       //Check for collisions from the top 
       if (vectorY > 0) 
       { 
        a.Velocity.y = 0; 
        a.Position.y += directionY; 
        collisionDir = Direction::Up; 
       } 

       //Collisions form the botttom 
       else 
       { 
        a.Velocity.y = 0; 
        a.Position.y -= directionY; 
        collisionDir = Direction::Down; 
       } 
      } 

      else if (directionX < directionY/2) 
      { 
       //Check for collisions from the left 
       if (vectorX > 0) 
       { 
        a.Velocity.x = 0; 
        a.Position.x += directionX; 
        collisionDir = Direction::Left; 
       } 

       //Collisions form the right side 
       else 
       { 
        a.Velocity.x = 0; 
        a.Position.x -= directionX; 
        collisionDir = Direction::Right; 
       } 
      } 
     } 

     //Return the direction. 
     return collisionDir; 

Это возвращает направление, мой другой код также проверяет, что направление == Bottom, то это позволит прыжки.

Спасибо за помощь. Я тренируюсь для Людума Дэйра, потому что я планирую (возможно) сделать платформер, и если я не могу определить обнаружение столкновения, я не знаю, насколько хороша моя игра.

В любом случае спасибо - Coder Cameron

+1

Добавить запись в свою игру, в которой будут записаны все данные, связанные с обнаружением столкновения. Таким образом, вы сможете найти условия, в которых он ведет себя неправильно. –

ответ

3

Первое, что я рекомендовал бы сделать себе класс Vector2D который держит вашу координату х и у и несколько перегрузок некоторых операторов, чтобы обеспечить сложение и вычитанием двух Vector2Ds и умножение и деление по ints, плавает и удваивает.Поверьте мне, это сделает вашу жизнь намного легче, поскольку они могут удерживать все ваши силы и точки столкновения.

Далее, когда я использовал стиль столкновения вы используете, я всегда считал, что это:

A) Harder для отладки.

B) Сложнее для других людей следовать вашему коду.

Поэтому я бы рекомендовал создать класс Rectangle2D, который обрабатывает столкновения с другими прямоугольниками и другую необходимую функциональность.

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

Вот пример кода, который, вероятно, поможет то, что я пытаюсь объяснить:

bool Intersects(Rectangle2D other) 
{ 
    //Checks the right, left, bottom then top of the rectangle 
    //against the other. 
    if(other.topLeftCorner.x >= bottomRightCorner.x  //Checks the right 
     || other.bottomRightCorner.x <= topLeftCorner.x //Checks the left 
     || other.topLeftCorner.y >= bottomRightCorner.y //Checks the bottom 
     || other.bottomRightCorner.y <= topLeftCorner.y) //Checks the top 
     return false; 
    else 
     return true; 
} 

Вы можете легко манипулировать этот код, чтобы дать вам направление столкновения. Надеюсь это поможет.

Смежные вопросы