2D столкновение ограничивающего прямоугольника - PullRequest
0 голосов
/ 05 октября 2010

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

В настоящее время у меня есть что-то вроде (псевдо-код):

if(PLAYER_BOX IS WITHIN THE BLOCKS Y_RANGE)
{
    if(PLAYER_BOX_RIGHT_SIDE >= BLOCK_LEFT_SIDE && PLAYER_BOX_RIGHT_SIDE <= BLOCK_RIGHT_SIDE)
    {
        return LEFT;
    }
    else if(PLAYER_LEFT_SIDE <= BLOCK_RIGHT_SIDE && PLAYER_LEFT_SIDE >= BLOCK_LEFT_SIDE)
    {
        return RIGHT;
    }
}
else if(PLAYER_BOX IS WITHIN BLOCK X_RANGE)
{
    if(PLAYER_BOTTOM_SIDE >= BLOCK_TOP_SIDE && PLAYER_BOTTOM_SIDE <= BLOCK_BOTTOM_SIDE)
    {
        return ABOVE;
    }
    else if(PLAYER_TOP_SIDE <= BLOCK_BOTTOM_SIDE && PLAYER_TOP_SIDE >= BLOCK_TOP_SIDE)
    {
        return BELOW;
    }
 }

Есть ли здесь логическая ошибка?Или я просто написал что-то не так в своем коде?

ВЫШЕ столкновение работает, но оно не распознает боковое столкновение, когда должно, а иногда - когда не должно.

игра является клоном SuperMario, так что это 2D-платформер с боковым скроллером.

Ответы [ 2 ]

2 голосов
/ 05 октября 2010

Я предполагаю, что проблема в направлении.

Что вы действительно хотите сделать, так это сначала принять во внимание направление «игрока», а затем выполнить свои проверки.

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

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

select movedir
(
   case up:
     //check if hitting bottom of box
     break;
   case down:
     //check if hitting top of box

    etc

}
0 голосов
/ 07 октября 2010

Возможно, вы захотите пересмотреть свои расчеты, используя дельту движения.

Примерно так (также псевдо):


// assuming player graphics are centered
player_right = player.x + player.width / 2;
player_left = player.x - player.width / 2;

player_top = player.y - player.height / 2;
player_bottom = player.y + player.height / 2;

// assuming block graphics are centered as well
block_right = box.x + box.width / 2;
...

// determine initial orientation
if (player_right  block_right) orientationX = 'right';

if (player_top  block_top) orientationY = 'top';

// calculate movement delta
delta.x = player.x * force.x - player.x;
delta.y = player.y * force.y - player.y;

// define a rect containing where your player WAS before moving, and where he WILL BE after moving
movementRect = new Rect(player_left, player_top, delta.x + player.width / 2, delta.y + player.height / 2);

// make sure you rect is using all positive values
normalize(movementRect);

if (movementRect.contains(new Point(block_top, block_left)) || movementRect.contains(new Point(block_right, block_bottom))) {

    // there was a collision, move the player back to the point of collision
    if (orientationX == 'left') player.x = block_right - player.width / 2;
    else if (orientationX == 'right') player.x = block_left + player.width / 2;

    if (orientationY == 'top') player.y = block_top - player.height / 2;
    else if (orientationY == 'bottom') player.y = block_bottom + player.height / 2;

    // you could also do some calculation here to see exactly how far the movementRect goes past the given block, and then use that to apply restitution (bounce back)

} else {

    // no collision, move the player
    player.x += delta.x;
    player.y += delta.y;

}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...