今日は keys.c と input.h を読みました。


RGKT-NDS-STDY-008(001)


keysDownRepeat() の使いどころがやっとわかった。
トライ&エラー最強です。


そもそも KeysDownRepeat() がどういう関数がどんなもんかってちゃんと分かってなくて、
最初はソース見ててもピンとこなくって
外国のサイトでごちゃごちゃした使用例見つけて真似してコード書いて
あーそういうことかって分かった感じ。


あれだ。
テキストエディタ(メモ帳とか)のキー長押ししてると同じ文字がダーって続くやつ。
これを keysDownRepeat() 使って実装するとお手軽で済む。
ゲームとかだと
シューティングのオート連射機能とか。
ショットキー一定時間押してると連打になるあれ。


どういう動作が実現できるのかってのは上の通りなんで動くソースは以下に。


#include <nds.h>
#include <stdio.h>


int main(void)
{
	
	uint32 kdr;
	
	consoleDemoInit();
	keysSetRepeat(30, 10);
	
	while(1) {
		
		scanKeys();
		
		if(kdr = (keysDownRepeat() & (KEY_A | KEY_B))){
			
			if(kdr & KEY_A)
				iprintf("KEY_A\n");
			
			if(kdr & KEY_B)
				iprintf("KEY_B\n");
			
		}
		
		swiWaitForVBlank();
		
	}
	
	return 0;
	
}


使い方としては
最初に
keysSetRepeat() で繰り返し動作の間隔を設定する。
次に
scanKeys() でキー状態を取得。
keysDownRepeat() で長押しさせたいキーとで比較させ
長押しが成立してた場合の処理を設定しておく、と。
それと
scanKeys() と keysDownRepeat() は毎フレーム実行させて現在の状態を常に更新させること。

void keysSetRepeat(u8 setDelay, u8 setRepeat)


第一引数の setDelay には
一番最初に押下して何フレーム後に最初のリピートが実行されるかまでを設定する。
上記ソースだと30フレーム後、1フレームの間隔はVBlankだので
約0.5秒後に最初のリピートが開始される。


第二引数の setRepeat には
最初のリピートが開始された後の繰り返しの間隔を何フレームとするかという設定。
上記ソースだと10フレームに設定してるので、
約0.2秒毎にリピート実行されることになる。

uint32 keysDownRepeat(void)


後は毎フレーム keysDownRepeat() の返値を取って
Delay または Repeat が成立したら非ゼロ(現フレームのキー状態丸ごと)、
成立してなければゼロが uint32 で帰って来るのでそれを使って判断するような処理を組めばよい。


ただ、問題点が1つ。
keysDownRepeat() は1フレームに付き1回までしか正しい値を返してこないということ。
同じフレームで2回目以降は全て0が帰ってくるので(1回実行すると0クリアさせるので)、
何度か返値を比較したいときは上記ソースのように
keysDownRepeat() の1回目の実行時に返値を変数に持たせる必要がある。


ディレイとリピート間隔のカウント処理も実は scanKeys() 内に含まれてる。
かなりコンパクトにまとまってて
これだけでリピート処理担ってるのかーって関心する。


追記:
keysDownRepeat() 関数のデフォルトの、Delay 値、Repeat 値は

static u8 delay = 60, repeat = 30


としてセットされてるので
このデフォルト値でキーリピート処理する分には
keysSetRepeat() 関数で初期値をセットせずとも使えます。