コンテンツにスキップ

3. Siv3D の基本

Siv3D プログラムの基本的な構成を学びます。

3.1 インクルードするヘッダ

  • ヘッダファイル <Siv3D.hpp> をインクルードするだけで、Siv3D のすべての機能を使えます
# include <Siv3D.hpp>
  • 通常の C++ プログラミングで使う標準ライブラリのヘッダは、基本的には不要です
  • <algorithm><vector> など、主要な標準ライブラリのヘッダファイルは、<Siv3D.hpp> の中でインクルードされます

3.2 プログラムの始まり方

  • 通常の C++ では int main() から始まりますが、Siv3D では代わりに void Main() 関数を書きます
# include <Siv3D.hpp>

void Main()
{
	// ここにプログラムを書く
}
  • Siv3D の内部プログラムが次のような構成になっているためです:
    • ① プログラムが始まる前に、Siv3D の内部プログラムが必要な初期化を全て実行する
    • ② 開発者が書いた Main() を実行する
    • Main() が終わったら、Siv3D の内部プログラムが自動的に後片付けを実行する
簡略化した Siv3D の内部プログラム
int main()
{
	Siv3D初期化(); // 必要な初期化処理を行う

	Main(); // 開発者が書いたプログラムを実行する

	Siv3D終了処理(); // 後片付けを行う
}
  • 開発者は面倒な準備や後片付けを気にせず、やりたいことだけを Main() 関数の中に書けば OK です
  • レストランの調理場で例えると次のようなイメージです:
    • スタッフがあらかじめ調理器具を用意してくれる(初期化)
    • シェフは調理だけに集中できる(Main 関数)
    • 終わったら、スタッフが後片付けをしてくれる(終了処理)

既存のプログラムの中で Siv3D を使うことはできない

  • Siv3D は内部に main() 関数を持っているため、main() 関数に書かれた既存のプログラム(過去に作ったゲームプログラムなど)の中で新しく Siv3D を使うことはできません

3.3 最小の Siv3D プログラム

  • 手元のエディタで Siv3D の最小のプログラムを書いて、ビルド・実行してみましょう
最小の Siv3D プログラム
# include <Siv3D.hpp>

void Main()
{

}
  • この Main 関数は何もすることがなく、実行すると一瞬で終了します
  • ウィンドウも表示されないため、何も起こっていないように見えるでしょう

3.4 メインループを書いてウィンドウを表示し続ける

  • プログラムをすぐに終了させないためには、メインループを書く必要があります
  • 次のコードのハイライト部分 while (System::Update()){ } がメインループです
  • while 文によって、ハイライト部分のプログラムが半永久的に繰り返されます
メインループを追加したプログラム
# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		// ここにプログラムを書く
	}
}
  • 繰り返しのたびに、System::Update() は、ウィンドウの表示やグラフィックス処理、マウスやキーボード入力の受け取りなどを行います
  • メインループが回っている間は、ウィンドウが表示され続けます

  • これで、グラフィックスの表示やユーザの入力の取得などを継続的に処理する準備が整いました

3.5 プログラムの終了方法

  • System::Update() は、普段は true を返すため、半永久的にメインループが続きます
  • 特定の操作をすると、System::Update()false を返すようになり、メインループを終了させます
  • メインループを抜けて、そのまま Main 関数の終端まで到達するとプログラムが終了します
メインループから抜けるとプログラムが終了する
# include <Siv3D.hpp>

void Main()
{
	// System::Update() が false を返すまでメインループを繰り返す
	while (System::Update())
	{

	}
}
  • System::Update()false を返す条件はいくつかあります
    1. ウィンドウの閉じるボタンを押す
    2. Esc キーを押す
    3. プログラムの中で System::Exit() を呼び出す
  • a, b の方法は、実際にウィンドウを閉じるか、Esc キーを押すことで確認できます
  • c の方法を試せるコードを下記に用意しました:
    • プログラムの開始から 5 秒経過したら System::Exit() を呼び出し、それ以降の System::Update()false を返すようになります
プログラムの開始から 5 秒経過したらプログラムを終了する
# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		// プログラムの開始から 5 秒経過したら
		if (5.0 <= Scene::Time())
		{
			// プログラムの終了を指示する
			System::Exit();
		}
	}
}
  • System::Exit() を呼んでも、そこで直ちにプログラムが終了するわけではありません
  • あくまで「次の System::Update()false を返すようにする」という指示を出すだけです

3.6 Main 関数からの return

  • 3.5 の方法とは別に、Main 関数から return してプログラムを終了させることもできます
  • とくに、その後の System::Update() を待たず、直ちにプログラムを終了させたい場合に有用です
  • 下のタブを切り替えて、System::Exit()return の違いを確認してみましょう
  • System::Exit() 呼び出し後、処理 A, 処理 B が実行されてから Main 関数が終了します
# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		// プログラムの開始から 5 秒経過したら
		if (5.0 <= Scene::Time())
		{
			System::Exit(); // 次の System::Update() が false を返すようにする
		}

		処理A();
	}

	処理B();
}
  • return; すると、処理 A, 処理 B は実行されず 直ちに Main 関数が終了します
# include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		// プログラムの開始から 5 秒経過したら
		if (5.0 <= Scene::Time())
		{
			return; // ここで直ちに Main() が終了する
		}

		処理A();
	}

	処理B();
}
  • どちらの方法を使うかどうかは、プログラムの構造や目的によります
  • Siv3D の公式サンプルで、明示的に終了処理を書く場合は、3.5 の方法を使っています
    • 「処理 B」の場所に、ゲームのセーブ処理や、オーディオのフェードアウトを記述できて都合が良いためです
  • 終了操作をカスタマイズする方法(Esc を押しても終了しないようにするなど)については、チュートリアル 5.6 で学びます

System::Exit() は必須ではない

  • System::Exit() は「後片付けを行う」関数ではないので、必ずしも使う必要はありません
  • Esc キーを押した場合や、ウィンドウの閉じるボタンを押した場合、return; で終了した場合、いずれもプログラムは正常に終了します

振り返りチェックリスト

  • <Siv3D.hpp> だけをインクルードすればよいことを学んだ
  • int main() ではなく void Main() を書くことを学んだ
  • メインループの書き方と、メインループによってウィンドウを表示し続ける方法を学んだ
  • System::Update() の戻り値が false になると、メインループから抜けてアプリケーションが終了することを学んだ
  • 具体的には、ウィンドウを閉じるか Esc を押すと System::Update()false を返すことを学んだ
  • System::Exit()System::Update() の戻り値を false に設定できることを学んた
  • System::Exit() は必須ではないことを学んだ