像 CCSprite 对象一样移动 Box2d 实体 [英] Moving Box2d Bodies Like CCSprite Objects

查看:19
本文介绍了像 CCSprite 对象一样移动 Box2d 实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 cocos2d 中,您可以在 CCSprites 中缓和并以各种方式移动它们.最重要的是 - 他们可以缓进/缓出.对于大多数游戏来说,这对于流畅的移动等是可取的.

In cocos2d, you can ease in CCSprites and move them around in all kinds of ways. Most importantly - they can have easing in/out. For most games this is desirable for smooth movement etc.

id action = [CCMoveTo actionWithDuration:dur position:pos];
move = [CCEaseInOut actionWithAction:action rate:2];
[self runAction: move];

移动 box2d 主体时,附加到它的 sprite 在 box2d step() 之后更新.移动精灵然后更新身体在这里不是一种选择,因为它完全违背了物理框架的目的.

When moving a box2d body, the sprite attached to it is updated after the box2d step(). Moving the sprite and then updating the body is not an option here, as it entirely defeats the purpose of the physics framework.

所以我已经成功实现的另一个选项是通过将精灵本身视为一个力学实体来计算精灵的位移、速度和加速度.每次我在精灵上调用我的 update() 以便角色可以决定移动到哪里等时,我的超类也会存储之前的位置和速度.这些通过除以 PTM_RATIO 存储为符合 box2d 的值.

So the other option, which I have successfully implemented, is to calculate the displacement, velocity and acceleration of a sprite by treating it as a mechanics entity in its own right. Each time I call my update() on the sprite so the character can decide where to move etc, my superclass also stores the previous position and velocity. These are stored as box2d compliant values by dividing by the PTM_RATIO.

在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 等.

I have then subclassed "FMSprite" into "FMObject", which stores a b2Body etc.

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

In order to move the body, I must first move a sprite and track its acceleration, through which I can find the required force (using the mass) needed to follow the sprite's motion. Since I can't move the object's sprite (which is synchronized to the body), I make another sprite called a "beacon", add it as a child to the object, and move it around. All we need to do then is to have a function to synchronize the position of the box2d body with this beacon sprite using the forces I mentioned before.

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

结果非常棒,b2body 的平滑缓动运动可以随心所欲地移动,无需使用任何自身的力,而是复制 CCSprite 的力并复制其运动.由于都是力,所以在与其他 b2Body 对象碰撞时不会引起抖动和失真.如果有人有任何其他方法可以做到这一点,请发布答案.谢谢!

The result is brilliant, a smooth easing motion of the b2body moving where ever you want it to, without playing around with any of its own forces, but rather copying that of a CCSprite and replicating its motion. Since it's all forces, it won't cause jittering and distortions when colliding with other b2Body objects. If anyone has any other methods to do this, please post an answer. Thanks!

推荐答案

我做的和你的不一样,但也可以像 CCSprite Objects 一样移动 Box2d Bodies 甚至使用 CCAction.最重要的是创建一个包含 ccSprite 和 b2body 的对象.

What I do is different from yours, but can also Moving Box2d Bodies Like CCSprite Objects and even use the CCAction. The most important thing is to create an object that contain ccSprite and b2body.

@interface RigidBody : CCNode {
    b2Body *m_Body;
    CCSprite *m_Sprite;
}

然后,重写 setPosition 方法.

And then, rewrite the setPosition method.

-(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.

The setPosition method calculate how much the position change,and set it to the b2body.

希望我能理解您的问题,并且回答对您有帮助...

I hope I have understanding your question and the answer is helpful for you...

这篇关于像 CCSprite 对象一样移动 Box2d 实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆