Обнаружение столкновения и поддержание импульса на объекте - PullRequest
1 голос
/ 07 марта 2012

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

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

Я хотел бы реализовать способ, которым я различаю верх / низ и левый / правыйСтолкновение, но это единственный метод, который работает прилично:

static void CheckCollision(PActor object1, PActor object2, PInput pinput)
{
    if ( CheckObjectCollision( object1, object2 ) )
    {
        AdjustMoveSpeed( object1, object2, pinput );
    }
}



static bool CheckObjectCollision(PActor object1, PActor object2)
{
    int object1LeftBound = object1.position.x;
    int object1RightBound = object1.position.x + object1.actorTextureXSize;
    int object1TopBound = object1.position.y;
    int object1BottomBound = object1.position.y + object1.actorTextureYSize;

    int object2LeftBound = object2.position.x;
    int object2RightBound = object2.position.x + object1.actorTextureXSize;
    int object2TopBound = object2.position.y;
    int object2BottomBound = object2.position.y + object2.actorTextureYSize;

    if ( object1RightBound < object2LeftBound )
        return false;

    if ( object1LeftBound > object2RightBound )
        return false;

    if ( object1BottomBound < object2TopBound )
        return false;

    if ( object1TopBound > object2BottomBound )
        return false;

    return true;        
}

Я предполагаю, что корень некоторых проблем, с которыми я сталкиваюсь, это функция AdjustMoveSpeed, вот она:

static void AdjustMoveSpeed(PActor object1, PActor object2, PInput pinput)
{
    PVector prevMouseLocation = pinput.GetPrevMouseLocation();
    PVector currMouseLocation = pinput.GetCurrMouseLocation();

    int currentMoveSpeed;
    int nextMoveSpeed;

    if (typeid(object1) == typeid(PBall))
    {

        object1.moveSpeed.x *= -1;  

        if ( typeid(object2) == typeid(PPlayer) )
        {
            currentMoveSpeed = object1.moveSpeed.y;
            nextMoveSpeed = prevMouseLocation.y  - currMouseLocation.y;

            object1.moveSpeed.y = (prevMouseLocation.y  - currMouseLocation.y) * -1; 

        }
        else
        {
            if (object1.moveSpeed.y > 0)
                object1.moveSpeed.y *= -1;
        }
    }
    else if (typeid(object2) == typeid(PBall))
    {

        object2.moveSpeed.x *= -1;

        if ( typeid(object1) == typeid(PPlayer) )
        {
            currentMoveSpeed = object1.moveSpeed.y;
            nextMoveSpeed = prevMouseLocation.y  - currMouseLocation.y;

            object2.moveSpeed.y = (prevMouseLocation.y  - currMouseLocation.y) * -1; 
        }
        else
        {
            if (object2.moveSpeed.y > 0)
                object2.moveSpeed.y *= -1;
        }
    }       
}

То, что я пытался сделать с AdjustMoveSpeed, это первая проверка, чтобы увидеть, какой объект является шаром, после этого, умножьте скорость движения x на -1, чтобы изменить направление.После этого я проверяю, является ли другой объект игроком, если это так, я устанавливаю скорость перемещения y равной разнице между предыдущим положением мыши и текущим положением мыши.Это здесь, чтобы дать игроку возможность изменить скорость мячей или добавить вращение.

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

Как правильно проверить обнаружение столкновения на двух объектах, которые являются квадратами?

Как я могу исправить AdjustMoveSpeed, чтобы он правильно работал с обнаружением столкновений?

Наконец, как мне сохранить, чтобы импульс шара его текущей скорости был больше, чем разница местоположения мышидо и после удара?

Я пытался сравнить абсолютные значения currentMoveSpeed ​​и nextMoveSpeed, но тогда мяч не меняет скорость y.Примерно так:

if ( abs(currentMoveSpeed) < abs(nextMoveSpeed )
    object1.moveSpeed.y = (prevMouseLocation.y  - currMouseLocation.y) * -1;
else
  object1.moveSpeed.y *= -1

Ответы [ 2 ]

6 голосов
/ 07 марта 2012

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

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

Это решение называется непрерывное обнаружение столкновений - см. этот ответ для получения дополнительной информации.

2 голосов
/ 07 марта 2012

Если мяч застрял на весле, а не отскакивает, это, вероятно, потому, что он продолжает менять направление назад и вперед. Мяч должен подпрыгивать только в том случае, если он движется к веслу.

if (sgn(object1.moveSpeed.x) == sgn(object1.x - object2.x)) {
  // Ball is already moving away from the paddle, don't bounce!
}
else {
  // Ok to bounce!
  object1.moveSpeed.x *= -1;
}
...