毎回同じ範囲内の数値で行ったり来たりを繰り返します。
スプライトのアニメーション・インデックスと同じような動作をします。実際にスプライトのアニメーションが 16 枚あるという想定で、0 〜 15 までの数値で循環し続ける処理をビット演算を使って実現します。
サンプルコード
if ステートメントを使うこともできますが、ビット演算を利用できる状況で活用すれば if 処理を省くことができます。
image_index = counter; var a = 15; counter = ++counter & a;
インスタンス変数 counter は 0
〜 15
の間で数字を返します。具体的には
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15;
となります。
「&」 は ビット演算(Bitwise)の AND 。これはビット積と呼ばれています。
GML における考え方/ビット積
GML では十進数を二進数化する標準のビルトイン関数はありません。しかし二進数は Power of 2 と組み合わせればかなり覚えやすくなるため一部丸暗記できます。
アニメーションの枚数が 16 というのは二進数を使った処理的には美味しい状況。まず Power of 2 (POW2)を考えて、
1,2,4,8,16,32,,
1 の二進数は「1」(一桁)、
2 の二進数は「10」(二桁)、
4 の二進数は「100」(三桁)、
8 の二進数は「1,000」(四桁)、
16 の二進数は「10,000」(五桁)、15 の二進数は「01,111」。
インスタンス変数 counter は 0
で初期化されましたが常に1
が加算されています。
(counter+1)
は ++counter と同じです。※ ++counter と counter++ は微妙に違う処理です。
counter と 15 (二進数化された値「01111」)とのビット積を考えます。
counter + 1 の結果が 1
の場合、1 の二進数は「00001」だから
00001 = 1 01111 = 15 ------------- 00001 = 1
ビット積の結果はこうなる。じゃあどんどん行きましょう。
00010 = 2 01111 = 15 ------------- 00010 = 2
00011 = 3 01111 = 15 ------------- 00011 = 3
途中省略、そして最後 ++counter の結果がいよいよ 16
となりました。
10000 = 16 01111 = 15 ------------- 00000 = 0
ビット積はビットを 0 でマスク(mask)する時に利用します。マスクとはビットを 0 もしくは 1 に変える処理のことで、ビット積の場合は
- 各桁のビット単位の比較が 1 で一致した場合 1 を返す
- ビットが 0 で一致した場合 0 を返す
- ビットが一致しない場合 0 を返す
するとその結果 16 & 15 == 0
となります。
ビット積を使わない場合
上記コードを if ステートメントで書き直すと以下のようになります。
image_index = counter; var a = 15; if (++counter > a) counter = 0;