Box2d's fast-moving bodies sometimes pass through each other

I know that the fast moving bodies in the Box2d world cause a tunneling effect and pass through each other. The solution is to identify bodies as bullets. I did this, but sometimes the bodies still intersect with each other, especially if the collision point does not quite correspond to the middle, and the bodies partially overlap at the intersection. Any solution?

This is how I do all bodies:

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); 

I move this ball to TouchesEnd as:

 - (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); } 

This is just a calculation of the distance of the touch point from the ball, finding the force to be applied on the ball in accordance with the distance, and moving the ball in the direction of touch. And this ball collides with any other ball that enters it.

+4
source share
2 answers

Let me elaborate on the duffymo answer.

Remember that the CCLayer tick method contains the following codes ?:

 int32 velocityIterations = 8; int32 positionIterations = 1; world->Step(dt, velocityIterations, positionIterations); 

The two int32 variables tell box2D how many iterations (i.e., passes) should be used to apply forces, detect collisions, etc. According to the box2D manual , increasing these values ​​improves simulation accuracy due to performance, and vice versa, to reduce these values. Therefore, I suggest you adjust these values, especially positionIterations, until you are satisfied with the result.

EDIT:

Here is another suggestion. Remember once again that the tick method is called at the same speed as fps, which is no more than 60 per second? This means that the b2World::Step function performs discrete modeling at 1/60 second intervals, so a rapidly moving body can go through another body if it takes less than this time. Therefore, to solve this problem, you need to increase the frequency of discrete modeling, say, up to 180 steps per second. But the question is how? Cocos2D-iPhone calls the tick method for each frame, and increasing the frame rate (if possible) reduces performance and consumes all the computing power.

Here you can do this without changing the frame rate by calling the b2World::Step function a couple of times within the same checkmark:

 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 } 
+5
source

You need to improve your penetration detection: increase sensitivity both in space and in time or in both cases.

0
source

Source: https://habr.com/ru/post/1344374/


All Articles