【M5Stack FACES】テトリス操作で下ボタンでの落下速度アップを実現
今回は、M5Stack FACESの記事です。
前回まででテトリスのGAMEBOYカバーでの操作ができる様になりました。
今回は、↓ボタンでの落下速度アップを実現しようと思います。
今回の修正ポイント
落下速度アップを実現するための修正箇所イメージは以下の3点です。
・ ↓ボタンの押下フラグを追加する
・ ↓ボタンの押下判定処理を追加する(長押し中でも判定させる)
・ ↓ボタンが押下フラグが立っている時は落下スピードを加速する
前回のコード解析で、ボタンの押下処理の場所は何となく、分かっていますので、
今回のポイントは、落下処理を何処で行っているか?という所になります。
実装
それでは順番に実装していこうと思います。
押下フラグの追加
まずは↓ボタンの押下処理の追加です。
前回までのコード解析で、押下処理判定で but_*** と言うフラグを使っている事が何となく分かっています。
なので、今回は新たに↓ボタン用のフラグ but_DOWN を追加します。
前回まで作成したコードの21行目に変数の宣言場所がありますので、そこに追加すればOK。
boolean but_A = false, but_LEFT = false, but_RIGHT = false, but_DOWN = false;
赤字部分が今回の追加コード。
他の変数と同様に、falseで初期化しています。
ボタン押下判定の追加
続いて、↓ボタンの押下判定処理を追加です。
これは、前回までの対応で、keyPodLoop関数で処理している事が分かっています。
今回も同じ様にボタン押下の処理を行いますが、前回と異なるのはボタンが押されている間はずっと判定させる(フラグを立てる)部分です。
前回の修正で、ボタンが押された瞬間にしか反応しない処理を入れていたので、↓ボタン押下だけは押している間はずっと反応する様にします。
修正箇所は107行目のClearKeys関数と109行目のKeyPodLoop関数です。
void ClearKeys() { but_A=false; but_LEFT=false; but_RIGHT=false; but_DOWN=false;} //======================================================================== bool KeyPadLoop(){ if(M5.BtnA.wasPressed()){ClearKeys();but_LEFT =true;return true;} if(M5.BtnB.wasPressed()){ClearKeys();but_RIGHT=true;return true;} if(M5.BtnC.wasPressed()){ClearKeys();but_A =true;return true;} // GameBoyカバーボタンの対応 Wire.requestFrom(0X08, 1); // 0x08アドレスから1バイト読み出す要求 if(0 != Wire.available()) { // 読み出すデータがあれば処理をする uint8_t key_val = Wire.read(); // 1バイトデータを取得 if (old_key_val != key_val ) { // 1つ前で取得したキー情報と同じでなければ処理をする old_key_val = key_val; // 取得したキー情報を保持 // ↑:FE ↓:FD ←:FB →:F7 A:EF B:DF SELECT:BF START:7F if(0xFB == key_val){ClearKeys();but_LEFT =true;return true;} // ← 押下処理 if(0xF7 == key_val){ClearKeys();but_RIGHT=true;return true;} // → 押下処理 if(0xEF == key_val){ClearKeys();but_A =true;return true;} // A 押下処理 } if (0xFD == key_val) { // ↓ 押下処理 old_key_val = key_val; // 取得したキー情報を保持 ClearKeys();but_DOWN =true;return true; } } return false; }
今回の修正箇所が赤字部分です。
ボタンが押下し続けている間は反応させたかったので、if (old_key_val != key_val){} の処理の中では処理せず、
その外側で1つ前のボタン押下状態に関係なく、毎回、ボタンの判定をする様にしています。
ClearKeys関数の修正は、フラグの初期化をしている部分です。
ここも同時に追加修正しました。
落下処理の修正
最後に今回の最大のポイントとなる、落下速度を上げる部分となります。
この処理をしている場所を探すのは、少しコードを読み進める必要があるのですが…
結果から言うと、修正箇所は128行目のGetNextPosRot関数となります。
void GetNextPosRot(Point* pnext_pos, int* pnext_rot) {
bool received = KeyPadLoop();
if (but_A) started = true;
if (!started) return;
pnext_pos->X = pos.X;
pnext_pos->Y = pos.Y;
fall_cnt ++;
if (received && but_DOWN) { but_DOWN = false; fall_cnt ++;} // ↓ボタン押下時は落下速度アップ
if (fall_cnt >= 10) {fall_cnt = fall_cnt % 10; pnext_pos->Y += 1;}
// if ((fall_cnt = (fall_cnt + 1) % 10) == 0) pnext_pos->Y += 1; // 元のコード(自動落下)
else if (received) {
if (but_LEFT) { but_LEFT = false; pnext_pos->X -= 1;}
else if (but_RIGHT) { but_RIGHT = false; pnext_pos->X += 1;}
else if (but_A) { but_A = false;
*pnext_rot = (*pnext_rot + block.numRotate - 1)%block.numRotate;
}
}
}
例の如く、赤字部分が修正箇所です。
このコードの特定は、but_RIGHT などでコード内を検索し、ボタン押下による処理の場所を探しました。
but_LEFT や but_RIGHT が押された場合の処理を見るとわかりますが、pnext_pos->X の値を変化させる事で左右移動を実現させています。
そして、落下もpnext_pos->Y の値を変化させる事で実現しているのですが…
ここで、ポイントとなるのが、“10カウントしたら、1つブロックを下ろす(落下する)”ように作られている所です。
元のコードの下記の部分がそれにあたります。
if ((fall_cnt = (fall_cnt + 1) % 10) == 0) pnext_pos->Y += 1;
これは、ループの度に処理をしていたら、落下が早すぎてしまうから、スピード調整をしているんですね。
基本は、1ループで1カウントアップする(自動落下)ようになっているので、
↓ボタンが押されていたら2カウントアップする様に修正しています。
ココは元々が1行のif文で記述されているので、少し分かりにくいかもしれませんね。
もし、分かりにくい様なら、処理を1つずつ分解して考えてみましょう。
参考:今回の修正コード
今回の修正もGitHubに上げていますので、参考にしてみてください。
COMMIT : 下ボタンでの落下速度アップを実装
懸念点が…
これで一応落下速度をアップさせる処理ができたのですが…
少し遊んでいると、時々スピードが変わらない様な動きをする時があるんですよね。。。
ハッキリとした原因は未解析ですが、ボタン押下も同時押しは反応しない様になっていますし、
GAMEBOYカバーのボタン反応もイマイチ良くなかったりしますから…
その辺りが何か関係しているのかもしれません。
あまり深くまで探るつもりは無いのですが、少し気になる所ではあります。
おわりに
何はともあれ、一応の落下速度アップの実装はできたのではないでしょうか?
今回は、倍速での落下としましたが、カウントアップ幅を上げる事でさらにスピードアップさせる事ができます。
ぜひ、数値を変更して試してみてくださいね。
次回は…回転・移動ボタンの長押し処理の対応でしょうか?
予定は未定ですが、次回もお楽しみに☆
ディスカッション
コメント一覧
まだ、コメントがありません