フラグをたくさん増やして管理しきれない?ビットフラグを使いこなす!

フラグというのはゲームにおいてかなり重要になってくる要素の一つだと思います。
例えばそのステージをクリアしているかどうか?とか装備をしている箇所とか…
これらを配列やds_mapで管理している人も多いかと思いますが、一つの方法としてビットによるフラグの管理方法をご紹介したいと思います。

ビットフラグってどんなもの?

player1_jump = false;
player1_walk = false;
player1_run = false;
player1_attack = false;

例えば上記のような状態管理のためのフラグがあるとします。
ビットフラグを使うと以下のようになります。

player1_state = 0000;

少しわかりづらいですが、要するに1つの変数で複数のフラグを持つ事ができます。

変数名jumpwalkrunattack
player1_state0001001001001000

各フラグに対し1のある位置がフラグが立っているという事です。
例えば、runなら0100のように3桁目の位置に1が入ります。

それぞれ何なのかを覚えているのは大変なので、enumを使用します。

enum states
{
    jump   = 1,		// 0001
    walk   = 2,		// 0010
    run    = 4,		// 0100
    attack = 8		// 1000
}

指定する場合は10進数の指定になるので、2進数から10進数に直します。
頭で2の累乗を意識するのが面倒な場合、以下のような定義でもいいかもしれませんね。

enum states
{
    jump   = 1<<0,	// 0001
    walk   = 1<<1,	// 0010
    run    = 1<<2,	// 0100
    attack = 1<<3	// 1000
}

定義方法

player_state = 0;

// walk
var _move_input = states.walk * (keyboard_check(vk_left) || keyboard_check(vk_right));
player_state = player_state | _move_input;

// run
var _run_input = states.run * (keyboard_check(vk_space));
player_state = player_state | _run_input;

show_debug_message(string(player_state));

上記の場合、player_stateの2進数の値は0110となります。
左右キーを押して、スペースキーを押した状態show_debug_message()などで出力すると10進数に変換されるため、6が出るはずです。
左右キーだけなら2、スペースキーだけなら4が表示されます。

参照方法

if(player_state & states.walk > 0)
{
    if(player_state & states.run > 0)
    {
	show_debug_message("is running!");
    }
    else
    {
	show_debug_message("is walking!");
    }
}

上記ではplayer_statestates.runstates.walkでビットマスクする事で、0以上かどうかを判断します。
ビットマスクの説明は公式で以下のようなサンプルで説明されています。

00&00 = 00
01&00 = 00
00&01 = 00
01&01 = 01
11&01 = 01
11&11 = 11
11&10 = 10

&の左側の値を右側の値でマスクする事を言います。
上記のサンプルを見るとわかりますが、右側の値の1の部分だけが取り出されています。

例えば以下ならどうなるか考えてみましょう。

1101101&1001010

上記の出力結果は以下になります。

1001000

メリット

  • 1つの変数と定数で簡単に状態やフラグを比較管理できる。
  • フラグが占有するメモリ量が圧倒的に小さくなる。
  • コードが短くなり視認しやすくなる

GMS2における変数が占有するメモリ量は32bitなので、これを1bitから無駄なく使う点では非常にスマートだと言えるでしょう。

まとめ

いかがでしょうか?

ビット演算はかなり扱いづらい印象があるのですが、使ってみるとシンプルで非常に便利な機能でした。
フラグ用の変数が膨大になって管理が苦しく、配列やデータ構造を使い始める人も多いかと思います。
しかしその中の手段の一つとして、ビットフラグを思い出してもらえればと思います。

Related Posts

いよいよ明後日19日からGM48が開始!48時間で完成させる戦略を練ってみた
GM48開催が明日に迫っています。 私自身初参加となりますし、本当に48時間で完成できるのか不安です。 そこで、完成させる戦略を練るために、様々...
セーブデータのセキュリティはどこまで必要か?
セーブデータのセキュリティはどこまで必要か? ゲーム開発者にとって頭を悩ませる要素の一つだと思います。 しかしこの悩みは目的を見直すことで解決す...
GMS2ファーストリファレンスを追加しました
GMS2ファーストリファレンスと銘打ってブログとは別コンテンツとしてサイトに追加しました。 どんな形にするかすごく迷っていたんですが、本のよう...
第32回!GMS2の世界的ゲームジャム『GM48』が開催!
来週19日から四半期に1度開催されるGameMakerのゲームジャム『GM48』が開催されます! スケジュールは以下の通り。 日時 内容 10月7日...
これだけは押さえておこう!GMLベストプラクティス!
GMS2では独自言語GML(GameMaker Language)を使用します。 エンジンの特性からプログラム経験が浅い方は「この書き方で合って...