読者です 読者をやめる 読者になる 読者になる

とあるプログラマの備忘録

都内某所に住むプログラマが自分用に備忘録を残すという趣旨のブログです。はてなダイアリーから移動しました!

Cocos2dx 3.x box2dを使用してカメラをフォローさせる

なんか横スクロールっぽい物を作成したいなと思って前々回位に
Cocos2dx 3.0 物理演算を試してみる - とあるプログラマの備忘録
という記事を書いたのですが、Cocos2dx 3.xで追加されたこの方法では

setPhysicsBodyしたNodeにカメラFollowが出来ない
※2014/5/25日現在

致命的じゃないか!詳細は
closed #4150: fix physics position and rotation bug. by boyu0 · Pull Request #5493 · cocos2d/cocos2d-x · GitHub
と解決策が出そうな出なさそうなというところです。早く直してほしい。。

しかし、Box2d使えば行けるらしいよ?
という情報をTさんから頂き早速やってみました。

まずは準備

【Cocos2d-xで学ぶBox2D超入門第0回】Box2Dを使う準備〜DebugDraw〜 | Cocoa部
Cocoa部さんの記事でBox2dを使用する為の準備を詳しく書いてくれていました、
DebugDrawを表示出来るところまで作成しましょう。

ボールと床の作成

HelloWorld::init()に以下の記述をします

    //画面サイズサイズを取得
    windowSize = Director::getInstance()->getWinSize();
    
    //メニューボタンを使う
    ball = Sprite::create("CloseSelected.png");
    ball->setPosition(Point(windowSize.width / 2, windowSize.height / 2));
    addChild(ball);
    
    //ボールの作成
    b2BodyDef player_body_def;
    player_body_def.type = b2_dynamicBody;
    player_body_def.position.Set(ball->getPositionX() / PTM_RATIO, ball->getPositionY() / PTM_RATIO);
    b2Body *body = _world->CreateBody(&player_body_def);
    
    b2CircleShape circle;
    circle.m_radius = 10.0 / PTM_RATIO;
    
    b2FixtureDef fixtureDef;
    fixtureDef.shape = &circle;
    fixtureDef.density = 2;
    fixtureDef.restitution = 0;
    fixtureDef.friction = 0.7;
    body->CreateFixture(&fixtureDef);
    
    //ballをセット
    body->SetUserData(ball);

    //フォローさせる
    this->runAction(Follow::create(ball));

    
    //床の作成
    b2BodyDef boxBodyDef;
    boxBodyDef.position.Set(windowSize.width / 2 / PTM_RATIO, 10 / PTM_RATIO);
    b2Body *boxBody = _world->CreateBody(&boxBodyDef);
    
    b2PolygonShape rect;
    rect.SetAsBox(200 / PTM_RATIO, 10 / PTM_RATIO);
    
    b2FixtureDef boxFixtureDef;
    boxFixtureDef.shape = ▭
    boxFixtureDef.density = 0.4;
    boxFixtureDef.friction = 0.5;
    boxFixtureDef.restitution = 1.0;
    boxBody->CreateFixture(&boxFixtureDef);

HelloWorld::updateに同期する処理を追記します

void HelloWorld::update(float delta)
{
    _world->Step(delta, 10, 10);
    
    
    //物理オブジェクトと位置を同期させる
    for (b2Body* b = _world->GetBodyList(); b; b = b->GetNext())
    {
        if (b->GetUserData() != NULL) {
            auto ball = (Sprite*)b->GetUserData();
            ball->setPosition( Point( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
            ball->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
        }
    }
}

エミュレートすると床部分とボールが出来ていて、 カメラがバウンドとともに上下するはずです。

次回はTileMapEditorの使い方をやります
Cocos2dx 3.0 TielMapEditor Tieldを使ってマップを作成する - とあるプログラマの備忘録