Cocos2d iphone 移动Box2d实体,如CCSprite对象

Cocos2d iphone 移动Box2d实体,如CCSprite对象,cocos2d-iphone,box2d,box2d-iphone,ccsprite,easing,Cocos2d Iphone,Box2d,Box2d Iphone,Ccsprite,Easing,在cocos2d中,您可以轻松地使用ccsprite并以各种方式移动它们。最重要的是,他们可以轻松进出。对于大多数游戏来说,这对于流畅的运动等都是可取的 id action = [CCMoveTo actionWithDuration:dur position:pos]; move = [CCEaseInOut actionWithAction:action rate:2]; [self runAction: move]; 移动box2d实体时,附加到它的精灵将在box2d步骤()之后更新。移

在cocos2d中,您可以轻松地使用ccsprite并以各种方式移动它们。最重要的是,他们可以轻松进出。对于大多数游戏来说,这对于流畅的运动等都是可取的

id action = [CCMoveTo actionWithDuration:dur position:pos];
move = [CCEaseInOut actionWithAction:action rate:2];
[self runAction: move];
移动box2d实体时,附加到它的精灵将在box2d步骤()之后更新。移动精灵然后更新身体在这里不是一个选项,因为它完全违背了物理框架的目的

我已经成功实现的另一个选择是,通过将精灵本身视为力学实体来计算其位移、速度和加速度。每次我在精灵上调用我的update(),以便角色可以决定移动的位置等,我的超类也会存储以前的位置和速度。通过除以PTM_比率,将其存储为符合box2d的值

在CCSprite的子类中,称为FMSprite:

-(CGPoint) displacement {
    return ccpSub(self.position, lastPos);
}

-(b2Vec2) getSpriteVelocity:(ccTime)dt {
    return b2Vec2(self.displacement.x / dt / PTM_RATIO,
                  self.displacement.y / dt / PTM_RATIO);
}

-(b2Vec2) getSpriteAccel:(ccTime)dt {
    b2Vec2 currVel = [self getSpriteVelocity:dt];
    if (dt == 0) {
        return b2Vec2(0,0);
    } else {    
        float accelX = (currVel.x - lastVel.x)/dt;
        float accelY = (currVel.y - lastVel.y)/dt;
        return b2Vec2(accelX, accelY);
    }
}

// This is called each update()
-(void) updateLast:(ccTime)dt {
    // MUST store lastVel before lastPos is updated since it uses displacement
    lastVel = [self getSpriteVelocity:dt];
    lastPos = ccp(self.X, self.Y);
}

// Leave this method untouched in subclasses
-(void) update:(ccTime)dt {
    [self updateObject:dt];

    // Store previous update values
    [self updateLast:dt];
}

// Override this method in subclasses for custom functionality
-(void) updateObject:(ccTime)dt {

}
然后,我将“FMSprite”子类化为“FMObject”,它存储b2Body等

为了移动身体,我必须首先移动精灵并跟踪其加速度,通过它我可以找到跟随精灵运动所需的力(使用质量)。由于我无法移动对象的精灵(与身体同步),我制作了另一个名为“灯塔”的精灵,将其作为子对象添加到对象中,然后四处移动。我们需要做的就是使用我前面提到的力,使box2d身体的位置与这个灯塔精灵同步

-(void) followBeaconWithDelta:(ccTime)dt {
    float forceX = [beacon getSpriteAccel:dt].x * self.mass;
    float forceY = [beacon getSpriteAccel:dt].y * self.mass;
    [self addForce:b2Vec2(forceX, forceY)];
}

结果是非常棒的,身体可以在任何你想让它移动的地方平稳地移动,而不需要玩弄它自己的任何力量,而是复制一个CCSprite并复制它的运动。因为它是所有的力,所以在与其他物体碰撞时不会引起抖动和扭曲。如果任何人有任何其他方法来做这件事,请张贴一个答案。谢谢

我所做的与您的不同,但也可以移动Box2d实体,例如CCSprite对象,甚至可以使用CCAction。 最重要的是创建一个包含ccSprite和b2body的对象

@interface RigidBody : CCNode {
    b2Body *m_Body;
    CCSprite *m_Sprite;
}
然后,重写setPosition方法

-(void)setPosition:(CGPoint)position
{
    CGPoint currentPosition = position_;
    b2Transform transform = self.body->GetTransform();
    b2Vec2 p = transform.p;
    float32 angle = self.body->GetAngle();
    p += [CCMethod toMeter:ccpSub(position, currentPosition)];
    self.body->SetTransform(p, angle);  
    position_ = position;
}
setPosition方法计算位置的变化量,并将其设置为b2body


我希望我理解了你的问题,答案对你有帮助…

这对定位有效,但SetTransform每次都会设置身体位置,而不是使用力。这意味着当两个刚体对象碰撞时,它们将产生抖动效果,而不是平滑地相互反弹。addForce方法需要更多的工作,但可以确保物理过程是平稳的。是的,但是使用力很难使物体保持稳定的速度和确定的位置。我在使用我的方法时从来没有犯过任何错误,但我不知道两个物体是否都是b2_dynamicBody。嗨,感谢这篇文章。但我还不明白一件事。你为什么需要一个灯塔精灵?如果正在使用某些自定义操作移动FMObject类型的对象(它是一个CCSprite),为什么不让FMObject中的b2Body跟随父sprite呢。我不确定“同步化到身体”是什么意思。为什么你需要一个灯塔精灵并移动它呢?我发布这篇文章已经快三年了,但我想你可能是对的。我看不出有灯塔精灵的理由。我认为这只是一个实现细节。您应该能够替换
FMObject
本身。