Skip to content

シーン管理

Reputeless edited this page Mar 17, 2017 · 4 revisions

基本

基本的なシーン管理
# include <Siv3D.hpp>
# include <HamFramework.hpp>

struct GameData
{
    int32 t;
};

// シーンのキーの型と、共有データの型を指定
using MyApp = SceneManager<String, GameData>;

struct Title : MyApp::Scene
{
    // クラスの初期化時に一度だけ呼ばれる(省略可)
    void init() override
    {

    }

    // 毎フレーム updateAndDraw() で呼ばれる
    void update() override
    {
        if (Input::MouseL.clicked)
        {
            // 次のシーケンスと、フェードイン・アウトの時間(ミリ秒)
            changeScene(L"Game", 2000);
        }

        // 共有データにアクセスできる
        m_data->t;
    }

    // 毎フレーム update() の次に呼ばれる
    void draw() const override
    {

    }
};

struct Game : MyApp::Scene
{
    void update() override
    {
        if (Input::MouseL.clicked)
            changeScene(L"Result", 2000);
    }

    void draw() const override
    {

    }
};

struct Result : MyApp::Scene
{
    void update() override
    {
        if (Input::MouseL.clicked)
            changeScene(L"Title", 2000);
    }

    void draw() const override
    {

    }
};

void Main()
{
    MyApp manager(SceneManagerOption::ShowSceneName);

    // SceneManagerOption::ShowSceneName を外せばシーン名のデバッグ表示は消える
    //MyApp manager;

    // フェードイン・アウト時の色
    manager.setFadeColor(Palette::White);

    // シーンを設定
    manager.add<Title>(L"Title");
    manager.add<Game>(L"Game");
    manager.add<Result>(L"Result");

    // 特に指定しなければ、一番最初に追加したシーンから開始
    // 別のシーンから始めたい場合は init()
    //manager.init(L"Game");

    while (System::Update())
    {
        if (!manager.updateAndDraw())
            break;
    }
}

応用

発展的なシーン管理
# include <Siv3D.hpp>
# include <HamFramework.hpp>

struct Spark : IEffect
{
    Array<std::pair<Vec2, Vec2>> m_particles;

    Spark(const Point& pos, const Point& size) : m_particles(50)
    {
        for (auto& particle : m_particles)
        {
            particle.second = Circular(Random(40.0), Random(TwoPi));
            particle.first = pos.movedBy(Random(-size.x / 2, size.x / 2), Random(-size.y / 2, size.y / 2));
        }
    }

    bool update(double t) override
    {
        for (const auto& particle : m_particles)
        {
            const Vec2 pos = particle.first + particle.second * t + 0.5* t*t * Vec2(0, 120);
            Triangle(pos, 8.0, particle.second.x).draw(HSV(pos.y - 40).toColorF(1.0 - t));
        }

        return t < 1.0;
    }
};

struct GameData
{
    int32 currentScore = 0;
    int32 highScore = 0;
};

using MyApp = SceneManager<String, GameData>;

struct Title : MyApp::Scene
{
    void update() override
    {
        if (Input::MouseL.clicked)
            changeScene(L"Game");
    }

    void draw() const override
    {
        FontAsset(L"Title")(L"BREAKOUT").drawCenter(100);
    }
};

struct Game : MyApp::Scene
{
    const Sound m_sound{ L"Example/Sound.mp3" };
    const Point m_blockSize{ 40, 20 };
    const double m_speed{ 8.0 };
    Rect m_wall{ 60, 10 };
    Circle m_ball{ 320, 400, 8 };
    Vec2 m_ballSpeed{ 0, -m_speed };
    Array<Rect> m_blocks;
    Effect m_effect;
    bool m_gameOver = false;

    void init() override
    {
        m_data->currentScore = 0;

        for (int y = 0; y < 5; ++y)
        {
            for (int x = 0; x < Window::Width() / m_blockSize.x; ++x)
            {
                m_blocks.emplace_back(x*m_blockSize.x, 60 + y*m_blockSize.y, m_blockSize);
            }
        }
    }

    void updateFadeIn(double) override
    {
        m_wall.setCenter(Mouse::Pos().x, 420);
    }

    void update() override
    {
        m_ball.moveBy(m_ballSpeed);
        m_wall.setCenter(Mouse::Pos().x, 420);

        for (auto it = m_blocks.begin(); it != m_blocks.end(); ++it)
        {
            if (it->intersects(m_ball))
            {
                (it->bottom.intersects(m_ball) || it->top.intersects(m_ball)
                    ? m_ballSpeed.y : m_ballSpeed.x) *= -1;

                ++m_data->currentScore;
                m_sound.playMulti();
                m_effect.add<Spark>(it->center, m_blockSize);
                m_blocks.erase(it);
                break;
            }
        }

        if (m_ball.y<0 && m_ballSpeed.y<0)
        {
            m_ballSpeed.y *= -1;
        }

        if ((m_ball.x < 0 && m_ballSpeed.x < 0) || (Window::Width() < m_ball.x && m_ballSpeed.x > 0))
        {
            m_ballSpeed.x *= -1;
        }

        if (m_ballSpeed.y>0 && m_wall.intersects(m_ball))
        {
            m_ballSpeed = Vec2((m_ball.x - m_wall.center.x) / 8, -m_ballSpeed.y).normalized()*m_speed;
        }

        if (m_blocks.empty() || m_ball.y > Window::Height())
        {
            for (auto const& block : m_blocks)
            {
                m_effect.add<Spark>(block.center, m_blockSize);
            }

            m_effect.setSpeed(0.3);
            changeScene(L"Result", 4000);
            m_gameOver = true;
        }
    }

    void draw() const override
    {
        if (!m_gameOver)
        {
            for (auto const& block : m_blocks)
            {
                block.stretched(-1).draw(HSV(block.y - 40));
            }
        }

        m_ball.draw();
        m_wall.draw();
        m_effect.update();
    }
};

struct Result : MyApp::Scene
{
    void init() override
    {
        m_data->highScore = Max(m_data->highScore, m_data->currentScore);
    }

    void update() override
    {
        if (Input::MouseL.clicked)
            changeScene(L"Title");
    }

    void draw() const override
    {
        FontAsset(L"Score")(L"Score: ", m_data->currentScore).draw(100, 100);
        FontAsset(L"Score")(L"High score: ", m_data->highScore).draw(100, 160);
    }
};

void Main()
{
    FontAsset::Register(L"Title", 60);
    FontAsset::Register(L"Score", 40);

    MyApp manager;
    manager.add<Title>(L"Title");
    manager.add<Game>(L"Game");
    manager.add<Result>(L"Result");

    while (System::Update())
    {
        if (!manager.updateAndDraw())
            break;
    }
}

Siv3D について

  1. Siv3D の基本
  2. 図形を描く
  3. テクスチャを描く
  4. テキストを描く
  5. 文字列と数値の変換
  6. キーボード入力
  7. マウス入力
  8. サウンドの再生
  9. MIDI の再生
  10. ウィンドウと背景
  11. 図形のあたり判定
  12. 乱数
  13. ダイアログ
  14. ドラッグ & ドロップ
  15. アプリの状態
  16. テキストファイル
  17. INI, CSV, JSON
  18. バイナリファイル
  19. GUI
  20. アセット管理
  21. 画像編集
  22. Web カメラ
  23. マイク入力
  24. 経過時間の測定
  25. HSV カラー
  26. ファイルダウンロード
  27. 3D 描画
  28. 2D のレンダーステート
  29. 3D のレンダーステート
  30. パーティクル
  31. スクリーンショット
  32. アプリケーションの公開
  33. さらに学ぶには

表現テクニック集

入出力デバイス

開発のヒント

Clone this wiki locally