2011-03-19 4 views
4

Я знаю, что быстро движущиеся тела в мире Box2d вызывают эффект туннелирования и проходят друг через друга. Решение состоит в том, чтобы определить тела как пули. Я сделал это, но тела иногда все еще пересекаются друг с другом, особенно если точка столкновения не совсем соответствует середине, а тела частично перекрываются при пересечении. Любое решение?Быстро движущиеся тела в Box2d иногда проходят друг через друга

Это, как я делаю все тела:

redBall = [CCSprite spriteWithFile:@"red-ball" rect:CGRectMake(0, 0, 34, 34)]; 
redBall.tag = 1; 
[self addChild:redBall]; 
ballBodyDef.type = b2_dynamicBody; 
ballBodyDef.position.Set((winSize.width/2)/PTM_RATIO, redBall.position.y/PTM_RATIO); 
ballBodyDef.userData = redBall; 

ballBodyDef.bullet = true; 
_ballBody = _world->CreateBody(&ballBodyDef); 

// Create circle shape 
b2CircleShape circle; 
circle.m_radius = 17.0/PTM_RATIO; 

// Create shape definition and add to body 
b2FixtureDef ballShapeDef; 
ballShapeDef.shape = &circle; 
ballShapeDef.density = 0.2f; 
ballShapeDef.friction = 0.0f; 
ballShapeDef.restitution = 1.0f; 
_ballFixture = _ballBody->CreateFixture(&ballShapeDef); 

Я переезжаю этот шар в TouchesEnd как:

- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 

    UITouch *myTouch = [touches anyObject]; 
    CGPoint location = [myTouch locationInView:[myTouch view]]; 
    location = [[CCDirector sharedDirector] convertToGL:location];   

    CGPoint shootVector = ccpSub(location, striker.position); 
    CGFloat shootAngle = ccpToAngle(shootVector); 
    CGPoint normalizeShootVector = ccpNormalize(shootVector); 

    float x1 = - cos(shootAngle); 
    float y1 = - sin(shootAngle); 

    int power = 0; 
    float dist =ccpDistance(location, redBall.position); 
    if (dist >= 200) 
     power = 20; 
    else if (dist >= 100) 
     power = 10; 
    else if (dist >=75) 
     power = 7; 
    else if (dist >= 60) 
     power = 4; 
    else if (dist >= 50) 
     power = 3; 
    else if (dist >= 35) 
     power = 2; 
    else 
     power = 1; 

    b2Vec2 force = b2Vec2(x1*power, y1*power); 
    _ballBody->ApplyLinearImpulse(force,ballBodyDef.position);  
} 

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

+0

вероятно код поможет нам – BlackBear

+0

я добавил код, связанный. – WaJiyaz

ответ

5

Позвольте мне подробнее остановиться на ответе Даффимо.

Помните метод в CCLayer в tick содержит следующие коды ?:

int32 velocityIterations = 8; 
int32 positionIterations = 1; 

world->Step(dt, velocityIterations, positionIterations); 

Этих два Int32 переменных говорят Box2D, сколько итераций (т.е. проходит) он должен сделать, чтобы применить силы, обнаружение столкновений и т.д. Согласно box2D manual, увеличение этих значений повышает точность моделирования за счет производительности, и наоборот, для уменьшения этих значений. Поэтому я предлагаю вам настроить эти значения, особенно positionIterations, пока вы не удовлетворены результатом.

EDIT:

Вот еще одно предложение. Помните еще раз, что метод tick вызывается с той же скоростью, что и fps, которая составляет не более 60 в секунду? Это означает, что функция b2World::Step выполняет дискретное моделирование с интервалом 1/60 секунды, поэтому быстро перемещающееся тело может пройти через другое тело, если оно занимает меньше времени. Поэтому для решения этой проблемы вам необходимо увеличить частоту дискретного моделирования, скажем, до 180 шагов в секунду. Но вопрос в том, как? Cocos2D-iPhone вызывает метод tick для каждого фрейма, а увеличение частоты кадров (если это возможно) уменьшит производительность и утилит всю вычислительную мощность.

Вот как вы можете сделать это без изменения частоты кадров, вызывая функцию b2World::Step пару раз в тот же клещ:

int32 velocityIterations = 8; 
int32 positionIterations = 1; 
uint substeps = 3; 
float32 subdt = dt/substeps; 

for (uint i = 0; i < substeps; i++) { 
    world->Step(subdt, velocityIterations, positionIterations); 

    // do your physics-related stuff inside here but leave any sprites manipulation outside this loop 
} 
+0

Спасибо, но я уже пробовал с этими значениями. Первоначально они составляли 10 и 1 соответственно. Я пробовал и 20,20. Я также пробовал скорость обрезки от вектора скорости до применения линейного импульса. Но никакого значительного успеха нет. И этот переход через поведение происходит только изредка, а не во все времена. – WaJiyaz

+0

@WJK: Я обновил ответ другим предложением – Lukman

+0

Он добавляет чувствительность при столкновении, но сначала все тела начали двигаться дико. Я попытался сбалансировать движение с помощью подстановок = 2, различных интервалов тика и увеличения плотности тел, но не может достичь желаемых результатов. Кроме того, это влияет на все остальные таймеры и элементы управления контуром. – WaJiyaz

0

Вам необходимо усовершенствовать свое обнаружение проникновения: увеличить чувствительность в любом пространстве или времени или в обоих случаях.

Смежные вопросы