5

cocos2dでは、CCSpritesを簡単に操作して、さまざまな方法で移動できます。最も重要なこと-彼らはイージングイン/アウトを持つことができます。ほとんどのゲームでは、これはスムーズな動きなどに適しています。

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

box2dボディを移動すると、それに接続されているスプライトはbox2d step()の後に更新されます。スプライトを移動してからボディを更新することは、物理フレームワークの目的を完全に無効にするため、ここではオプションではありません。

したがって、私が正常に実装したもう1つのオプションは、スプライトをそれ自体が力学エンティティとして扱うことにより、スプライトの変位、速度、および加速度を計算することです。スプライトでupdate()を呼び出して、キャラクターが移動先などを決定できるようにするたびに、スーパークラスは前の位置と速度も保存します。これらは、PTM_RATIOで除算することにより、box2d準拠の値として保存されます。

FMSpriteと呼ばれるCCSpriteのサブクラス:

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

その結果、b2bodyの動きが素晴らしく、スムーズに動き、自分の力で遊ぶことなく、CCSpriteの動きをコピーして、その動きを複製することができます。すべての力であるため、他のb2Bodyオブジェクトと衝突するときにジッターや歪みが発生することはありません。他にこれを行う方法がある場合は、回答を投稿してください。ありがとう!

4

1 に答える 1

4

私がしていることはあなたのものとは異なりますが、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 に設定します。

私はあなたの質問を理解し、答えがあなたに役立つことを願っています...

于 2012-05-08T09:07:48.517 に答える