Arduboyでボタンのリピートを取得する
Arduboyのボタン入力の取得は、pressed(), notPressed(), justPressed(), justReleased()があるが、ボタンのリピートも欲しくなる。
ドキュメントには次のようにする。と書かれているが少々使いづらそうだ。
if (arduboy.everyXframes(5)) { if (arduboy.pressed(A_BUTTON)) { fireShot(); } }
そこでボタンのリピートを簡単に取れるようにした。
#include <Arduboy2.h> Arduboy2 arduboy; void setup() { arduboy.begin(); arduboy.setFrameRate(60); arduboy.clear(); } void loop() { if (!arduboy.nextFrame()) return; ButtonUpdate(); arduboy.clear(); static int16_t x, y; if (ButtonRepeat(UP_BUTTON)) { if (--y < 0) y = 5 - 1; } else if (ButtonRepeat(DOWN_BUTTON)) { ++y %= 5; } if (ButtonRepeat(LEFT_BUTTON)) { if (--x < 0) x = 2 - 1; } else if (ButtonRepeat(RIGHT_BUTTON)) { ++x %= 2; } for (int16_t i = 0; i < 2; i++) { for (int16_t j = 0; j < 5; j++) { arduboy.setCursor(i * 56, j * 8); arduboy.print(i == x && j == y ? ">" : " "); arduboy.print("ITEM "); arduboy.print(i * 5 + j); arduboy.print("\n"); } } arduboy.display(); } // ボタン情報 static uint8_t btnOn; static uint8_t btnPress; static uint8_t btnRelease; static uint8_t btnRepeat; static uint8_t btnPrev; static uint16_t repeatStart = 30; static uint16_t repeatInterval = 10; static uint16_t repeatCounter[2][6]; static uint8_t buttons[] = { UP_BUTTON, DOWN_BUTTON, LEFT_BUTTON, RIGHT_BUTTON, A_BUTTON, B_BUTTON }; // ボタン情報の更新(毎フレーム呼び出す) void ButtonUpdate() { btnOn = arduboy.buttonsState(); // 現在のボタンの状態 btnPress = ~btnPrev & btnOn; // 今ボタンが押された btnRelease = btnPrev & ~btnOn; // 今ボタンが離された uint8_t hold = btnPrev & btnOn; // ボタンが押され続けている btnPrev = btnOn; // 前回のボタンの状態 btnRepeat = 0; for (int16_t i = 0; i < 6; i++) { if (hold & buttons[i]) { // ボタンが押され続けている if (repeatCounter[0][i] > 0) { // 1回目のリピートまで待つ repeatCounter[0][i]--; } else if (repeatCounter[1][i] == 0) { // 2回目以降のリピートを開始する btnRepeat |= buttons[i]; // リピートがかかった repeatCounter[1][i] = repeatInterval; // 次のリピートまでの待ち時間 } else { // 次のリピートまで待つ repeatCounter[1][i]--; } } else { // ボタンが押された。または押されていない btnRepeat |= (btnOn & buttons[i]); // 押されていたらbitを立てる repeatCounter[0][i] = repeatStart; // 1回目のリピート開始までの待ち時間 repeatCounter[1][i] = 0; // リセット } } } // ボタンが押されているか bool ButtonOn(uint8_t button) { return btnOn & button; } // ボタンが押されたか bool ButtonPress(uint8_t button) { return btnPress & button; } // ボタンが離されたか bool ButtonRelease(uint8_t button) { return btnRelease & button; } // ボタンがリピートしたか bool ButtonRepeat(uint8_t button) { return btnRepeat & button; } // リピート速度を設定する void ButtonSetRepeat(uint16_t start, uint16_t interval) { repeatStart = start; repeatInterval = interval; btnOn = btnPress = btnRelease = btnRepeat = btnPrev = 0; for (int16_t i = 0; i < 2; i++) { for (int16_t j = 0; j < 6; j++) { repeatCounter[i][j] = 0; } } }