【ゲームプログラミング】ビット演算による点滅処理
ゲームプログラミングキャラクターを点滅させたいとき、以下のような実装にするかもしれません。
// C++ class Player { int m_DrawCount; public: Player() : m_DrawCount( 0 ){} void Draw( void ) { // 2フレームに1回描画 if ( m_DrawCount % 2 == 0 ) { // 実際の描画処理 } ++m_DrawCount; } };
2で割ったあまりが0の場合のみ描画してます。2で割ったあまりは0か1になるので、2フレームに1回描画することになります。 この実装でも特に問題はないのですが、ビット演算(&)を使うと効率的かつバラエティに富んだ点滅をさせることができます。
// C++ class Player { int m_DrawCount; uint8_t m_BlinkMask; public: Player() : m_DrawCount( 0 ), m_BlinkMask( 1 ){} void Draw( void ) { // 一致するビットが1つでもある場合描画 if ( m_DrawCount & m_BlinkMask ) { // 実際の描画処理 } ++m_DrawCount; } };
m_BlinkMaskを1にすると2フレームに1回の描画になります。しかも割り算が発生しない分高速です。
- 0フレーム目 : 0 & 1 -> 0b0000 & 0b0001 -> 0b0000 -> 偽 -> 描画なし
- 1フレーム目 : 1 & 1 -> 0b0001 & 0b0001 -> 0b0001 -> 真 -> 描画あり
- 2フレーム目 : 2 & 1 -> 0b0010 & 0b0001 -> 0b0000 -> 偽 -> 描画なし
- 3フレーム目 : 3 & 1 -> 0b0011 & 0b0001 -> 0b0001 -> 真 -> 描画あり
- 4フレーム目 : 4 & 1 -> 0b0100 & 0b0001 -> 0b0000 -> 偽 -> 描画なし
- 5フレーム目 : 5 & 1 -> 0b0101 & 0b0001 -> 0b0001 -> 真 -> 描画あり
m_BlinkMaskを変えるとさまざまなパターンの点滅になっていきます。
例えば、m_BlinkMaskを2にすると以下のように2フレームごとに描画のon/offが切り替わります。
- 0フレーム目 : 0 & 2 -> 0b0000 & 0b0010 -> 0b0000 -> 偽 -> 描画なし
- 1フレーム目 : 1 & 2 -> 0b0001 & 0b0010 -> 0b0000 -> 偽 -> 描画なし
- 2フレーム目 : 2 & 2 -> 0b0010 & 0b0010 -> 0b0010 -> 真 -> 描画あり
- 3フレーム目 : 3 & 2 -> 0b0011 & 0b0010 -> 0b0010 -> 真 -> 描画あり
- 4フレーム目 : 4 & 2 -> 0b0100 & 0b0010 -> 0b0000 -> 偽 -> 描画なし
- 5フレーム目 : 5 & 2 -> 0b0101 & 0b0010 -> 0b0000 -> 偽 -> 描画なし
- 6フレーム目 : 6 & 2 -> 0b0110 & 0b0010 -> 0b0010 -> 真 -> 描画あり
- 7フレーム目 : 7 & 2 -> 0b0111 & 0b0010 -> 0b0010 -> 真 -> 描画あり
ちなみに、このように同じ割合でon/offを繰り返すのはm_BlinkMaskの値を2のn乗にしたときのみで、他の場合はonの割合が多くなります。
m_BlinkMaskの値を63まで試したGif動画を用意したので、参考にどうぞ。
on/offを逆にしたバージョン