コンテンツにスキップ

7. Siv3D 入門 ③

7.1 絵文字を動かす

メインループのたびに位置をずらすことで移動のモーションをつくれます。

Scene::DeltaTime() は前フレームからの経過時間(秒)を返します。画面の更新頻度が毎秒 60 フレーム(60 FPS)の場合、1 フレームあたりの時間は約 0.016 秒です。

次のコードでは、毎秒 100 ピクセルの速さで絵文字が右に移動します。

#include <Siv3D.hpp>

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

	const Texture emoji{ U"☃️"_emoji };

	// 絵文字の X 座標
	double x = 100.0;

	while (System::Update())
	{
		const double deltaTime = Scene::DeltaTime();

		x += (deltaTime * 100.0);

		emoji.drawAt(x, 300);
	}
}

7.2 絵文字を往復させる

次のようにコードを書き換えると、絵文字が左右に往復するようになります。

#include <Siv3D.hpp>

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

	const Texture emoji{ U"☃️"_emoji };

	// 絵文字の X 座標
	double x = 100.0;

	// 右に進むフラグ
	bool toRight = true;

	while (System::Update())
	{
		const double deltaTime = Scene::DeltaTime();
		
		if (toRight)
		{
			x += (deltaTime * 100.0);

			if (750 < x)
			{
				toRight = false;
			}
		}
		else
		{
			x -= (deltaTime * 100.0);

			if (x < 50)
			{
				toRight = true;
			}	
		}

		emoji.drawAt(x, 300);
	}
}

7.3 絵文字を回す

メインループのたびに回転の角度を増やすことで回転のモーションをつくれます。次のコードでは、毎秒 180° 回転する寿司を描画します。

#include <Siv3D.hpp>

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

	const Texture emoji{ U"🍣"_emoji };

	// 回転角度
	double angle = 0_deg;

	while (System::Update())
	{
		const double deltaTime = Scene::DeltaTime();
		
		// 回転角度を増やす
		angle += (deltaTime * 180_deg);

		// 回転ずし
		emoji.rotated(angle).drawAt(400, 300);

	}
}

7.4 図形を動かす

7.1 と同じ要領で図形の位置をずらすことで、図形の移動モーションをつくれます。

#include <Siv3D.hpp>

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

	double x = 100.0;

	while (System::Update())
	{
		const double deltaTime = Scene::DeltaTime();

		x += (deltaTime * 100.0);

		Circle{ x, 200, 80 }.draw();

		// double 型を使う場合, Rect ではなく RectF
		RectF{ x, 400, 100, 80 }.draw();
	}
}

7.5 図形クラスのメンバ変数

Circle は次のようなクラスであり、Circle 型の変数を作ることができます。

struct Circle
{
	double x;
	double y;
	double r;
};

Rect は次のようなクラスであり、Rect 型の変数を作ることができます。

struct Rect
{
	int32 x;
	int32 y;
	int32 w;
	int32 h;
};

RectF は次のようなクラスであり、RectF 型の変数を作ることができます。

struct RectF
{
	double x;
	double y;
	double w;
	double h;
};

#include <Siv3D.hpp>

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

	// Circle 型の変数
	Circle circle{ 400, 300, 100 };

	// RectF 型の変数
	RectF rect{ 400, 300, 300, 200 };

	while (System::Update())
	{
		circle.draw(Palette::White);

		rect.draw(Palette::Seagreen);
	}
}

7.6 図形クラスのメンバ変数の操作

  • 図形クラスのメンバ変数の値を変更するサンプル

#include <Siv3D.hpp>

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

	// Circle 型の変数
	Circle circle{ 400, 300, 100 };

	// RectF 型の変数
	RectF rect{ 400, 300, 300, 200 };

	while (System::Update())
	{
		circle.draw(Palette::White);

		circle.r += 0.5;

		rect.draw(Palette::Seagreen);

		rect.x -= 0.5;
	}
}

7.7 文字列の中に変数の値をいれる

U"{}"_fmt(x) と書くと、{} には値 x を文字列にしたものが入ります。

例えば U"{} 月 {} 日"_fmt(12, 31)U"12 月 31 日" という文字列になります。

# include <Siv3D.hpp>

void Main()
{
	int32 score = 1234;

	Print << U"スコア: {}"_fmt(score);

	int32 month = 12;

	int32 day = 31;

	Print << U"今日は {} 月 {} 日"_fmt(month, day);

	while (System::Update())
	{

	}
}

7.8 小数点以下の桁数を指定して変換する

double 型の値 x を、小数点以下の桁数を指定して変換する場合、U"{:.2f}"_fmt(x) のように書きます(この場合小数点以下 2 桁)。

小数点以下を表示しない場合は U"{:.0f}"_fmt(x) とします。

# include <Siv3D.hpp>

void Main()
{
	double x = 123.4567;

	Print << x;

	Print << U"{}"_fmt(x);

	Print << U"{:.2f}"_fmt(x);

	Print << U"{:.0f}"_fmt(x);

	while (System::Update())
	{

	}
}

7.9 マウスカーソルを手の形にする

Cursor::RequestStyle(CursorStyle::Hand); を呼ぶと、そのフレームはマウスカーソルが手の形のアイコンで表示されます。

# include <Siv3D.hpp>

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

	const Circle circle{ 200, 200, 50 };

	while (System::Update())
	{
		// 円の上にマウスカーソルがあれば
		if (circle.mouseOver())
		{
			// マウスカーソルを手のアイコンにする
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		circle.draw(Palette::Orange);
	}
}

7.10 絵文字をクリックしたかを調べる

絵文字(テクスチャ)には .leftClicked().mouseOver() が無いため、代わりに近い大きさの円を使って判定します。

# include <Siv3D.hpp>

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

	const Texture emoji{ U"🍪"_emoji };

	const Circle circle{ 200, 200, 60 };

	while (System::Update())
	{
		// 円の上にマウスカーソルがあれば
		if (circle.mouseOver())
		{
			// マウスカーソルを手のアイコンにする
			Cursor::RequestStyle(CursorStyle::Hand);
		}

		// 円を左クリックしたら
		if (circle.leftClicked())
		{
			Print << U"クッキーをクリック";
		}

		// 円は描かない
		//circle.draw();

		// circle.center は Vec2{ circle.x, circle.y } と同じ
		emoji.drawAt(circle.center, Palette::Orange);
	}
}

7.11 乱数を生成する

Random(a, b) は a 以上 b 以下の数を返します。ただし a < b とします。

  • 例: Random(0, 100), Random(0.8, 1.2)
  • さいころの目を出す場合は Random(1, 6)

#include <Siv3D.hpp>

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

	while (System::Update())
	{
		// 左クリックされたら
		if (MouseL.down())
		{
			// 0 以上 2 以下のランダムな整数を作る
			int32 n = Random(0, 2);

			if (n == 0)
			{
				Print << U"大吉";
			}
			else if (n == 1)
			{
				Print << U"小吉";
			}
			else
			{
				Print << U"凶";
			}
		}		
	}
}

7.12 ランダムな場所に移動する

画面を左クリックするたびに絵文字がランダムな場所に移動するサンプルです。

#include <Siv3D.hpp>

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

	const Texture emoji{ U"☃️"_emoji };

	double x = 400.0;

	double y = 300.0;

	while (System::Update())
	{
		// 左クリックされたら
		if (MouseL.down())
		{
			// ランダムな X 座標を代入
			x = Random(50, 750);

			// ランダムな Y 座標を代入
			y = Random(50, 550);
		}

		emoji.drawAt(x, y);
	}
}

7.13 簡単なアプリやゲームを作る

7.13.1 カウンター

絵文字をクリックするとカウントが増えるアプリです。

#include <Siv3D.hpp>

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

	const Texture emoji{ U"🛎️"_emoji };

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

	// 押した回数
	int32 count = 0;

	while (System::Update())
	{
		if (Circle{ 500, 300, 70 }.leftClicked())
		{
			++count;
		}

		font(U"{} 回"_fmt(count)).draw(50, Vec2{ 200, 300 }, Palette::Black);

		Circle{ 500, 300, 70 }.draw(ColorF{ 1.0, 1.0, 1.0, 0.5 });

		emoji.drawAt(500, 300);
	}
}

7.13.2 クッキークリッカー

クッキーをたくさんクリックするゲームです。

#include <Siv3D.hpp>

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

	const Texture emoji{ U"🍪"_emoji };

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

	int32 score = 0;

	// クッキーの X 座標
	double cookieX = 400;

	// クッキーの Y 座標
	double cookieY = 300;

	while (System::Update())
	{
		if (Circle{ cookieX, cookieY, 70 }.leftClicked())
		{
			score += 100;
			cookieX = Random(50, 750);
			cookieY = Random(50, 550);
		}

		emoji.drawAt(cookieX, cookieY);

		font(U"スコア: {}"_fmt(score)).draw(50, Vec2{ 50, 50 }, Palette::Black);
	}
}