Столкновение мяча с мячом — при столкновении приобретает значительную скорость.

StackOverflow https://stackoverflow.com/questions/894935

Вопрос

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

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

Вход:
масса == 12,56637
скорость.x == 1,73199439
скорость.y == -10,5695238

шар.масса == 12,56637
ball.velocity.x == 6.04341078
ball.velocity.y == 14.2686739

Выход:
масса == 12,56637
скорость.x == 110.004326
скорость.y == -10,5695238

шар.масса == 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));

}
Это было полезно?

Решение

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

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

// 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 рассчитан правильно, скорости удара и т. д. и т. п., пока не увидите, где происходит большое увеличение.

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

Другие советы

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

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

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

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

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

/ (im1 + im2)

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

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

CGPoint impulse = ccpMult(mtd, i);

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

CGPoint impulse = ccpMult(ccpNormalize(mtd), i);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top