Help us understand the problem. What is going on with this article?

Siv3D での 2D 物理演算をサポートする Physics (Box2D)

More than 3 years have passed since last update.

Siv3D AdventCalendar 2016 の 18 日目の記事です.

概要

Siv3D に付属されている HamFramework の機能の一つに,簡易的な 2D 物理シミュレーションを実装できる「Physics」があります.以下のソースコードで玉を転がす遊びができます.

Siv3DBox2D001.gif

Main.cpp
# include <Siv3D.hpp>
# include <HamFramework.hpp>

void Main()
{
    CameraBox2D camera(Vec2(0, 10), 17.0);

    PhysicsWorld world;

    auto ground = world.createLineString(Vec2(0, 0), { Vec2(-20, 10), Vec2(-20, 0), Vec2(20, 0), Vec2(20, 10) }, none, none, PhysicsBodyType::Static)
        .addLine({ Vec2(15, 20), Vec2(0, 15) })
        .addLine({ Vec2(-15, 10), Vec2(0, 5) });

    Array<PhysicsBody> bodies;

    while (System::Update())
    {
        world.update();
        camera.update();
        {
            const auto t1 = camera.createTransformer();

            if (Input::MouseL.clicked)
            {
                bodies.push_back(world.createCircle(Mouse::PosF(), 1.0));
            }

            Circle(Mouse::PosF(), 1.0).drawFrame(0.05);

            ground.draw();

            for (const auto& body : bodies)
            {
                body.draw();
            }
        }
        camera.draw();
    }
}

2D ゲーム と物理演算

物理演算を活用した 2D ゲームは多く存在します.例えば,Rovio Entertainment が開発した Angry Birds は,物理演算を用いて鳥の主人公を飛ばし,敵やオブジェクトを破壊するゲームです.また Umea 大学の学生 Emil Ernerfeldt の修士論文で開発された Phun (現 Algodoo) は,お絵かき感覚で物理演算を楽しむことができるゲーム(ツール)であり,インターネット上に多くの作品が公開されています.このような物理演算を活用したゲームを作るためには,自分で物理演算用の計算をするか,Box2D や Chipmunk2D 等の物理演算ライブラリを利用する必要がありますが,どちらもソースコードが長くなる傾向がありました.そこで,2D の物理演算を簡単に楽しめる Physics の基本的な使い方を紹介します.

Box2D と Siv3D

HamFramework の Physics は,Box2D を Siv3D から利用しやすいようにまとめた機能です.Box2D とは オープンソースで開発された C++ の 2D ゲーム用物理演算ライブラリで,円形や多角形の剛体の運動や衝突判定をシミュレーションすることが可能です.(先程紹介した Angry Birds もこの Box2D を用いています.)HamFramework の Physics では Siv3D が C++ で開発されていることや,Box2D のドキュメントが豊富であることから,2D 物理演算に Box2D を採用しました.

基本的な使い方

ワールドの生成と更新

Main.cpp
# include <Siv3D.hpp>
# include <HamFramework.hpp>

void Main()
{
    PhysicsWorld world;

    while (System::Update())
    {
        world.update();        
    }
}

  1. HamFramework.hpp をインクルード
  2. PhysicsWorld クラスのインスタンスを作成
  3. メインループの中で PhysicsWorld::update() を呼ぶ

これにより,物理演算を行うための環境が生成されました.この時点では画面に何も表示されません.今後は,この PhysicsWorld オブジェクトを利用して,運動や衝突判定を行う物体 PhysicsBody の生成を行いきます.

物体の生成と描画

Siv3DBox2D002.gif

Main.cpp
# include <Siv3D.hpp>
# include <HamFramework.hpp>

void Main()
{
    PhysicsWorld world;

    const auto ground = world.createLine(Vec2(0, 10), Line({ 0, 0 }, {640, 0 }), none, none, PhysicsBodyType::Static);
    const auto ball = world.createCircle(Vec2(320, 300), Circle(100));

    while (System::Update())
    {
        world.update();        

        ground.draw();
        ball.draw();
    }
}

  1. PhysicsWorld::create***()PhysicsBody オブジェクトを生成
  2. メインループの中で PhysicsBody::draw() を呼ぶ

PhysicsWorld::create***() の *** の部分にはRect,Circleなどの Siv3D で用いられる図形の名前が入ります.引数には,

  1. 中央の位置
  2. 図形
  3. 物理定数(指定がない場合は none)
  4. フィルタ(指定がない場合は none)
  5. 静止するか運動するを決める PhysicsBodyType

の順番で指定します.中央の位置はその PhysicsBody の配置を意味します.しかし,このままでは不自然な点いくつかあります.

  1. 重力の方向が上に向かっている
  2. 物体の動きが遅い

これは,Box2D の単位がメートル単位であることや,Y 軸の方向が,上方向を正にしている事が原因で発生した現象です.(つまり上の例では,半径 100 [m] の円が高さ 290 [m] から降っている事になります.)そこで以前紹介した ham::Camera2D 機能を活用し,上記の不自然な点を解決します.
http://qiita.com/hamukun8686/items/95471335b8a0fa1d877f

Camera2D の利用

Siv3DBox2D003.gif

Main.cpp
# include <Siv3D.hpp>
# include <HamFramework.hpp>

void Main()
{
    PhysicsWorld world;

    const auto ground = world.createLine(Vec2(0, -10), Line({ -20, 0 }, { 20, 0 }), none, none, PhysicsBodyType::Static);
    const auto ball = world.createCircle(Vec2(0, 10), Circle(1));

    CameraBox2D camera(Vec2(0, 0), 20);

    while (System::Update())
    {
        camera.update();
        {
            const auto t1 = camera.createTransformer();

            world.update();

            ground.draw();
            ball.draw();
        }
        camera.draw();
    }
}

  1. Camera2D の派生クラスである CameraBox2D オブジェクトの作成と利用

これにより,Y 軸の正の方向は上方向になりした.また,カメラ位置や拡大率を変更できるようになりました.

今後の機能について

HamFramework の Physics 機能は Box2D の機能全体をカバーするため,今後のアップデートで新しい機能を追加していきます.具体的には,衝突時の処理を記述する方法,物体同士を接続して動かすジョイント機能などです.

まとめ

今回は 2D の物理演算をサポートする Physics の基本的な使い方について解説しました.Physics を用いたゲームが公開されることを期待しています.

明日は @Nicious さんの記事です.よろしくお願いいたします.

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした