オレンジブログ

オレンジブログ

自作ゲームについてとか色々

GameMakerStudio2でImGuiを使用する方法

はじめに

最近GameMaker Studio2(以下GMS2)のライセンスが更新されて、無料でWindowsビルドとかが出来るようになりました。
これ以降GMS2ユーザーも増えるのかなぁとワクワクしています。
そこで、ImGuiと言うGMS2で使用できる便利なライブラリを紹介しようと思います。
どういったライブラリかと言うと

  • ゲーム内にGUIウィンドウを表示させて、そこに描画することが出来る
  • 描画できる内容は文字列だけでなく、クリックしたら動作するボタンや、スライダーやプルダウンまで存在
  • 1行でテキストの表示ができ、シンプルなコード記述で実装可能
  • さらにデフォルトでマウス操作が可能なので、入力周りを実装する必要は無い
サンプルのメニュー

と、至れり尽くせりなライブラリとなっております。
その他にも機能は多く存在しますが、ボリュームが大きくなるのでそれは別途解説致します。

上記の機能は主にデバッグ機能として使用できるので、どんなゲームを作っていても参考になると思います。

※注意
htmlビルドでは使用できないため注意。

ImGuiって?

デバッグ機能等を作ることを目的としたC++向けのGUIライブラリです。
見た目や機能がシンプルで、簡単なコードを記述するだけでUIが作れるのでデバッグ機能やツールを作るのに非常に向いているものですね。
詳しくはこちら。
https://github.com/ocornut/imgui

サンプルコードを読めば分かりますが、1行でテキスト表示やボタンの実装など行えて使いやすいです。
非常に使いやすく、企業や実際のゲーム開発現場でも使われているほどメジャーで実績もあります。

GameMakerへの導入

さて、上で説明したImGuiですが、元々はC++ライブラリなのでそのままGameMakerに導入することは出来ません。
そこで、既に拡張機能としてGameMaker内でImGuiのコードを使えるようにしてくれたものがあるのでそちらを使います。(非常に重宝してます。作者さんありがとうございます!)

アセットのダウンロード

制作者様のサイトにアクセスして最新版をダウンロードします。
nommiiin.itch.io

サイト内下の方の「Download Now」のボタンをクリックします。

出典:imgui_gm

そしたらダウンロード画面が出てきて、よかったらサポートしていただけますか?というポップアップが出てきます。
一旦お試しでダウンロードするので「No thanks, just take me to the downloads」をクリックします。

出典:imgui_gm

気に入ったらサポーターになって製作者様を支援しましょう!

次のページに飛んだら、ダウンロードするバージョンを選択します。
一番上のバージョンの「Download」ボタンを押しましょう。(2023/12/10現在 v1_0_15)

出典:imgui_gm

「imgui_gm_v1_0_〇〇.yymps」のような名前のファイルがダウンロードされればOKです。

インポート

ダウンロードしたらGameMakerを起動して導入したいプロジェクトを開きます。

上記でダウンロードしたyympsファイルをプロジェクトにドラッグアンドドロップでインポートします。

下記のようなポップアップが出てくるので「はい」をクリックします。

アセットのインポート

そしたら追加するファイル一覧が表示されるので「[すべて追加]」を選択してインポートするリソースに全フォルダを入れてから左下の「インポート」をクリックします

アセットのインポート

「Example」「ImGui_GM」フォルダがプロジェクトに追加されていれば成功です。

アセットのインポート

使い方

セットアップ

ImGuiをGameMaker内で使用するためには、専用のオブジェクトを作成する必要があります。
1つImGui用のオブジェクトを作成してください。
自分はわかりやすく「obj_imguigml_manager」と名前を付けました。名前はなんでも大丈夫です。

そしたらCreateイベント(作成)を作り、中に下記を記述します。

/// @description imguigmlを使用するための管理オブジェクト
// このエディターでコードを作成することができます

// ImGuiを初期化
ImGui.__Initialize();

次にBegin_Stepイベント(ステップ前)を作り、中に下記を記述します。

/// @description ImGui.__Update()を回す
// このエディターでコードを作成することができます
// 更新処理
ImGui.__Update();

最後にDraw_GUIイベント(GUI 描画)を作り、中に下記を記述します。

/// @description ImGui.__Render()で描画
// このエディターでコードを作成することができます
// 描画処理を回す
ImGui.__Render();

これでImGuiを使用する準備が出来ました。このオブジェクトを描画したいRoomに配置します。
Roomを超えて使用したい場合はpersistant(持続的)にチェックを付けてください。

ウィンドウの描画

では次に、ImGuiのウィンドウを描画していきます。
先ほど作ったオブジェクトのCreateイベントに下記のコードを追加します。

// メニューを開いているかを管理するフラグ
is_menu_open = true;

そしたら新たにStepイベント(ステップ)を作り、中に下記を記述します。

/// @description デバッグ用にメニューを作る
// このエディターでコードを作成することができます

if(is_menu_open){
    // windowサイズを指定。とりあえず画面の半分で
    ImGui.SetNextWindowSize(room_width / 2, room_height / 2, ImGuiCond.Once);
    
    var is_begin = ImGui.Begin("ImGui_GM Example", is_menu_open, ImGuiWindowFlags.None, ImGuiReturnMask.Both);
    // 引数に送ったis_menu_openの参照の値を取得
    is_menu_open = is_begin & ImGuiReturnMask.Pointer;
    // is_beginの戻り値がtrueなら
    if(is_begin & ImGuiReturnMask.Return){
	// ここにウィンドウ内の機能を記述する
    }
	// ImGui描画終了
    ImGui.End();
}

ここまで記述した状態で、試しにゲームを実行してみましょう。
こんな感じでウィンドウが表示されていれば成功です。

ビルド後

右下にカーソルを合わせて左クリックしてマウスを動かすと、ウィンドウサイズを変えることができます。

サイズ変更

他にも、ウィンドウの上の青い部分をダブルクリックすることで半透明化させて一時的に無効にしたり(もう一回ダブルクリックで元に戻る)

一時無効化。もう一回ダブルクリックで元に戻る

ウィンドウの右上の×を押すことでウィンドウを閉じれます。

ウィンドウ内に機能を追加

ここからは先ほど作ったウィンドウに機能を追加していきます。
流石にこの記事で全ての機能は紹介できませんので、よく使う機能をピックアップして紹介します。
もし他にも気になる方がいましたら、Example内に入っている「objExample」を確認してください。

テキストの表示

まずはウィンドウ内にテキストを表示してみましょう。
ウィンドウ内にテキストを表示する際には、ImGui.Textと記述し、引数に表示したい文字列を渡します。

ImGui.Text(文字列);

試しに先ほど作ったウィンドウにテキストを表示してみましょう。
Stepイベントを下記のように修正します。

/// @description デバッグ用にメニューを作る
// このエディターでコードを作成することができます

if(is_menu_open){
    // windowサイズを指定。とりあえず画面の半分で
    ImGui.SetNextWindowSize(room_width / 2, room_height / 2, ImGuiCond.Once);
    
    var is_begin = ImGui.Begin("ImGui_GM Example", is_menu_open, ImGuiWindowFlags.None, ImGuiReturnMask.Both);
    // 引数に送ったis_menu_openの参照の値を取得
    is_menu_open = is_begin & ImGuiReturnMask.Pointer;
    // is_beginの戻り値がtrueなら
    if(is_begin & ImGuiReturnMask.Return){
        // Test用のテキストを表示
        ImGui.Text("Test");
    }
	// ImGui描画終了
    ImGui.End();
}
テキスト描画

こんな感じで指定したテキストが表示されれば成功です。めちゃくちゃ簡単ですよね!

動的にテキスト内容を変更することができるので、デバッグ表示機能として非常に優れています。
例えば、下記のようなコードを記述すればマウスの座標を表示することができます。

// マウスの座標を表示
ImGui.Text("mouse_pos " + string(mouse_x) + ", " + string(mouse_y));
マウス座標の表示

実際にマウスを動かして値が変わるのを確認してみましょう。

ボタンの追加

次はボタン機能を追加します。
クリックしたら何かを実行する機能なので、何かしらをデバッグメニューから実行したい時に使えます。
こちらも非常に汎用性が高いので、是非使い方を覚えましょう。

ボタンは下記のコードで追加することができます。

// ボタンの描画
ImGui.Button(ボタン名);

ImGui.Buttonの戻り値が、クリックされた時のみtrueが返ってくるので、下記のようにif文を使用することで
クリックされたときに動作するコードを記述できます。

if (ImGui.Button("Clicked Log!!")) {
    // クリックした実行した内容を記述
}

Stepイベントを下記のように修正し、ボタンを押したらログを表示するようにしてみます。

if(is_menu_open){
    // windowサイズを指定。とりあえず画面の半分で
    ImGui.SetNextWindowSize(room_width / 2, room_height / 2, ImGuiCond.Once);
    
    var is_begin = ImGui.Begin("ImGui_GM Example", is_menu_open, ImGuiWindowFlags.None, ImGuiReturnMask.Both);
    // 引数に送ったis_menu_openの参照の値を取得
    is_menu_open = is_begin & ImGuiReturnMask.Pointer;
    // is_beginの戻り値がtrueなら
    if(is_begin & ImGuiReturnMask.Return){
	// Test用のテキストを表示
        ImGui.Text("Test");
	// マウスの座標を表示
	ImGui.Text("mouse_pos " + string(mouse_x) + ", " + string(mouse_y));
	// ボタンを作り、ボタンをクリックしたらログを出す。
        if (ImGui.Button("Clicked Log!!")) {
		show_debug_message("Clicked!!!!!");	
	}
    }
    // ImGui描画終了
    ImGui.End();
}
ボタン追加

このようなボタンが表示されており、これをクリックしたら

ログ表示

このようにログが出力されたら成功です。

数値入力欄の表示

次に数字入力欄を作ります。デバッグ用に数値を変更したい際などに利用できます。
数値入力欄はImGui.InputInt関数を使用します。

// 数字入力欄の描画
ImGui.InputInt(入力欄名, 現在の値);

ImGui.InputInt関数の戻り値で変更後の値が返ってきます。
また、第二引数に現在の値を代入するため、変数を作って管理することをおススメします。

Createイベントに数字入力欄のための変数を宣言します。

// ImGuiを初期化
ImGui.__Initialize();
is_menu_open = true;
// 数字入力欄用の変数
input_int = 0;

StepイベントにImGui.InputIntを使用した処理を追加します。

if(is_menu_open){
    // windowサイズを指定。とりあえず画面の半分で
    ImGui.SetNextWindowSize(room_width / 2, room_height / 2, ImGuiCond.Once);
    
    var is_begin = ImGui.Begin("ImGui_GM Example", is_menu_open, ImGuiWindowFlags.None, ImGuiReturnMask.Both);
    // 引数に送ったis_menu_openの参照の値を取得
    is_menu_open = is_begin & ImGuiReturnMask.Pointer;
    // is_beginの戻り値がtrueなら
    if(is_begin & ImGuiReturnMask.Return){
		// Test用のテキストを表示
        ImGui.Text("Test");
		// マウスの座標を表示
		ImGui.Text("mouse_pos " + string(mouse_x) + ", " + string(mouse_y));
		// ボタンを作り、ボタンをクリックしたらログを出す。
        if (ImGui.Button("Clicked Log!!")) {
			show_debug_message("Clicked!!!!!");	
		}
		// 数値入力ウィンドウを作り、入力結果をinput_int変数に代入
		input_int = ImGui.InputInt("Input Int!!", input_int);
    }
	// ImGui描画終了
    ImGui.End();
}

input_intで代入された値を使ってみましょう。
DrawGUIイベントを下記のように修正します。

// 描画処理を回す
ImGui.__Render();
// input_intの値をmouse_x.mouse_yに描画
draw_text(mouse_x,mouse_y,string(input_int));
InputIntの描画

InputIntの枠の中をクリックするとテキスト入力ができるので、数値を入れましょう。
その数値が現在のマウスの位置に描画されればOKです!

まとめ

この記事ではGameMaker内でImGuiを使う方法を記述しました。
ゲームを作成する上でデバッグ機能は必須と言っていいほどなのですが、
そのデバッグ機能の実装が大変だったりして本末転倒になってしまうケースがあります。

そんな問題をImGuiは解決してくれるので、個人的には必須級のライブラリだと思っています。
(もちろん別のライブラリでデバッグ機能を作るのもOKです。デバッグ機能を簡単に作れるライブラリが開発に必須だなぁという意見です)

この記事で解説した機能はほんの一部のみで、ImGuiにはもっと便利な機能がいっぱいあります。
ドキュメントもサンプルも充実しているので、自分で調べて自分だけのデバッグ機能を作っていくと良いでしょう。

次回はImGuiをGameMakerで使う際に便利なメニューについてまとめたいと思います。(予定)
それでは、良いGameMakerライフを!