コンテンツにスキップ

6. Siv3D 入門 ②

6.1 マウス入力を扱う

マウスカーソルがウィンドウ上のどこにあるかを知るには Cursor::Pos() を使います。マウスカーソルの座標を Point 型で返します。次のサンプルでは、マウスカーソルを中心に円を描画します。

#include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		// マウスカーソルの座標を中心とする半径 50 の円を描画する
		Circle{ Cursor::Pos(), 50 }.draw();
	}
}

マウスの左ボタンをクリックしたかは if (MouseL.down()) で判定できます。

#include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		// マウスの左ボタンがクリックされたら
		if (MouseL.down())
		{
			// 円を描く
			Circle{ Cursor::Pos(), 50 }.draw();
		}
	}
}

.down() はマウスのボタンを押した瞬間のフレーム(メインループ 1 周が 1 フレーム)しか true を返しません。以降はボタンを押し続けていても false になります。押し続けている間も true を返すのは .pressed() です。また、離した瞬間だけ true を返すのは .up() です。

メンバ関数 説明
.down() ボタンを押した瞬間のフレームだけ true を返します。
.pressed() ボタンが押されている間 true を返します。
.up() ボタンが離されたフレームだけ true を返します。
#include <Siv3D.hpp>

void Main()
{
	while (System::Update())
	{
		if (MouseL.down())
		{
			Print << U"左ボタンがクリックされた";
		}

		// マウスの左ボタンが押されている間
		if (MouseL.pressed())
		{
			// 円を描く
			Circle{ Cursor::Pos(), 50 }.draw();
		}

		if (MouseL.up())
		{
			Print << U"左ボタンが離された";
		}
	}
}

6.2 キーボード入力を扱う

キーボードの入力を扱う最も簡単な方法は、KeyAKeySpace など、キーを表すオブジェクトを使うことです。6.1 で説明したマウス入力と同様に、.down(), .pressed(), .up() などのメンバ関数を使って、キーが押されている状態を判定できます。各キーと対応するオブジェクトは、次の表のとおりです。

キー オブジェクト
A KeyA
B KeyB
1 Key1
2 Key2
KeyUp
KeyDown
KeyLeft
KeyRight
Space KeySpace
Enter KeyEnter

次のサンプルでは、キーボードの矢印キーに従って円が移動します。フレームレートによって移動速度が変わらないように、前フレームからの経過時間 Scene::DeltaTime() を使って移動量を調整しています。

#include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	// 円の初期位置
	Vec2 pos{ 400, 300 };

	while (System::Update())
	{
		// 前フレームからの経過時間(秒)* 200
		double move = (Scene::DeltaTime() * 200);

		if (KeyRight.pressed())
		{
			pos.x += move;
		}
		
		if (KeyLeft.pressed())
		{
			pos.x -= 5;
		}
		
		if (KeyUp.pressed())
		{
			pos.y -= 5;
		}
		
		if (KeyDown.pressed())
		{
			pos.y += 5;
		}

		Circle{ pos, 100 }.draw();
	}
}

6.3 テキストを表示する

Print を使えば最低限の文字列の表示ができますが、より自由なフォントやサイズ、色、位置で文字列を描画するには Font クラスを使います。Font クラスは、フォントファイルから読み込んだフォントを表現するクラスで、() 演算子と、.draw() を使って文字列を描画します。

フォントは実行ファイルからの相対パス、あるいは絶対パスを指定してフォントファイルから読み込むことができるほか、Siv3D に標準で同梱されている数種類のフォントから読み込んで作成することができます。

#include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	// 同梱フォントファイル(Regular)からフォントを作成する
	const Font font1{ FontMethod::MSDF, 40 }; // Typeface::Regular は省略可能

	// 同梱フォントファイル(Bold)からフォントを作成する
	const Font font2{ FontMethod::MSDF, 40, Typeface::Bold };

	while (System::Update())
	{
		font1(U"Hello, Siv3D!")
			.draw(50, Vec2{ 100, 100 }, ColorF{ 0.2 });

		font2(U"Hello, C++!")
			.draw(80, Vec2{ 100, 200 }, ColorF{ 0.0, 0.5, 1.0 });
	}
}
  • Font のコンストラクタで与えている 40 はフォントの基本サイズで、拡大縮小時の品質に影響します。実際の文字の大きさは .draw() の引数で指定している 5080 です。
  • 太字のフォントは Font 変数名{ FontMethod::MSDF, 48, Typeface::Bold }; で作成します。通常の太さのフォントは Typeface::Regular ですが、これは省略できます。
フォントの品質

FontMethod::MSDF 方式でフォントを作成するときの 40 は、フォントデータの詳細度を表しています。この値は実行時性能とのトレードオフです。詳細度を大きくすると、メモリ消費が増加して処理時間が増えます。小さくすると、複雑な字形の文字の描画品質が低下する場合があります。漢字の場合は 48 がバランスの取れた値です。英数字のみの場合は 32 でも十分です。

6.4 テキストの基準位置

中心の座標を指定してテキストを表示するには .drawAt(サイズ, x, y, color); または .drawAt(サイズ, pos, color); を使います。中心座標が (x, y), あるいは pos になるようにテキストが表示されます。

右端の中心の座標を指定してテキストを表示するには .draw(サイズ, Arg::rightCenter(x, y), color); を呼びます。右端の中心が (x, y) になるようにテキストが表示されます。

基準位置は全部で 9 種類用意されています。Arg::rightCenter = Vec2{ x, y }Arg::rightCenter(pos) のように、Vec2 で指定することもできます。

基準位置 説明
Arg::topLeft(x, y) 左上。.draw() と同じ。
Arg::topCenter(x, y) 上中央
Arg::topRight(x, y) 右上
Arg::leftCenter(x, y) 左中央
Arg::center(x, y) 中央。.drawAt() と同じ。
Arg::rightCenter(x, y) 右中央
Arg::bottomLeft(x, y) 左下
Arg::bottomCenter(x, y) 下中央
Arg::bottomRight(x, y) 右下

# include <Siv3D.hpp>

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

	const Font font{ FontMethod::MSDF, 48 };

	while (System::Update())
	{
        // (400, 100) が中心になるように描画する
		font(U"Hello").drawAt(50, Vec2{ 400, 100 }, ColorF{ 0.1 });

        // (780, 300) が右端の中心になるように描画する
		font(U"Siv3D").draw(50, Arg::rightCenter(780, 300), ColorF{ 0.1 });

        // (780, 400) が右端の中心になるように描画する
		font(U"Hello").draw(50, Arg::rightCenter(780, 400), ColorF{ 0.1 });

        // マウスカーソルの位置が下中央になるように描画する
		font(U"programming").draw(50, Arg::bottomCenter(Cursor::Pos()), ColorF{ 0.1 });
	}
}

6.5 あたり判定を行う

画面に円や長方形を描き、それらにマウスオーバーしているか、クリックしたかを判定するには、図形クラスが持つメンバ関数を使います。

  • .mouseOver(): マウスカーソルが図形の上にある場合に true を返します。
  • .leftClicked(): その図形を左クリックした瞬間のフレームに true を返します。
  • .leftPressed(): その図形を左クリックし続けている間 true を返します。
# include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	Circle circle{ 200, 200, 50 };

	Rect rect{ 400, 400, 200, 40 };

	while (System::Update())
	{
		ClearPrint();

		// 円の上にマウスカーソルがあれば
		if (circle.mouseOver())
		{
			Print << U"円の上にある";
		}

		// 長方形の上にマウスカーソルがあれば
		if (rect.mouseOver())
		{
			Print << U"長方形の上にある";
		}

		circle.draw();

		rect.draw();
	}
}

# include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	Circle circle{ 200, 200, 50 };

	Rect rect{ 400, 400, 200, 40 };

	while (System::Update())
	{
		// 円を左クリックしたら
		if (circle.leftClicked())
		{
			Print << U"円を左クリックした";
		}

		// 長方形を左クリックしたら
		if (rect.leftClicked())
		{
			Print << U"長方形を左クリックした";
		}

		circle.draw();

		rect.draw();
	}
}

6.6 配列

Siv3D では、Array クラスを使って配列を扱うことができます。Array は C++ 標準ライブラリの std::vector に似ていますが、より使いやすい機能を提供しています。配列は Array<要素の型> で作成します。

  • 配列 Array に要素を追加するには << を使います。
  • 配列 Array の要素をすべて削除するには .clear() を使います。
  • 配列 Array のメンバ関数 .size() は配列の要素数を size_t 型で返します。
  • 配列 Array のメンバ関数 .isEmpty() は配列が空(要素数が 0)かどうかを bool 型で返します。

左クリックした場所に円が追加されるプログラムは次のようになります。右クリックすると、すべての円が削除されます。

#include <Siv3D.hpp>

void Main()
{
	Scene::SetBackground(ColorF{ 0.6, 0.8, 0.7 });

	// 要素数 0 の配列を作成する
	Array<Circle> circles;

	while (System::Update())
	{
		// もし左クリックされたら
		if (MouseL.down())
		{
			// 円を追加する
			circles << Circle{ Cursor::Pos(), 20 };
		}

		// もし右クリックされたら
		if (MouseR.down())
		{
			// 配列の要素をすべて削除する
			circles.clear();
		}

		for (const auto& circle : circles)
		{
			circle.draw();
		}

		ClearPrint();
		Print << U"円の数: " << circles.size();
	}
}

6.7 画像を描画する

イラストや写真、ロゴやアイコンなど、画像を描画するには Texture クラスを使います。Texture クラスは画像ファイルを読み込み、描画可能な「テクスチャ」として保持します。

画像は実行ファイルからの相対パス、あるいは絶対パスを指定して画像ファイルから読み込むことができるほか、Siv3D に標準で同梱されている Unicode 絵文字やアイコンセットから読み込んで作成することもできます。絵文字は動物や食べ物、道具や乗り物など、約 3,000 種類以上の絵が用意されているので、ゲームのプロトタイプ作成に便利です。

テクスチャは .draw(左上の位置), または .drawAt(中心の位置) メンバ関数を使って描画します。

# include <Siv3D.hpp>

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

	// 画像ファイルからテクスチャを作成する
	const Texture t1{ U"example/windmill.png" };

	// 絵文字からテクスチャを作成する
	const Texture t2{ U"🍎"_emoji };

	const Texture t3{ U"🐈"_emoji };

	while (System::Update())
	{
		// (20, 20) を左上にして描画する
		t1.draw(20, 20);

		// (300, 500) を中心にして描画する
		t2.drawAt(300, 500);

		// カーソルの位置を中心にして描画する
		t3.drawAt(Cursor::Pos());
	}
}

6.8 画像を拡大縮小 / 回転して描画する

draw する前に .scaled(拡大縮小倍率), .rotated(回転角度) メンバ関数をつなげることで、描画時に拡大縮小や回転を伴うことができます。拡大縮小は 1.0 を基準として、2.0 で 2 倍、0.5 で 1/2 倍になります。回転角度は 360° を 2π とするラジアン単位で指定します。_deg サフィックスを使うことで度数法からラジアン法に簡単に変換できます。

# include <Siv3D.hpp>

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

	const Texture t1{ U"example/windmill.png" };
	const Texture t2{ U"🍎"_emoji };
	const Texture t3{ U"🐈"_emoji };

	while (System::Update())
	{
		// 50% の大きさで描画する
		t1.scaled(0.5).draw(20, 20);

		// 時計回りに 45° 回転して描画する
		t2.rotated(45_deg).drawAt(300, 400);

		// 2 倍の大きさで、反時計回りに 15° 回転して描画する
		t3.scaled(2.0).rotated(-15_deg)
			.drawAt(Cursor::Pos());
	}
}