ゲーム実装で身に付くプログラミング 8

「C/C++」の「RayLib」でコンソールゲーム「Color」を開発してみよう

第8回の今回は、プログラミング言語「C/C++」の「RayLib」ライブラリを使ってコンソールゲーム「Color」を作る解説をします。

大西 武 (オオニシ タケシ)

6:30

はじめに

この連載では、さまざまなプログラミング言語やライブラリで同じゲームを開発することで、容易にそのプログラミング言語に入門します。

第8回の今回はプログラミング言語「C/C++」を使って、次のURLのようなColorゲームを作ります。こちらからアセットをダウンロードしておいてください。

コンソールアプリはデスクトップアプリではありますが、昔で言うMS-DOSに当たるターミナルから起動するアプリです。

Colorゲームについて

Colorゲームの内容は第1回でも解説した通り、ゲームを開始したら、赤緑青の色ブロックをクリックします。すると背景色にその色が混ぜられるので、どんどんクリックして真っ白な背景にしていこうというゲームです。

プログラミング言語について

プログラミング言語「C/C++」はベル研究所が開発した、アプリやカーネルなど低レベルな(より深い層でという意味で)処理速度が要求される場面で使われる言語です。機械寄りのC言語にオブジェクト指向を加えたのがC++言語で、大規模開発で威力を発揮するのが特徴です。

RayLibについて

「RayLib」はプログラミング言語C/C++で2Dグラフフィックスを扱うゲームなどのコンソールアプリを開発できるライブラリです。シンプルに関数をまとめてくれているので、C/C++プログラミング入門用に非常に向いています。
はっきりとは分からないのですが、コメントアウトなどで全角文字を書くとバグがあるようです。画面が真っ黒になったらアンドゥしてバグを探してみてください。

開発のために必要となる環境の準備

今回必要となる、無料版の「Visual Studio 2026」(以下、VS2026)を準備します。次のURLからVisual StudioインストーラーをダウンロードしてVS2026の「C++によるデスクトップ開発」をインストールしてください。

また、Windows以外にもmacOSやLinuxでも開発できますが、それらの開発環境のセットアップ方法は次で説明する「raylib-quickstart」の「README.md」を参考にしてください。

プロジェクトを作成しよう

GitHubから「raylib-quickstart-main」をダウンロードし、解凍して「build-VisualStudio2026.bat」を実行するとプロジェクトが作成されます。

VS2026を起動し、「Open a project or solution」メニューでプロジェクトの中に生成された「raylib-quickstart-main.slnx」ファイルを開きます。

次の階層図のように、必ず「images」フォルダ内の画像は「resources」フォルダに、「sounds」フォルダ内のサウンドはresourcesフォルダに、「.cpp」ファイルは「src」フォルダに、「.h」ファイルは「include」フォルダに配置します。

なお、今回のライブラリはサウンドがシンプルに扱えるため、サウンドも使います。

・階層図

raylib-quickstart-mainフォルダ
┠raylibフォルダ(RayLibライブラリフォルダ)
┃┠Referencesフォルダ
┃┠External Dependenciesフォルダ
┃┠Header Files
┃┗Source Files
┗raylib-quickstart-mainフォルダ(メインフォルダ)
 ┠Referencesフォルダ
 ┠External Dependenciesフォルダ
 ┠Game Resouce Files(resourcesフォルダ)
 ┃┠0.pngファイル(赤の色ブロック画像)
 ┃┠1.pngファイル(緑の色ブロック画像)
 ┃┠2.pngファイル(青の色ブロック画像)
 ┃┠GameClear.oggファイル(ゲームクリアサウンド)
 ┃┠GameOver.oggファイル(ゲームオーバーサウンド)
 ┃┠GameOver.pngファイル(ゲームオーバー画像)
 ┃┠Mix.oggファイル(混色サウンド)
 ┃┠StageClear.oggファイル(ステージクリアサウンド)
 ┃┠StageClear.pngファイル(ステージクリア画像)
 ┃┗Title.pngファイル(タイトル画像)
 ┠Header Files(includeフォルダ)
 ┃┠ColorBlock.hファイル(色ブロックヘッダー)
 ┃┗resource_dir.hファイル(リソースパスヘッダー)
 ┠Source Files(srcフォルダ)
 ┃┠ColorBlock.cppファイル(色ブロックファイル)
 ┃┗main.cppファイル(メインファイル)
 ┗Windows Resource Files(includeフォルダ)
  ┠application.rc
  ┗icon.ico

「main.c」ファイルの拡張子を、CだけでなくC++も使えるように「main.cpp」に変更します。

次のサンプルコードをコーディングし、「Debug」→「Start Debugging」メニューを実行すると真っ白なウィンドウが表示されます(図1)。まだテンプレートからウィンドウサイズを大きくして画像と文字を消し、背景色を真っ白にしただけです。

・サンプルコード「main.cpp」ファイル

#include "resource_dir.h"

Color bg = { 255, 255, 255, 255 };

int main() {
	SetConfigFlags(FLAG_VSYNC_HINT | FLAG_WINDOW_HIGHDPI);
	InitWindow(1800, 900, "Color");
	SetTargetFPS(60);
	while (!WindowShouldClose()) {
		BeginDrawing();
		ClearBackground(bg);
		EndDrawing();
	}
	CloseWindow();
	return 0;
}

【サンプルコードの解説】
リソースヘッダーをインクルードすると、その中でraylibヘッダーもインクルードされます。
「main」関数がアプリ起動時に最初に呼ばれる関数です。
コンフィグをセットします。
ウィンドウを初期化します。
60FPS(1秒間に60コマ画面を更新)にセットします。
while文がメインループです。
描画を開始(「BeginDrawing」関数)します。
背景色を真っ白(「bg」変数)にします。
描画を終了(「EndDrawing」関数)します。
ウィンドウを閉じます。
main関数から戻り値で0を返します。

図1:真っ白なウィンドウを表示

タイトル画面を表示する

まずタイトル画像を表示します(図2)。タイトル画面をどこでもクリックしたら「ゲームスタート」という音声とともにゲームを開始し、タイトル画像が消えます。画像の「Texture」クラスとサウンドの「Sound」クラスはSTLの<vector>で管理することで、メモリの解放を明記しなくても自動で解放してくれます。

図2:タイトル画面を表示

・サンプルコード「main.cpp」ファイル

#include "resource_dir.h"
#include <vector>

enum GameState { TITLE, MAIN_LOOP, GAME_OVER, STAGE_CLEAR };
GameState game_state = TITLE;
std::vector<Texture> img;
std::vector<Sound> snd;
Color bg = { 255, 255, 255, 255 };

void init() {
}

void title() {
	Vector2 mouse = GetMousePosition();
	if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) {
		game_state = MAIN_LOOP;
		init();
		PlaySound(snd[1]);
	}
	DrawTexture(img[3], (1800 - img[3].width) / 2, (900 - img[3].height) / 2, WHITE);
}

int main() {
	SetConfigFlags(FLAG_VSYNC_HINT | FLAG_WINDOW_HIGHDPI);
	InitWindow(1800, 900, "Color");
	SetTargetFPS(60);
	InitAudioDevice();
	SearchAndSetResourceDir("resources");
	img.push_back(LoadTexture("0.png"));
	img.push_back(LoadTexture("1.png"));
	img.push_back(LoadTexture("2.png"));
	img.push_back(LoadTexture("Title.png"));
	img.push_back(LoadTexture("GameOver.png"));
	img.push_back(LoadTexture("StageClear.png"));
	snd.push_back(LoadSound("Mix.ogg"));
	snd.push_back(LoadSound("GameStart.ogg"));
	snd.push_back(LoadSound("GameOver.ogg"));
	snd.push_back(LoadSound("StageClear.ogg"));
	while (!WindowShouldClose()) {
		BeginDrawing();
		ClearBackground(bg);
		switch (game_state) {
			case TITLE: title(); break;
		}
		EndDrawing();
	}
	for (int i = 0; i < img.size(); i++) UnloadTexture(img[i]);
	CloseAudioDevice();
	CloseWindow();
	return 0;
}

【サンプルコードの解説】
<vector>をインクルードします。
ゲーム状態をTITLEにセットします。
Textureクラスのimg配列と、Soundクラスのsnd配列を宣言します。
「init」関数はステージ開始時に呼ばれます。
「title」関数でマウス座標を「mouse」変数に取得し、タイトル画像を描画し、マウス左ボタンが押されたらメインループに遷移します。
main関数でオーディオデバイスを初期化し、"resources"フォルダをリソースディレクトリに指定し、画像とサウンドをすべて読み込みます。whileのメインループでtitle関数を呼び出し、メインループを抜けたらテクスチャをアンロードしてオーディオデバイスを閉じます。

【コラム】ビブリオかるた

かるたの代わりに、本の各ページを使って競技かるたのようなことができたらいいですね。百人一首ではなく歴史人物の経歴でかるたをすれば、日本史・世界史の勉強にもなるのではないでしょうか?

人気記事トップ10

人気記事ランキングをもっと見る

企画広告も役立つ情報バッチリ! Sponsored