Столкновение шара с мячом - набирает значительную скорость при столкновении - PullRequest
4 голосов
/ 22 мая 2009

Я реализовал код из вопроса " Столкновение шара с мячом - обнаружение и обработка " в Objective-C. Однако всякий раз, когда шары сталкиваются под углом, их скорость резко возрастает. Вся векторная математика выполняется с использованием cocos2d-iphone с заголовком CGPointExtension.h. В чем причина этого нежелательного ускорения?

Ниже приведен пример увеличения скорости:

Введите:
масса == 12,56637
speed.x == 1.73199439
speed.y == -10.5695238

бал.масс = = 12,56637
ball.velocity.x == 6.04341078
ball.velocity.y == 14.2686739

Выход:
масса == 12,56637
speed.x == 110.004326
speed.y == -10.5695238

ball.mass == 12.56637
ball.velocity.x == -102.22892
ball.velocity.y == -72.4030228

#import "CGPointExtension.h"
#define RESTITUTION_CONSTANT (0.75) //elasticity of the system

- (void) resolveCollision:(Ball*) ball
{
    // get the mtd (minimum translation distance)
    CGPoint delta = ccpSub(position, ball.position);
    float d = ccpLength(delta);
    // minimum translation distance to push balls apart after intersecting
    CGPoint mtd = ccpMult(delta, (((radius + ball.radius)-d)/d)); 


    // resolve intersection --
    // inverse mass quantities
    float im1 = 1 / [self mass]; 
    float im2 = 1 / [ball mass];

    // push-pull them apart based off their mass
    position = ccpAdd(position, ccpMult(mtd, (im1 / (im1 + im2))));
    ball.position = ccpSub(ball.position, ccpMult(mtd, (im2 / (im1 + im2))));

    // impact speed
    CGPoint v = ccpSub(velocity, ball.velocity);
    float vn = ccpDot(v,ccpNormalize(mtd));

    // sphere intersecting but moving away from each other already
    if (vn > 0.0f) return;

    // collision impulse
    float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / ([self mass] + [ball mass]);
    CGPoint impulse = ccpMult(mtd, i);


    // change in momentum
    velocity = ccpAdd(velocity, ccpMult(impulse, im1));
    ball.velocity = ccpSub(ball.velocity, ccpMult(impulse, im2));

}

Ответы [ 3 ]

5 голосов
/ 22 мая 2009

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

Почему вы добавляете 1,0 к коэффициенту реституции?

От: http://en.wikipedia.org/wiki/Coefficient_of_restitution

COR обычно является числом в диапазоне [0,1]. Качественно 1 представляет идеально упругое столкновение, а 0 представляет совершенно неупругое столкновение. Теоретически возможно превышение COR больше единицы, представляющее столкновение, которое генерирует кинетическую энергию, например, мины, сбрасываемые вместе и взрывающиеся.

Другая проблема заключается в следующем:

/ (im1 + im2)

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

3 голосов
/ 22 мая 2009

Я тот, кто написал исходный код возврата мяча, на который вы ссылались. Если вы скачаете и попробуете этот код, вы увидите, что он работает нормально.

Следующий код правильный (как у вас изначально):

// collision impulse
float i = (-(1.0f + RESTITUTION_CONSTANT) * vn) / (im1 + im2);
CGPoint impulse = ccpMult(mtd, i);

Это очень распространенный физический код, и вы можете увидеть, что он почти точно реализован следующим образом:

Это правильно, и это не создает CoR более 1.0, как предлагали другие. Это вычисление относительного вектора импульса на основе массы и коэффициента реституции.

Игнорируя трение, простой 1d пример выглядит следующим образом:

J = -Vr(1+e) / {1/m1 + 1/m2}  

Где e - ваш CoR, Vr - нормализованная скорость, а J - скалярное значение импульсной скорости.

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

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

Я не знаю ничего, касающегося разработки iPhone, но я бы предложил установить точку останова в верхней части этого метода и отслеживать итоговое значение каждого шага и определять, где происходит взрыв. Убедитесь, что MTD рассчитан правильно, скорости удара и т. Д., И т. Д., Пока вы не увидите, где вводится большое увеличение.

Сообщите значения каждого шага в этом методе, и мы увидим, что у нас есть.

0 голосов
/ 13 августа 2012

В этой строке:

CGPoint impulse = ccpMult(mtd, i);

Mtd должен быть нормализован. Ошибка произошла потому, что в исходном коде mtd нормализовался в предыдущей строке, но не в вашем коде. Вы можете исправить это, выполнив что-то вроде этого:

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
...