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

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

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

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

6:30

はじめに

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

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

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

Colorゲームについて

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

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

C言語は1972年にデニス・リッチーがベル研究所で開発したプログラミング言語です。処理速度が速く、コンピュータを細かく制御できるため、現在でも幅広い分野で利用されています。現在のプログラミング言語の多くが設計においてC言語の影響を受けています。

RayLibについて

「RayLib」ライブラリは、プログラミング言語C/C++で2Dグラフフィックスを扱うゲームなどのコンソールアプリを開発できます。シンプルに関数をまとめてくれているので、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フォルダに、「.c」ファイルは「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.cファイル(色ブロックファイル)
 ┃┗main.cファイル(メインファイル)
 ┗Windows Resource Files(includeフォルダ)
  ┠application.rc
  ┗icon.ico

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

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

#include "resource_dir.h"

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

int main(void) {
	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)。タイトル画面をどこでもクリックしたら、「ゲームスタート」という音声とともにゲームを開始し、タイトル画像が消えます。画像の「Texture2D」構造体とサウンドの「Sound」構造体を、配列の要素数を限定して宣言します。

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

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

#include "resource_dir.h"

#define MAX_TEXTURES 6
#define MAX_SOUNDS 4

typedef enum { TITLE,MAIN_LOOP,GAME_OVER,STAGE_CLEAR } GameState;
GameState game_state = TITLE;
Texture2D img[MAX_TEXTURES];
Sound snd[MAX_SOUNDS];
Color bg = { 255,255,255,255 };

void init() {
}

void title(void) {
    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(void) {
    SetConfigFlags(FLAG_VSYNC_HINT | FLAG_WINDOW_HIGHDPI);
    InitWindow(1800, 900, "Color");
    SetTargetFPS(60);
    InitAudioDevice();
    SearchAndSetResourceDir("resources");
    img[0] = LoadTexture("0.png");
    img[1] = LoadTexture("1.png");
    img[2] = LoadTexture("2.png");
    img[3] = LoadTexture("Title.png");
    img[4] = LoadTexture("GameOver.png");
    img[5] = LoadTexture("StageClear.png");
    snd[0] = LoadSound("Mix.ogg");
    snd[1] = LoadSound("GameStart.ogg");
    snd[2] = LoadSound("GameOver.ogg");
    snd[3] = LoadSound("StageClear.ogg");
    while (!WindowShouldClose()) {
        BeginDrawing();
        ClearBackground(bg);
        switch (game_state) {
        case TITLE:
            title();
            break;
        }
        EndDrawing();
    }
    for (int i = 0; i < MAX_TEXTURES; i++)
        UnloadTexture(img[i]);
    for (int i = 0; i < MAX_SOUNDS; i++)
        UnloadSound(snd[i]);
    CloseAudioDevice();
    CloseWindow();
    return 0;
}

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

【コラム】器用貧乏は悪い意味

筆者はアイデア、プログラミング、絵、音楽、デザイン、文章、動画など何でもやってきました。ビジネスでは1つに特化するだけで良いので、器用貧乏が「色々手を出してはいるが何もモノになっていない」という悪い意味なのが分かる気がします…。

人気記事トップ10

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

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