キーコンフィグ実装サンプル。


今日考えて取り合えず実装してみたら
まずまずの体裁が取れてたので公開しておきます。
キーとアクションの間にモジュールを咬ましてみたら案外スマートに行けた感じです。


昨日のネームエントリ実装サンプルもなのですが、1シーンとして作らず、部品として扱えるよう
記述を最小に抑えて書いてます(書いてるつもりです(汗)。)。
シーンを組む際のUI実装等はその都度必要になる代わり、
好きなときに利用者の用途に応じて呼び出せるというメリットを狙ってます。


KeyConfig routine
Keycfg module test


プロジェクト一式
ttp://page.freett.com/ntr/tech/keycfg.zip


ソース


main.c

/*---------------------------------------------------------------------------------
	
	KeyConfig routine
	Keycfg module test
	
	version 0.01
	Apr 12, 2010
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <nds.h>
#include "Keycfg.h"


typedef enum{
	MAIN_INIT = 0x00, 
	MAIN_EXEC, 
	MAIN_CONF
}MAIN_ACT;

typedef struct{
	u16 act;
	int cursor;
}MainStatus;

static MainStatus st_main;


int main(void);
void main_Init(void);
void main_Exec(void);
void main_Conf(void);
char *main_GetKeyNamePtr(u32 key_bit);


//---------------------------------------------------------------------------------
int main(void) {
//---------------------------------------------------------------------------------
	
	while(1) {
		
		swiWaitForVBlank();
		scanKeys();
		
		switch(st_main.act){
			
		case MAIN_INIT:
			main_Init();
			break;
			
		case MAIN_EXEC:
			main_Exec();
			break;
			
		case MAIN_CONF:
			main_Conf();
			break;
			
		default:
			break;
			
		}
		
	}

}

//---------------------------------------------------------------------------------
void main_Init(void) {
//---------------------------------------------------------------------------------
	
	memset(&st_main, 0, sizeof(st_main));
	
	consoleDemoInit();
	printf("KeyConfig routine\nKeycfg module test\n\nversion 0.01\nApr 12, 2010\n\nBy REGEKATSU\n\n");
	
	st_main.act = MAIN_EXEC;
	
}

//---------------------------------------------------------------------------------
void main_Exec(void) {
//---------------------------------------------------------------------------------
	
	//弱パンチの処理
	if(keysDown() & Keycfg_GetButton(0)){
		printf("\x01b[10;0HLow Punch!");
	}else if(keysUp() & Keycfg_GetButton(0)){
		printf("\x01b[10;0H\x01b[2K");
	}
	
	//中パンチの処理
	if(keysDown() & Keycfg_GetButton(1)){
		printf("\x01b[11;0HMiddle Punch!");
	}else if(keysUp() & Keycfg_GetButton(1)){
		printf("\x01b[11;0H\x01b[2K");
	}
	
	//強パンチの処理
	if(keysDown() & Keycfg_GetButton(2)){
		printf("\x01b[12;0HHigh Punch!");
	}else if(keysUp() & Keycfg_GetButton(2)){
		printf("\x01b[12;0H\x01b[2K");
	}
	
	//弱キックの処理
	if(keysDown() & Keycfg_GetButton(3)){
		printf("\x01b[13;0HLow Kick!");
	}else if(keysUp() & Keycfg_GetButton(3)){
		printf("\x01b[13;0H\x01b[2K");
	}
	
	//中キックの処理
	if(keysDown() & Keycfg_GetButton(4)){
		printf("\x01b[14;0HMiddle Kick!");
	}else if(keysUp() & Keycfg_GetButton(4)){
		printf("\x01b[14;0H\x01b[2K");
	}
	
	//強キックの処理
	if(keysDown() & Keycfg_GetButton(5)){
		printf("\x01b[15;0HHigh Kick!");
	}else if(keysUp() & Keycfg_GetButton(5)){
		printf("\x01b[15;0H\x01b[2K");
	}
	
	
	//キーコンフィグへ遷移
	printf("\x01b[21;0HKEY_SL to key configuration... ");
	
	if(keysDown() & KEY_SELECT){
		
		printf("\x01b[10;0H\x01b[2K\x01b[10;8HL-PUNCH : %s", main_GetKeyNamePtr( Keycfg_GetButton(0) ) );
		printf("\x01b[11;0H\x01b[2K\x01b[11;8HM-PUNCH : %s", main_GetKeyNamePtr( Keycfg_GetButton(1) ) );
		printf("\x01b[12;0H\x01b[2K\x01b[12;8HH-PUNCH : %s", main_GetKeyNamePtr( Keycfg_GetButton(2) ) );
		printf("\x01b[13;0H\x01b[2K\x01b[13;8HL-KICK  : %s", main_GetKeyNamePtr( Keycfg_GetButton(3) ) );
		printf("\x01b[14;0H\x01b[2K\x01b[14;8HM-KICK  : %s", main_GetKeyNamePtr( Keycfg_GetButton(4) ) );
		printf("\x01b[15;0H\x01b[2K\x01b[15;8HH-KICK  : %s", main_GetKeyNamePtr( Keycfg_GetButton(5) ) );;
		
		printf("\x01b[%d;7H>", 10 + st_main.cursor);
		
		st_main.act = MAIN_CONF;
		
	}
	
}

//---------------------------------------------------------------------------------
void main_Conf(void) {
//---------------------------------------------------------------------------------
	
	u32 key_bit;
	
	//キーコンフィグ可能なキーが押下された場合。
	if( (key_bit = keysDown() & Keycfg_GetKeyMasks()) ){
		
		//押下のあったキーを、現在カーソルで選択されてる動作に対応させる。
		Keycfg_SetButton(st_main.cursor, key_bit);
		printf("\x01b[%d;18H%s", 10 + st_main.cursor, main_GetKeyNamePtr( Keycfg_GetButton(st_main.cursor) ) );
		
	}
	
	
	//カーソルの移動(動作の選択を行う。)。
	if(keysDown() & KEY_UP){
		
		printf("\x01b[%d;7H ", 10 + st_main.cursor);
		if(--st_main.cursor < 0){
			st_main.cursor = BUTTON_MAX - 1;
		}
		printf("\x01b[%d;7H>", 10 + st_main.cursor);
		
	}else if(keysDown() & KEY_DOWN){
		
		printf("\x01b[%d;7H ", 10 + st_main.cursor);
		if(++st_main.cursor > BUTTON_MAX - 1){
			st_main.cursor = 0;
		}
		printf("\x01b[%d;7H>", 10 + st_main.cursor);
		
	}
	
	
	//メイン処理へ遷移
	printf("\x01b[21;0HKEY_SL to exit configuration...");
	
	if(keysDown() & KEY_SELECT){
		
		printf("\x01b[10;0H\x01b[2K");
		printf("\x01b[11;0H\x01b[2K");
		printf("\x01b[12;0H\x01b[2K");
		printf("\x01b[13;0H\x01b[2K");
		printf("\x01b[14;0H\x01b[2K");
		printf("\x01b[15;0H\x01b[2K");
		
		st_main.act = MAIN_EXEC;
		
	}
	
}

//---------------------------------------------------------------------------------
char *main_GetKeyNamePtr(u32 key_bit) {
//---------------------------------------------------------------------------------
	
	char *key_name = NULL;
	
	switch(key_bit){
		
	case KEY_A:
		key_name = "KEY_A";
		break;
		
	case KEY_B:
		key_name = "KEY_B";
		break;
		
	case KEY_SELECT:
		key_name = "KEY_SELECT";
		break;
		
	case KEY_START:
		key_name = "KEY_START";
		break;
		
	case KEY_RIGHT:
		key_name = "KEY_RIGHT";
		break;
		
	case KEY_LEFT:
		key_name = "KEY_LEFT";
		break;
		
	case KEY_UP:
		key_name = "KEY_UP";
		break;
		
	case KEY_DOWN:
		key_name = "KEY_DOWN";
		break;
		
	case KEY_R:
		key_name = "KEY_R";
		break;
		
	case KEY_L:
		key_name = "KEY_L";
		break;
		
	case KEY_X:
		key_name = "KEY_X";
		break;
		
	case KEY_Y:
		key_name = "KEY_Y";
		break;
		
	case KEY_TOUCH:
		key_name = "KEY_TOUCH";
		break;
		
	case KEY_LID:
		key_name = "KEY_LID";
		break;
		
	default:
		key_name = "KEY_NULL";
		break;
		
	}
	
	return key_name;
	
}

//---------------------------------------------------------------------------------


Keycfg.h

/*---------------------------------------------------------------------------------
	
	Keycfg module header
	
	version 0.01
	Apr 12, 2010
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _KEYCFG_H_
#define _KEYCFG_H_


//キーコンフィグを許可するボタン数。
#define BUTTON_MAX 6


#include <nds/ndstypes.h>
#include <nds/arm9/input.h>


#ifdef __cplusplus
extern "C" {
#endif


u32 Keycfg_GetKeyMasks(void);
u32 Keycfg_GetButton(int button_no);
void Keycfg_SetButton(int button_no, u32 key_bit);


#ifdef __cplusplus
}
#endif

#endif	// _KEYCFG_H_


Keycfg.c

/*---------------------------------------------------------------------------------
	
	Keycfg module routine
	
	version 0.01
	Apr 12, 2010
	
	By. REGEKATSU
	
---------------------------------------------------------------------------------*/

#include "Keycfg.h"


//キーコンフィギュレーション時、
//特定キー以外のキーデータ、または複数キーデータ(同時押し)を登録しないようにするため、マスク用テーブルを用意する。
//キーセット関数引数より受け取ったキーデータはこのマスク値を用いて確定データを作成するものとする。
const static u32 key_mask[BUTTON_MAX] = {KEY_A, KEY_B, KEY_R, KEY_L, KEY_X, KEY_Y};


typedef struct{
	u32 button[BUTTON_MAX];
}KeycfgStatus;


static KeycfgStatus st_keycfg = { 
	
	//デフォルトとするキーデータ(キー配置)にて初期化する。
	{KEY_Y, KEY_X, KEY_L, KEY_B, KEY_A, KEY_R} 
	
};


//---------------------------------------------------------------------------------
u32 Keycfg_GetKeyMasks(void){
//---------------------------------------------------------------------------------
	
	//キーコンフィグを許可するボタンのビット情報(KEY_A, KEY_B 等)を全てまとめた状態で返す。
	
	int i;
	u32 key_masks = 0;
	
	for(i = 0;i < BUTTON_MAX;i++){
		key_masks |= key_mask[i];
	}
	
	return key_masks;
	
}

//---------------------------------------------------------------------------------
u32 Keycfg_GetButton(int button_no){
//---------------------------------------------------------------------------------
	
	//ボタン番号の指定がキーコンフィグ可能数を超える場合、0 を返す。
	if(button_no < 0 || button_no >= BUTTON_MAX) return 0;
	
	return st_keycfg.button[button_no];
	
}

//---------------------------------------------------------------------------------
void Keycfg_SetButton(int button_no, u32 key_bit){
//---------------------------------------------------------------------------------
	
	//ボタン番号の指定がキーコンフィグ可能数を超える場合、何もせず終了する。
	if(button_no < 0 || button_no >= BUTTON_MAX) return;
	
	int i;
	u32 key_fix;
	
	//引数より受け取ったキーデータは特定キーのみ登録を許可するものとする。
	//また単一のキー入力となるようキーデータの丸め作業も行う。
	for(i = 0;i < BUTTON_MAX;i++){
		
		if( (key_fix = key_bit & key_mask[i]) ){
			st_keycfg.button[button_no] = key_fix;
			break;
		}
		
	}
	
}

//---------------------------------------------------------------------------------