【cocos2d-x】物理エンジンの重力を変更したらモンストも作れるぞ!


背景

Cocos2dxはv3.xからChipmunk2Dに統一されて簡単に実装ができるようになりました。

重力を変更したかったのですが、少しはまってしまったので、メモをしておきます。

重力を0にすることで「モンスターストライク」のような動きをするアプリを簡単に作れてしまいます!

物理エンジンをONにして、重力を変更

まずは物理エンジンをONにします。
Sceneのcreate()createWithPhysics()に置き換えることでONになります。

次に重力を変更します。以下のようにすると重力が0になり宇宙空間のようになります。

PhysicsWorld* world = scene->getPhysicsWorld();
world->setGravity(Vec2(0, 0));
Vec2(0, -980)とすることで一般的な現実世界の重力になる。

GameScene.cpp
Scene* GameScene::createScene() {
    //auto scene = Scene::create();           //通常シーンの作成
    auto scene = Scene::createWithPhysics();  //物理エンジンのシーンの作成
    auto layer = GameScene::create();
    scene->addChild(layer);

    //gravityを変更(現実の場合0,-980)
    PhysicsWorld* world = scene->getPhysicsWorld();
    world->setGravity(Vec2(0, 0));

    return scene;
}

物体(PhysicsBody)を生成する

ここでは丸型と四角型の物体を生成するサンプルを示しておきます。
このサンプルはロードする画像と同じサイズの物体を生成します。
必要に応じて変更して使うとよいと思います。

丸型の物体を生成

GameScene.cpp
// 丸(物理エンジン)を作成
Sprite* GameScene::addNewCircleAtPosition(Node *parent, Point p, bool dynamic, const char *fileName) {
    Sprite* sprite = Sprite::create(fileName);
    auto material = PHYSICSBODY_MATERIAL_DEFAULT;
    material.density     = 1.0f; // 密度
    material.restitution = 0.7f; // 反発係数
    material.friction    = 0.0f; // 摩擦係数
    sprite->setPhysicsBody(PhysicsBody::createCircle((sprite->getContentSize().width/2 - 1), material));
    sprite->getPhysicsBody()->setDynamic(dynamic);
    sprite->setPosition(p);
    parent->addChild(sprite, 10);
    return sprite;
}

四角型の物体を生成

GameScene.cpp
// 四角(物理エンジン)を作成
Sprite* GameScene::addNewBoxAtPosition(Node *parent, Point p, bool dynamic, const char *fileName) {
    Sprite* sprite = Sprite::create(fileName);
    auto material = PHYSICSBODY_MATERIAL_DEFAULT;
    material.density     = 1.0f; // 密度
    material.restitution = 0.7f; // 反発係数
    material.friction    = 0.0f; // 摩擦係数
    sprite->setPhysicsBody(PhysicsBody::createBox(sprite->getContentSize(), material));
    sprite->getPhysicsBody()->setDynamic(dynamic);
    sprite->setPosition(p);
    parent->addChild(sprite, 10);
    return sprite;
}

こんな感じで使います。

GameScene.cpp
// 固定された物体(壁などに利用)
auto map = this->addNewBoxAtPosition(this, Point(0, 100), false, "map.png");
// 物理計算されてダイナミックに動く物体(プレイヤーなどに利用)
auto player = this->addNewBoxAtPosition(this, Point(100, 100), true, "player.png");

実際に動かす

実際に動かすと重力を無視した状態になり、跳ね返ってもまっすぐに移動するようになります。
パラメータを調整することで、疑似モンストのような動作が実現できます。
反発係数を1.0にすると、永遠に跳ね返るようにすることもできます。
係数をいろいろ変更して試して遊んでみてください。

あとがき

この仕組みを使って最近アプリを作りました。
よかったら見てやってください。
参考:【くまのがっこう】ジャッキーのほしあつめ

 

今回は「物理エンジンの重力を変更して遊ぶ」でした。

ではまた。