押したキーを表示する - イベントハンドラ版
押したキーを読み取り、画面に表示します。
- 2022-06-12
- 公開
コード
main.c
- #include <genesis.h>
- #define DEFAULT_POSITION_X 12;
- #define DEFAULT_POSITION_Y 13;
- // テキスト表示位置
- static u16 posX = DEFAULT_POSITION_X; // 表示文字のX座標
- static u16 posY = DEFAULT_POSITION_Y; // 表示文字のY座標
- /**
- * 渡された1文字を状態に対応するパレットで画面に表示する
- * @param c 表示する文字
- * @param state 状態
- */
- static void drawChar(char c, u16 state) {
- // 表示するボタンの頭文字の設定(0は終端文字)
- char chr[2];
- chr[0] = c;
- chr[1] = 0;
- // テキストのパレットを、ボタンの押下があれば0、なければ1に設定
- VDP_setTextPalette(state ? PAL0 : PAL1);
- // 対応するボタンの頭文字を表示
- VDP_drawText(chr, posX, posY);
- // 表示の横位置をずらす
- posX += 2;
- }
- /**
- * 1Pコントローラの変化したボタンに対応した画面上の文字の色を変更する
- * @param state ボタン
- */
- static void drawButtonChar(u16 state) {
- drawChar('U', state & BUTTON_UP);
- drawChar('D', state & BUTTON_DOWN);
- drawChar('L', state & BUTTON_LEFT);
- drawChar('R', state & BUTTON_RIGHT);
- drawChar('A', state & BUTTON_A);
- drawChar('B', state & BUTTON_B);
- drawChar('C', state & BUTTON_C);
- drawChar('X', state & BUTTON_X);
- drawChar('Y', state & BUTTON_Y);
- drawChar('Z', state & BUTTON_Z);
- drawChar('S', state & BUTTON_START);
- }
- /**
- * コントローラの状態
- */
- typedef struct {
- u16 current; // 押下しているキー
- u16 trigger; // 押し始めたキー
- u16 off; // 離したキー
- } JoyState;
- /**
- * コントローラの状態を保持するグローバル変数
- */
- JoyState joyState;
- /**
- * 1Pコントローラの押されたボタンに対応した画面上の頭文字の色を変更する
- * NOTE: コントローラの状態に変化があると実行される関数
- * 1PコントローラのAボタンが押された: joy = JOY_1, changed = BUTTON_A, state = BUTTON_A
- * 2PコントローラのBボタンが離された: joy = JOY_2, changed = BUTTON_B, state = 0
- * @param joy 変更のあったコントローラ
- * @param changed 変更のあったボタン
- * @param state 押されているボタン
- */
- static void joyEvent(u16 joy, u16 changed, u16 state) {
- if (joy != JOY_1) {
- return;
- }
- // 押し始めたボタン
- joyState.trigger = state & changed;
- // 離したボタン
- joyState.off = changed & ~state;
- // 押しているボタン
- joyState.current = state;
- }
- int main(u16 hard) {
- // ボタンを押していない時のテキスト色をパレット1に設定する
- // NOTE: SGDKではテキスト色はパレット0~3の15番を使用する
- // 1パレットは16個単位だが、色を表す値は区切りなく連続して存在している
- // つまり16+15はパレット1の15番目の色ということ
- PAL_setColor(16+15, 0x0666);
- // 初期テキスト
- VDP_drawText("1P Pad:", posX-6, posY-1);
- VDP_drawText("trig:", posX-6, posY);
- VDP_drawText("off :", posX-6, posY+1);
- VDP_drawText("curt:", posX-6, posY+2);
- // パレットを1に設定(文字色変更)
- VDP_setTextPalette(PAL1);
- // 初期テキスト2
- VDP_drawText("U D L R A B C X Y Z S", posX, posY);
- VDP_drawText("U D L R A B C X Y Z S", posX, posY+1);
- VDP_drawText("U D L R A B C X Y Z S", posX, posY+2);
- // コントローラ状態を初期化(0埋め)
- memset(&joyState, 0, sizeof(JoyState));
- // コントローラの状態を監視し、変化を検出すると指定されたイベントを発生させる
- JOY_setEventHandler(joyEvent);
- // メインループ
- while (TRUE) {
- SYS_doVBlankProcess();
- // テキスト表示位置の初期化
- posX = DEFAULT_POSITION_X;
- posY = DEFAULT_POSITION_Y;
- // 押し始めたボタン
- drawButtonChar(joyState.trigger);
- // テキスト表示位置をずらす
- posX = DEFAULT_POSITION_X;
- posY++;
- // 離したボタン
- drawButtonChar(joyState.off);
- // テキスト表示位置をずらす
- posX = DEFAULT_POSITION_X;
- posY++;
- // 押しているボタン
- drawButtonChar(joyState.current);
- }
- return 0;
- }
実行結果
上記コードをSGDK1.70でコンパイルし
Gens v2.14 Souvenirで実行したスクリーンショット
解説
JOY_setEventHandler関数はVBlankごとにコントローラの状態を更新し、状態に変化があれば指定されたイベントを発生させます。
ボタン押下時の処理を指定関数内で書いても良いのですが、ボタン受付を必要とする場面が増えるたびに分岐が増えることが予想されます。
そのためイベントハンドラ関数ではボタンの状態を設定するだけにし、ボタンによるそれぞれの処理はメインループ内で行っています。
注意が必要なのは、イベントハンドラ関数はボタンの状態に変化が起きた場合のみ実行されるということです。
同じボタンを押し続けている間、つまり前の状態から変化がない場合はイベントハンドラ関数は実行されません。