OpenSiv3D | 脱出ゲームを作る

公開:2021/02/23
更新:2021/02/23
8 min読了の目安(約7800字TECH技術記事

このコースでは、初歩的な C++ の文法と OpenSiv3D の機能を使って、シンプルな脱出ゲームを作ります。

1. 絵文字の表示


画面にアイテムを表示しましょう。

画面に画像を描きたいときは Texture を作成し、.draw() または .drawAt() します。.drawAt() では、テクスチャの中心をどこに据えるかをシーンの座標で指定します。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

void Main()
{
	const Texture computerTexture{ Emoji{ U"🖥️" } };
	const Texture boxTexture{ Emoji{ U"🗃️" } };
	const Texture doorTexture{ Emoji{ U"🚪" } };

	while (System::Update())
	{
		computerTexture.drawAt(200, 300);
		boxTexture.drawAt(400, 300);
		doorTexture.drawAt(600, 300);
	}
}

2. 背景の色


背景の色を変えましょう。

背景の色を変えるには Scene::SetBackground() 関数に色を渡します。色の表現には ColorF を使います。ColorF では、0.0 - 1.0 の範囲で RGB の各成分を指定します。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

void Main()
{
	Scene::SetBackground(ColorF{ 0.9, 0.85, 0.8 });

	const Texture computerTexture{ Emoji{ U"🖥️" } };
	const Texture boxTexture{ Emoji{ U"🗃️" } };
	const Texture doorTexture{ Emoji{ U"🚪" } };

	while (System::Update())
	{
		computerTexture.drawAt(200, 300);
		boxTexture.drawAt(400, 300);
		doorTexture.drawAt(600, 300);
	}
}

3. アイテムの領域


アイテムの領域を円 (Circle) で表現して表示しましょう。

ColorF の 4 番目の引数は不透明度を 0.0-1.0 で示します。0.0 は完全に透明で、0.5 は半分透過、1.0 は透過無しです。この値のことをアルファ値とも呼びます。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

void Main()
{
	Scene::SetBackground(ColorF{ 0.9, 0.85, 0.8 });

	const Texture computerTexture{ Emoji{ U"🖥️" } };
	const Texture boxTexture{ Emoji{ U"🗃️" } };
	const Texture doorTexture{ Emoji{ U"🚪" } };

	const Circle computerCircle{ 200, 300, 80 };
	const Circle boxCircle{ 400, 300, 80 };
	const Circle doorCircle{ 600, 300, 80 };

	while (System::Update())
	{
		computerTexture.drawAt(200, 300);
		computerCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		boxTexture.drawAt(400, 300);
		boxCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		doorTexture.drawAt(600, 300);
		doorCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });
	}
}

4. マウスカーソルの変更

マウスカーソルがアイテムの領域上にあるときにカーソルのスタイルを手のアイコンに変更するようにしましょう。

Circle の上にマウスカーソルが重なっているかを .mouseOver() で調べられます。マウスカーソルを手のアイコンにするには Cursor::RequestStyle() 関数に CursorStyle::Hand を渡します。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

void Main()
{
	Scene::SetBackground(ColorF{ 0.9, 0.85, 0.8 });

	const Texture computerTexture{ Emoji{ U"🖥️" } };
	const Texture boxTexture{ Emoji{ U"🗃️" } };
	const Texture doorTexture{ Emoji{ U"🚪" } };

	const Circle computerCircle{ 200, 300, 80 };
	const Circle boxCircle{ 400, 300, 80 };
	const Circle doorCircle{ 600, 300, 80 };

	while (System::Update())
	{
		computerTexture.drawAt(200, 300);
		computerCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		boxTexture.drawAt(400, 300);
		boxCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		doorTexture.drawAt(600, 300);
		doorCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		if (computerCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (boxCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (doorCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}
	}
}

5. メッセージの表示


アイテムをクリックしたときにメッセージを表示しましょう。

Circle が左クリックされたかを .leftClicked() で調べられます。Print にテキストを << で送ると、画面の左上にそのテキストが表示され続けます。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

void Main()
{
	Scene::SetBackground(ColorF{ 0.9, 0.85, 0.8 });

	const Texture computerTexture{ Emoji{ U"🖥️" } };
	const Texture boxTexture{ Emoji{ U"🗃️" } };
	const Texture doorTexture{ Emoji{ U"🚪" } };

	const Circle computerCircle{ 200, 300, 80 };
	const Circle boxCircle{ 400, 300, 80 };
	const Circle doorCircle{ 600, 300, 80 };

	while (System::Update())
	{
		computerTexture.drawAt(200, 300);
		computerCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		boxTexture.drawAt(400, 300);
		boxCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		doorTexture.drawAt(600, 300);
		doorCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		if (computerCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (boxCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (doorCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (computerCircle.leftClicked())
		{
			Print << U"パソコンだ。電源は入らない。";
		}

		if (boxCircle.leftClicked())
		{
			Print << U"箱の中に何か入っている。部屋の鍵を見つけた!";
		}

		if (doorCircle.leftClicked())
		{
			Print << U"ドアには鍵がかかっている。出られない。";
		}
	}
}

6. メッセージの消去


新しいアイテムをクリックしたときに、古いメッセージを消去しましょう。

Print したメッセージを消去するには、ClearPrint() を使います。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

void Main()
{
	Scene::SetBackground(ColorF{ 0.9, 0.85, 0.8 });

	const Texture computerTexture{ Emoji{ U"🖥️" } };
	const Texture boxTexture{ Emoji{ U"🗃️" } };
	const Texture doorTexture{ Emoji{ U"🚪" } };

	const Circle computerCircle{ 200, 300, 80 };
	const Circle boxCircle{ 400, 300, 80 };
	const Circle doorCircle{ 600, 300, 80 };

	while (System::Update())
	{
		computerTexture.drawAt(200, 300);
		computerCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		boxTexture.drawAt(400, 300);
		boxCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		doorTexture.drawAt(600, 300);
		doorCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		if (computerCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (boxCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (doorCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (computerCircle.leftClicked())
		{
			ClearPrint();
			Print << U"パソコンだ。電源は入らない。";
		}

		if (boxCircle.leftClicked())
		{
			ClearPrint();
			Print << U"箱の中に何か入っている。部屋の鍵を見つけた!";
		}

		if (doorCircle.leftClicked())
		{
			ClearPrint();
			Print << U"ドアには鍵がかかっている。出られない。";
		}
	}
}

7. フラグの管理


状態を表す変数を追加し、イベントを管理できるようにしましょう。

true または false を表現できる bool 型の変数を使って、イベントの ON/OFF を管理します。

# include <Siv3D.hpp> // OpenSiv3D v0.4.3

void Main()
{
	Scene::SetBackground(ColorF{ 0.9, 0.85, 0.8 });

	const Texture computerTexture{ Emoji{ U"🖥️" } };
	const Texture boxTexture{ Emoji{ U"🗃️" } };
	const Texture doorTexture{ Emoji{ U"🚪" } };

	const Circle computerCircle{ 200, 300, 80 };
	const Circle boxCircle{ 400, 300, 80 };
	const Circle doorCircle{ 600, 300, 80 };

	// 箱が開けられたか
	bool boxOpened = false;

	// プレイヤーが鍵を持っているか
	bool playerHasKey = false;

	while (System::Update())
	{
		computerTexture.drawAt(200, 300);
		computerCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		boxTexture.drawAt(400, 300);
		boxCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		doorTexture.drawAt(600, 300);
		doorCircle.draw(ColorF{ 1.0, 0.5, 0.0, 0.2 });

		if (computerCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (boxCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (doorCircle.mouseOver())
		{
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		if (computerCircle.leftClicked())
		{
			ClearPrint();
			Print << U"パソコンだ。電源は入らない。";
		}

		if (boxCircle.leftClicked())
		{
			ClearPrint();

			if (boxOpened)
			{
				Print << U"箱の中にはもう役に立ちそうなものは入っていない。";
			}
			else
			{
				Print << U"箱の中に何か入っている。部屋の鍵を見つけた。";
				boxOpened = true;
				playerHasKey = true;
			}
		}

		if (doorCircle.leftClicked())
		{
			ClearPrint();

			if (playerHasKey)
			{
				Print << U"持っている鍵を使ってドアを開くことができた!";
			}
			else
			{
				Print << U"ドアには鍵がかかっている。出られない。";
			}
		}
	}
}

8.

(準備中)