libgba のキー入力ライブラリは scanKeys 関数でキーデータ更新後、
keysUp、keysDown、keysDownRepeat 関数で入力情報を 1 度取得すると、
2 回目以降値を返してくれなくなる。
libnds 使って DS 開発してた頃も確かそういう動きだったなーと思い
ソースコード見てみたら案の定だった。
関数内で値を返しつつ 0 でクリアしていやがる。
但し、keysHeld だけは何故か値クリアされていない。
for (;;)
{
VBlankIntrWait();
scanKeys();
if (keysDown() & KEY_A) { iprintf("INPUT A"); }
if (keysDown() & KEY_B) { iprintf("INPUT B"); }
}
この場合 A ボタンの入力には反応するが
B ボタンの入力には反応しない。
なので、押したときや離したときを複数回評価したいなら
一度変数に入れてから作業することになる。
for (;;)
{
VBlankIntrWait();
scanKeys();
off = keysUp();
trg = keysDown();
rep = keysDownRepeat();
if (trg & KEY_A) { iprintf("INPUT A"); }
if (trg & KEY_B) { iprintf("INPUT B"); }
}
なお、keysUp、keysDown、keysDownRepeat の戻り値はそれぞれ別なので、
3 つの変数を用意して scanKeys で更新の度に取得しておくと
必要なとき最新のデータが手に入って何かと便利。
という事で、とりあえずライブラリ化してみたものが以下。
id:akkera102さんの key.h, key.c をリスペクト(汗)。
中身は libgba と C 標準ライブラリで実装。
…実を言うとakkeraさんのサンプルプログラムから
こそーり借用しようかと思ったけど
如何せん key.h, key.c 以外のインクルードは増やしたくなかったので
結局お借りしないでポーティングという手段を取った。
key.h
#ifndef KEY_H
#define KEY_H
#ifdef __cplusplus
extern "C" {
#endif
#include <gba_types.h>
#include <gba_input.h>
#define KEY_REPEAT_CNT 30
#define KEY_REPEAT_DLY 60
typedef struct {
u32 cnt;
u32 trg;
u32 off;
u32 rep;
} ST_KEY;
void KeyInit(void);
void KeyExec(void);
u32 KeyGetCnt(void);
u32 KeyGetTrg(void);
u32 KeyGetOff(void);
u32 KeyGetRep(void);
#ifdef __cplusplus
}
#endif
#endif
key.c
#include "key.h"
#include <string.h>
ST_KEY Key;
void KeyInit(void)
{
memset(&Key, 0x00, sizeof(ST_KEY));
setRepeat(KEY_REPEAT_DLY, KEY_REPEAT_CNT);
}
void KeyExec(void)
{
scanKeys();
Key.cnt = keysHeld();
Key.trg = keysDown();
Key.off = keysUp();
Key.rep = keysDownRepeat();
}
u32 KeyGetCnt(void)
{
return Key.cnt;
}
u32 KeyGetTrg(void)
{
return Key.trg;
}
u32 KeyGetOff(void)
{
return Key.off;
}
u32 KeyGetRep(void)
{
return Key.rep;
}