C ++ 2D Box-Collision, это правильно? - PullRequest
0 голосов
/ 03 июля 2011

Что ж, у меня есть код столкновения 2D-блоков, который в основном проходит по всем блокам в списке, называемом «Блоки», и проверяет, не нахожусь ли я по бокам и еще много чего.

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

Вот и все (это выполняется в цикле):

for(unsigned int i = 0; i<blocks.size(); i++){
Block &b = blocks.at(i);
if(!b.passable==true){
    //Check if we are on the sides
    if(y + height + vspeed >= b.worldY+2 && y + vspeed <= b.worldY+b.height)
    {
        //Right side
        if(x + hspeed <= b.worldX+b.width-1  && x + hspeed > b.worldX+b.width + hspeed-2)
        {
         x = b.worldX + b.width; hspeed = 0;
        }
        //Left side    
        if(x + width + hspeed >= b.worldX +1 && x + width + hspeed <= b.worldX + hspeed + 2)
        {
         x = b.worldX - width; hspeed = 0;
        }
    }

    //Check if we are on the top or the bottom
    if(x + width + hspeed >= b.worldX+2 && x + hspeed <= b.worldX+b.width-2)
    {
        if(y + height + vspeed >= b.worldY && y + height + vspeed <= b.worldY + vspeed + 1 && jumpstate=="falling")
            {
            y = b.worldY - height; jumpstate.assign("ground"); vspeed = 0;
            }

        if(y + vspeed <= b.worldY + b.height && y + vspeed >= b.worldY + b.height + vspeed - 1 && jumpstate=="jumping")
        {
     y = b.worldY + b.height; jumpstate.assign("falling"); vspeed = 0;
        }
     }
  }    
}

Ответы [ 2 ]

0 голосов
/ 03 июля 2011

Хорошо, я вижу несколько мелких деталей:

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

if(x + hspeed <= b.worldX+b.width-1  && x + hspeed > b.worldX+b.width + hspeed-2)

Становится:

if(x + hspeed <= b.worldX + b.width - 1  && x > b.worldX + b.width - 2)

То же самое относится и к другим аналогичным линиям.

2) Небольшие смещения -2 и -1 являютсянемного сбивает с толку, я полагаю, вы пытаетесь получить небольшой буфер, так что требуется небольшое количество наложения.Особенно в этой строке, где вы использовали <вместо <= вы использовали все остальные: </p>

if(x + hspeed <= b.worldX+b.width-1  && x + hspeed > b.worldX+b.width + hspeed-2)

Чтобы сохранить согласованность с остальной частью программы, я, вероятно, написал бы:

if(x + hspeed <= b.worldX + b.width - 1  && x >= b.worldX + b.width - 1)

3) Похоже, вам не хватает нескольких небольших смещений в проверках vert:

Итак, сначала проверьте:

if(y + height + vspeed >= b.worldY && y + height + vspeed <= b.worldY + vspeed + 1 && jumpstate=="falling")

У вас, похоже, естьзабыли ваше маленькое смещение:

if(y + height + vspeed >= b.worldY + 1 && y + height <= b.worldY + 1 && jumpstate=="falling")

Затем вторая проверка:

if(y + vspeed <= b.worldY + b.height && y + vspeed >= b.worldY + b.height + vspeed - 1 && jumpstate=="jumping")

Смещение снова:

if(y + vspeed <= b.worldY + b.height - 1 && y >= b.worldY + b.height - 1 && jumpstate=="jumping")

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

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

if(y + height + vspeed >= b.worldY+2 && y + vspeed <= b.worldY+b.height)

Вторая проверка в этих строках будет ложной, если скорость выше b.height и координаты y схожи.

Надеюсь, что это поможет некоторым.

0 голосов
/ 03 июля 2011

Я не уверен, что вы заставите его работать так. Я объясню решение, которое я придумал для некоторого обнаружения столкновений и отскоков, которое работает плавно. Запишите временной интервал с момента последней проверки столкновений и скорректированной позиции. Если Xplayer+Vplayer*deltaT>Xtarget (если игрок будет перекрывать цель), тогда вычислите фактическое время, когда оно коснется цели deltaTtouch=(Xtarget-Xplayer)/Vplayer. Теперь верните игрока обратно Xplayer=Xtarget-Vplayer*(deltaT-deltaTtouch). Вам придется выяснить все случаи при движении вперед, назад, вверх, вниз.
Л.Е .: Вы также можете реализовать гравитацию, это включает решение квадратного уравнения для определения deltaTtouch.

...