Skip to content

演習 A - アイテム集めゲーム

空から落ちてくるアイテムを集めるゲームを作ります。

1. プレイヤーの移動

# include <Siv3D.hpp>

void Main()
{
	// プレイヤーの絵文字テクスチャ
	const Texture playerTexture{ U"😃"_emoji };

	// プレイヤーのスピード(ピクセル / 秒)
	const double playerSpeed = 500.0;

	// プレイヤーの座標
	Vec2 playerPos{ 400, 500 };

	while (System::Update())
	{
		////////////////////////////////
		//
		//	状態更新
		//
		////////////////////////////////

		// 前のフレームからの経過時間 (秒)
		const double deltaTime = Scene::DeltaTime();

		// プレイヤーの移動に関する処理
		{
			if (KeyLeft.pressed()) // [←] キーが押されていたら
			{
				playerPos.x -= (playerSpeed * deltaTime);
			}
			else if (KeyRight.pressed()) // [→] キーが押されていたら
			{
				playerPos.x += (playerSpeed * deltaTime);
			}

			// 壁の外に出ないようにする
			// Clamp(x, min, max) は, x を min~max の範囲に収めた値を返す
			playerPos.x = Clamp(playerPos.x, 0.0, 800.0);
		}

		////////////////////////////////
		//
		//	描画
		//
		////////////////////////////////

		// 背景はグラデーションの Rect
		Scene::Rect()
			.draw(Arg::top = ColorF{ 0.1, 0.4, 0.8 }, Arg::bottom = ColorF{ 0.3, 0.7, 1.0 });

		// プレイヤーのテクスチャの描画
		playerTexture.drawAt(playerPos);
	}
}

2. 落ちてくるアイテム

# include <Siv3D.hpp>

// アイテムの情報
struct Item
{
	// アイテムの現在位置
	Vec2 pos;

	// アイテムの種類を表す ID
	int32 type;
};

void Main()
{
	// プレイヤーの絵文字テクスチャ
	const Texture playerTexture{ U"😃"_emoji };

	// プレイヤーのスピード(ピクセル / 秒)
	const double playerSpeed = 500.0;

	// プレイヤーの座標
	Vec2 playerPos{ 400, 500 };

	// アイテムのテクスチャ
	const Texture itemTexture{ U"🍰"_emoji };

	// 現在画面上にあるアイテムの配列
	Array<Item> items;

	// アイテムが発生する時間間隔(秒)
	const double SpawnTime = 0.5;

	// 最後にアイテムが発生してからの経過時間(秒)
	double itemTimer = 0.0;

	// アイテムの落下スピード(ピクセル / 秒) 
	const double ItemSpeed = 200.0;

	while (System::Update())
	{
		// アイテムの個数の可視化
		ClearPrint();
		Print << U"ゲーム中のアイテムの個数: " << items.size();

		////////////////////////////////
		//
		//	状態更新
		//
		////////////////////////////////

		// 前のフレームからの経過時間 (秒)
		const double deltaTime = Scene::DeltaTime();

		// プレイヤーの移動に関する処理
		{
			if (KeyLeft.pressed()) // [←] キーが押されていたら
			{
				playerPos.x -= (playerSpeed * deltaTime);
			}
			else if (KeyRight.pressed()) // [→] キーが押されていたら
			{
				playerPos.x += (playerSpeed * deltaTime);
			}

			// 壁の外に出ないようにする
			// Clamp(x, min, max) は, x を min~max の範囲に収めた値を返す
			playerPos.x = Clamp(playerPos.x, 0.0, 800.0);
		}

		// アイテムの出現と移動と消滅に関する処理
		{
			itemTimer += deltaTime;

			// spawnTime が経過するごとに新しいアイテムを出現させる
			while (itemTimer >= SpawnTime)
			{
				Item item;
				item.pos.x = Random(100, 700); // アイテムの X 座標
				item.pos.y = -100; // アイテムの Y 座標
				item.type = 0; // アイテムの種類。 = Random(0, 3); とすれば 0~3 のランダムな数に

				// 配列に追加
				items << item;

				itemTimer -= SpawnTime;
			}

			// すべてのアイテムについて移動処理
			for (auto& item : items)
			{
				item.pos.y += deltaTime * ItemSpeed;
			}

			// 画面外に出たアイテムを消去する
			items.remove_if([](const Item& item) { return (item.pos.y > 700); });
		}

		////////////////////////////////
		//
		//	描画
		//
		////////////////////////////////

		// 背景はグラデーションの Rect
		Scene::Rect()
			.draw(Arg::top = ColorF{ 0.1, 0.4, 0.8 }, Arg::bottom = ColorF{ 0.3, 0.7, 1.0 });

		// プレイヤーのテクスチャの描画
		playerTexture.drawAt(playerPos);

		// アイテムの描画
		for (const auto& item : items)
		{
			itemTexture.drawAt(item.pos);
		}
	}
}

3. アイテムとの当たり判定

# include <Siv3D.hpp>

// アイテムの情報
struct Item
{
	// アイテムの現在位置
	Vec2 pos;

	// アイテムの種類を表す ID
	int32 type;
};

void Main()
{
	// プレイヤーの絵文字テクスチャ
	const Texture playerTexture{ U"😃"_emoji };

	// プレイヤーのスピード(ピクセル / 秒)
	const double playerSpeed = 500.0;

	// プレイヤーの座標
	Vec2 playerPos{ 400, 500 };

	// アイテムのテクスチャ
	const Texture itemTexture{ U"🍰"_emoji };

	// 現在画面上にあるアイテムの配列
	Array<Item> items;

	// アイテムが発生する時間間隔(秒)
	const double SpawnTime = 0.5;

	// 最後にアイテムが発生してからの経過時間(秒)
	double itemTimer = 0.0;

	// アイテムの落下スピード(ピクセル / 秒) 
	const double ItemSpeed = 200.0;

	// スコア
	int32 score = 0;

	while (System::Update())
	{
		// アイテムの個数の可視化
		ClearPrint();
		Print << U"ゲーム中のアイテムの個数: " << items.size();

		////////////////////////////////
		//
		//	状態更新
		//
		////////////////////////////////

		// 前のフレームからの経過時間 (秒)
		const double deltaTime = Scene::DeltaTime();

		// プレイヤーの移動に関する処理
		{
			if (KeyLeft.pressed()) // [←] キーが押されていたら
			{
				playerPos.x -= (playerSpeed * deltaTime);
			}
			else if (KeyRight.pressed()) // [→] キーが押されていたら
			{
				playerPos.x += (playerSpeed * deltaTime);
			}

			// 壁の外に出ないようにする
			// Clamp(x, min, max) は, x を min~max の範囲に収めた値を返す
			playerPos.x = Clamp(playerPos.x, 0.0, 800.0);
		}

		// アイテムの出現と移動と消滅に関する処理
		{
			itemTimer += deltaTime;

			// spawnTime が経過するごとに新しいアイテムを出現させる
			while (itemTimer >= SpawnTime)
			{
				Item item;
				item.pos.x = Random(100, 700); // アイテムの X 座標
				item.pos.y = -100; // アイテムの Y 座標
				item.type = 0; // アイテムの種類。 = Random(0, 3); とすれば 0~3 のランダムな数に

				// 配列に追加
				items << item;

				itemTimer -= SpawnTime;
			}

			// すべてのアイテムについて移動処理
			for (auto& item : items)
			{
				item.pos.y += deltaTime * ItemSpeed;
			}

			// プレイヤーのあたり判定の円
			const Circle playerCirlce{ playerPos, 60 };

			// アイテムのあたり判定と回収したアイテムの削除
			for (auto it = items.begin(); it != items.end();)
			{
				// アイテムのあたり判定の円
				const Circle itemCircle{ it->pos, 60 };

				// 交差したらアイテムを削除
				if (playerCirlce.intersects(itemCircle))
				{
					// (削除する前に) スコアを加算
					score += 100;

					// アイテムを削除
					it = items.erase(it);
				}
				else
				{
					// イテレータを次のアイテムに進める
					++it;
				}
			}

			// 画面外に出たアイテムを消去する
			items.remove_if([](const Item& item) { return (item.pos.y > 700); });
		}

		////////////////////////////////
		//
		//	描画
		//
		////////////////////////////////

		// 背景はグラデーションの Rect
		Scene::Rect()
			.draw(Arg::top = ColorF{ 0.1, 0.4, 0.8 }, Arg::bottom = ColorF{ 0.3, 0.7, 1.0 });

		// プレイヤーのテクスチャの描画
		playerTexture.drawAt(playerPos);

		// アイテムの描画
		for (const auto& item : items)
		{
			itemTexture.drawAt(item.pos);
		}

		// 当たり判定の可視化(デバッグ用)
		Circle{ playerPos, 60 }.drawFrame(2, Palette::Red); // プレイヤーの当たり判定円
		for (const auto& item : items)
		{
			// アイテムの当たり判定円
			Circle{ item.pos, 60 }.drawFrame(2, Palette::Red);
		}
	}
}