Cocos2d iphone Box2d中快速移动的物体有时会相互穿过

Cocos2d iphone Box2d中快速移动的物体有时会相互穿过,cocos2d-iphone,box2d-iphone,Cocos2d Iphone,Box2d Iphone,我知道Box2d世界中快速移动的物体会产生隧道效应,并相互穿过。解决方案是将实体定义为项目符号。我这样做了,但身体有时仍然会相互交叉,特别是当相遇点不完全朝向中间,身体在交叉时部分重叠时。有解决办法吗 这就是我制作所有身体的方式: redBall = [CCSprite spriteWithFile:@"red-ball" rect:CGRectMake(0, 0, 34, 34)]; redBall.tag = 1; [self addChild:redBall]; ballBodyDef.t

我知道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);
我在触球时移动此球SEND为:

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

它只是简单地计算接触点到球的距离,根据距离找到施加在球上的力量,并将球向接触方向移动。这个球和其他任何挡在它前面的球碰撞

您需要改进渗透检测:在空间或时间或两者中增加灵敏度。

让我进一步阐述duffymo的答案

还记得CCLayer的
tick
方法包含以下代码吗

int32 velocityIterations = 8;
int32 positionIterations = 1;

world->Step(dt, velocityIterations, positionIterations);
这两个int32变量告诉box2D应进行多少次迭代(即通过),以应用力、检测碰撞等。根据,增加这些值可以提高模拟的精度,但会牺牲性能,反之亦然,降低这些值也会提高模拟的精度。所以我建议你调整这些值,特别是位置迭代,直到你对结果满意为止

编辑:

这里还有一个建议。请再次记住,
tick
方法的调用速率与fps相同,最多为每秒60次?这意味着
b2World::Step
函数以1/60秒的间隔进行离散模拟,因此,如果快速移动的物体需要的时间少于该时间,则可以设法通过另一个物体。为了解决这个问题,你需要增加离散模拟的频率,比如说每秒180步。但问题是怎么做?Cocos2D iPhone为每一帧调用
勾选
方法,增加帧速率(如果可能的话)将降低性能并浪费所有处理能力

下面介绍了如何在不更改帧率的情况下,在同一个刻度内多次调用
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
}
int32速度迭代=8;
int32=1;
uint子步=3;
float32 subdt=dt/子步;
对于(uint i=0;i步骤(subdt、速度迭代、位置迭代);
//在这里做你的物理相关的事情,但是把精灵的操作留在这个循环之外
}

该代码可能会对我们有所帮助。我添加了相关代码。谢谢,但我已经尝试使用这些值。最初他们分别是10和1。我也试过用20,20。在应用线性脉冲之前,我还尝试从速度矢量中调整速度。但没有重大成功。这种穿越行为只是偶尔发生,并非总是发生。它确实增加了碰撞的敏感性,但起初所有的物体都开始疯狂地移动。我试着用子步=2、不同的滴答声间隔和增加身体密度来平衡运动,但无法达到预期的效果。除此之外,它还影响到所有其他计时器和循环控件。通过对一些事物的可变值进行试验,我最终找到了所需的移动和碰撞。子步=2就足够了。谢谢你。顺便说一句,您不是“新手”程序员,所以请公正地对待自己:)将速度交互和位置迭代提高一倍对我来说不如每次更新调用world.step两次。谢谢事实上,将VelocityInteractions和positionIterations设置为1并运行两次步骤对我来说比将VelocityInteractions和positionIterations设置为5并运行一次步骤运行得更好(阻止我的身体彼此移动)。也许这与我的目标FPS是30有关。