Упругое столкновение между косой стенкой и шаром - PullRequest
2 голосов
/ 28 декабря 2008

У меня проблемы с вычислением углов отражения для шара, поражающего наклонную стену. Я использую алгоритм, взятый из этого урока . Это выглядит так (в Actionscript 3), где p1 - текущий вектор скорости, а p2 - нормаль стены:

private function getReflect2(p1 : Point, p2 : Point) : Point
{

    var wallvec : Point = getNorm(p2);
    var wallnorm  : Point = p2;

    var t : Number = dotProduct(wallvec, p1);
    var n : Number = dotProduct(wallnorm, p1);
    var vt : Point = new Point(wallvec.x * t, wallvec.y * t);
    var vn : Point = new Point(wallnorm.x * -n, wallnorm.y * -n);

    var vx : Number = dotProduct(new Point(1,0), vn) + dotProduct(new Point(1,0), vt);
    var vy : Number = dotProduct(new Point(0,1), vn) + dotProduct(new Point(0,1), vt);
    return new Point(vx, vy);
}

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

Может кто-нибудь заметить мою ошибку? Или предложить лучший алгоритм?

Ответы [ 5 ]

1 голос
/ 28 декабря 2008

Векторы wallvec и wallnorm должны иметь величину 1, чтобы функция работала. Я подозреваю, что функция getNorm () обрабатывает работу для wallvec для вас, но wallnorm, кажется, получает произвольную величину.

Кроме того, ваша реализация не совсем соответствует алгоритму, указанному на странице. В частности, страница использует P2 в качестве направления самой стены. Затем он нормализует вектор (который уменьшает величину до 1 без изменения направления) и копирует его в wallvec. Wallnorm получает нормаль от стены (которая уже на уровне 1).

Моя реализация C выглядит следующим образом. Обратите внимание, что хотя wnx и wny имеют то же направление, что и p2c и p2y, мне все равно пришлось делить на величину.

void solve (double p1x, double p1y, double p2x, double p2y, double *p3x, double *p3y)
{
double wvx = -p2y / sqrt(p2x*p2x+p2y*p2y);
double wvy = p2x / sqrt(p2x*p2x+p2y*p2y);
double wnx= p2x/ sqrt(p2x*p2x+p2y*p2y);
double wny=  p2y/ sqrt(p2x*p2x+p2y*p2y);

double t = wvx*p1x+wvy*p1y;
double n = wnx*p1x+wny*p1y;

double vtx = wvx*t;
double vty = wvy*t;
double vnx = wnx*-n;
double vny = wny*-n;

*p3x=vnx+vtx;
*p3y=vny+vty;

}
0 голосов
/ 07 февраля 2009

это не проверено, но это должно отражать вашу скорость

private function reflectVectors(p1 : Point, p2 : Point) : Point
{
    // get the normalized normal
    var wallNorm:Point = p2.clone();
    wallNorm.normalize(1);

    // v1 = v - 2 * (v.n).n
    var dot:Number = p1.x * wallNorm.x + p1.y * wallNorm.y;
    var diff:Point = wallNorm.clone();
    diff.normalize(dot * -2);
    return p1.add(diff);
}
0 голосов
/ 03 января 2009

Это не совсем ответ на ваш вопрос, но последние несколько строк излишне сложны. Поскольку (1, 0) представляет ось x ,

dotProduct(new Point(1,0), vn)

можно заменить на vn.x. Таким образом, последние три строки вашей функции можно сделать более понятными, просто обратившись к соответствующим членам vn и vt:

return new Point(vn.x + vt.x, vn.y + vt.y);

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

0 голосов
/ 28 декабря 2008

Я думаю, что ответом может быть часть о «(т. Е. Нормаль может выступать в другом направлении)». Если нормаль направлена ​​«в» стену, отражение будет от до стены, а не в ожидаемом вами направлении.

0 голосов
/ 28 декабря 2008

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

Редактировать : Можете ли вы указать все векторные значения, когда P1 равно (1, 0) и P2 равно (0, 1)?

...