-
Notifications
You must be signed in to change notification settings - Fork 0
3.3. Handling key input
Main reference: touch pad example.
Key input handling is a must-know in DS programming. The Nintendo DS features 12 buttons (DPad Up/Down/Left/Right, A/B/X/Y, L/R, Start/Select), plus the the Power button and the TouchScreen (which is also handled through keys API).
libnds makes things incredibly simple:
while(1)
{
scanKeys();
int keys=keysDown();
if(keys & KEYS_DOWN)
{
iprintf("Down key pressed\n");
}
swiWaitForVBlank();
}
This gets the current keys state (for each key check either if it has been pressed or not at the current time). As libnds documentation recommends, we should "call this function once per main loop in order to use the keypad functions".
The difference between these two is the moment of reference. keysDown()
gets the keys newly pressed at the current moment, while keysHeld()
gets all the heys held at the moment of calling, regardless of when they have been pressed.
Both functions return an uint32_t
whose bits tell whether a key is pressed or not. Each key is assigned to a certain bit position in the key states uint
, and we can get the state of a current key by asking if that bit if it's set or not. We can do that by masking the key states returned by keysDown
/keysHeld
/keysUp
with the predefined key masks KEY_<key_name>
, which is internally represented as (1<<key_id). If the result of key_states & KEY_<key_name>
is not zero, then the key in discussion has been triggered at the last key states check.
Step | Keys down | Keys held | Keys Up | keysDown() & KEY_A |
keysHeld() & KEY_A |
keysUp() & KEY_A |
---|---|---|---|---|---|---|
1 | Up | 0 | 0 | 0 | ||
2 | A | Up | KEY_A | 0 | 0 | |
3 | Up A | 0 | KEY_A | 0 | ||
4 | A | Up | 0 | KEY_A | 0 | |
5 | A | 0 | KEY_A | 0 | ||
6 | A | 0 | 0 | KEY_A | ||
7 | 0 | 0 | 0 |
Please also check this post in order not to repeat the same easy-to-do mistake. Don't expect a code block inside
if(keysDown() & KEY_<key_name>) { ... }
continuously run every frame you hold (not sistematically press and release) the<key_name>
. Be aware of the situations when to usekeysDown
andkeysHeld
!
The following code is a demonstration of key handling process in libnds:
#include <nds.h>
#include <stdio.h>
inline void goto_xy(int x,int y) { iprintf("\033[%d;%dH", y, x); }
// prints a table row showing data for each key
inline void writeRow(char* key_name,char* state_down,char* state_held,char* state_up)
{
iprintf("| %-9s| %-5s| %-5s| %-4s|",key_name,state_down,state_held,state_up);
}
const int KEYS_COUNT = 12; // Number of keys we want to check (w/o TOUCH, LID)
int main(void)
{
int keyIds[KEYS_COUNT] = {KEY_A, KEY_B, KEY_SELECT, KEY_START, KEY_RIGHT, KEY_LEFT,
KEY_UP, KEY_DOWN, KEY_R, KEY_L, KEY_X, KEY_Y};
char keyNames[KEYS_COUNT][10] = {"A", "B", "Select", "Start", "Right", "Left",
"Up", "Down", "R", "L", "X", "Y"};
char key_triggered[2]="X";
char key_not_trigg[2]="";
consoleDemoInit();
writeRow("Key name","Down","Held","Up");
iprintf("|----------|------|------|-----|");
while(1)
{
scanKeys(); // fetch key states
int keys_down = keysDown();
int keys_held = keysHeld();
int keys_up = keysUp();
goto_xy(0,2);
for(int i=0;i<KEYS_COUNT;i++)
{
writeRow(keyNames[i],
(keys_down & keyIds[i]) ? key_triggered:key_not_trigg, // prints X if key i id down
(keys_held & keyIds[i]) ? key_triggered:key_not_trigg, // prints X if key i id held
(keys_up & keyIds[i]) ? key_triggered:key_not_trigg); // prints X if key i id up
}
swiWaitForVBlank();
}
return 0;
}
This code illustrates the way keysDown
, keysHeld
and keysUp
work.
libnds Practical Wiki - This is an independent work of learning and exposing the facts about NDS programming. I am not affiliated in any way with Nintendo, devkitPro organization or libnds developers.