Відповідь прямокутника зіткнення


10

У мене виникають труднощі з рухомим прямокутником для зіткнення з більш ніж одним прямокутником.

Я використовую SFML, і він має зручну функцію, intersectsяка називається, яка займає 2 прямокутника і повертає перехрестя. У мене вектор повний прямокутників, з яким я хочу, щоб мій рухливий прямокутник стикався. Я переглядаю це за допомогою наступного коду (p - прямокутник, що рухається).

IsCollidingWithповертає bool, але також використовує SFML intersectsдля опрацювання перехресть.

while(unsigned i = 0; i!= testRects.size(); i++){
   if(p.IsCollidingWith(testRects[i]){
        p.Collide(testRects[i]);
   }
}

і фактичний Collide()код:

void gameObj::collide( gameObj collidingObject ){

 printf("%f %f\n", this->colliderResult.width, this->colliderResult.height);

if (this->colliderResult.width < this->colliderResult.height) {
    // collided on X
    if (this->getCollider().left < collidingObject.getCollider().left ) {
        this->move( -this->colliderResult.width , 0);
    }else {
        this->move( this->colliderResult.width, 0 );
    }

}

if(this->colliderResult.width > this->colliderResult.height){
    if (this->getCollider().top < collidingObject.getCollider().top ) {
        this->move( 0, -this->colliderResult.height);
    }else {     
        this->move( 0, this->colliderResult.height );
    }

}

і IsCollidingWith()код:

bool gameObj::isCollidingWith( gameObj testObject ){
if (this->getCollider().intersects( testObject.getCollider(), this->colliderResult )) {
    return true;
}else {
    return false;
}

Це добре працює, коли Rectна сцені лише 1 . Однак, коли їх більше, Rectце спричиняє проблеми при розробці двох зіткнень одночасно.

Будь-яка ідея, як правильно з цим боротися? Я завантажив у youtube відео, щоб показати свою проблему. Консоль праворуч показує ширину та висоту перехресть. Ви можете побачити на консолі, що вона намагається обчислити 2 зіткнення одразу, я думаю, саме тут і виникає проблема.

Нарешті, подане нижче зображення наче добре ілюструє мою проблему:

прямокутник, що стикається з кількома іншими прямокутниками


Відеопосилання розірвано.
XiaoChuan Yu

Чи colliderповертаються об'єкти this->getCollider()оновленими this->move()??
XiaoChuan Yu

Чи можете ви додати трохи більше інформації? У чому саме проблема? Здається, відео YouTube демонструє передбачувану поведінку, а в сцені є лише один прямокутник.
Вакідев

Відповіді:


3

Ваше зображення ілюструє одну з безлічі проблем із спробою використання опуклих фігур - особливо прямокутників - для імітації плоскої поверхні, як підлога. Алгоритм призводить до того, що персонажі застрягають на внутрішніх краях фігур, що складають підлогу.

Просте виправлення для цього полягає в тому, щоб перевірити лише вертикальне зіткнення, виправити це, а потім знову перевірити на горизонтальне зіткнення. Якщо ви не падаєте і не намагаєтесь ковзати вниз по стіні, тоді ви хочете спочатку перевірити наявність горизонтальних зіткнень. Як ви знаєте, коли слід перевірити, хто перший? Ви можете зробити це на основі того, який компонент швидкості більший (якщо горизонтальний рух більший, спочатку перевірте вертикальні зіткнення, інакше перевіряйте горизонтальні зіткнення).

Що може бути ще простішим та більш ефективним - натомість створити список країв для вашого світу. Тобто, для ваших коробок, що складають підлогу, встановіть прапор, який вказує, що тільки їх верхній край насправді стикається, а потім ігноруйте зіткнення з іншими краями. Ви не зможете використовувати рутину зіткнення SFML для цього, але, чесно кажучи, просто поле зіткнення - це, можливо, найпростіший біт коду, який ви коли-небудь будете писати в грі. Ця техніка працює особливо добре, якщо ваш світ вирівняний у сітку. Я хотів би перевірити чудові навчальні посібники щодо Metanet (http://www.metanetsoftware.com/technique.html/) для цієї методики.

Ви збираєтеся зіткнутися з багатьма іншими проблемами, намагаючись створити просту 2D-платформу, як ви. Напевно, найкращий ресурс, який я бачив для цього часу, є наступним, який слід прочитати, а потім прочитати ще раз:

http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/


1

Можливо, простим рішенням було б перевірити наявність зіткнень з кожним прямокутником і рухатись назад, у зворотному напрямку руху, доки не буде виявлено зіткнення. Якщо це вирішує проблему, реалізація також повинна бути досить простою.


+1, я фактично про це писав тут: gamedev.stackexchange.com/questions/38252/…
Маркус фон Броаді

0

Я не думаю, що обчислення двох зіткнень не є проблемою, це лише проблема продуктивності. Для правильного керування зіткненням його, можливо, доведеться перевірити двічі. Використовуючи свою діаграму, подумайте, якщо A спершу тестується на B, тоді його потрібно буде протестувати і над іншими полями, і він може зіткнутися з іншим.

Сподіваюся, що це корисно?


0

Це на самому ділі не є оптимальним способом, ви повинні намагатися визначити там ранній час , коли і перша точка вздовж рухаються об'єктів шляху , де відбуваються зіткнення і переміщення об'єктів в цю позицію (або позиції в розрахунковий час), намагаючись виправити на основі проникаючих позицій після руху дуже проблематично, але ви можете використовувати свій поточний процес з невеликою зміною. Просто продовжуйте перевіряти на зіткнення, поки їх немає.

bool collided = true;
while(collided) {
   collided = false
   while(unsigned i = 0; i!= testRects.size(); i++){
      if(p.IsCollidingWith(testRects[i]){
         collided = true
         p.Collide(testRects[i]);
      }
   }
}

Зауважте, що існують ситуації, коли це призведе до нескінченного циклу (подумайте про ситуацію, коли переміщення коробки із зіткнення призводить до іншої колекції, а переміщення коробки з цього зіткнення повертає її назад у ту саму позицію, що і раніше)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.