掌叔
2008-06-15 09:30:35
摘自:ndsbbs
作者:nashi1987
这一节,我们介绍如何处理用户的按键操作。
REG_KEYINPUT 寄存器:
NDS有一个硬件寄存器,当按键被按下时,寄存器的值会改变。寄存器REG_KEYINPUT 位于内存地址的0x4000130处。它是只读寄存器。当按键时,值会改变:
KEYS Bit Key 'ndslib' define Down if Up if
0 A KEY_A Cleared Set
1 B KEY_B Cleared Set
2 Select KEY_SELECT Cleared Set
3 Start KEY_START Cleared Set
4 Directional Right KEY_RIGHT Cleared Set
5 Directional Left KEY_LEFT Cleared Set
6 Directional Up KEY_UP Cleared Set
7 Directional Down KEY_DOWN Cleared Set
8 Right Alternate Button KEY_R Cleared Set
9 Left Alternate Button KEY_L Cleared Set
REG_KEYXY 寄存器:
你会注意到这里漏掉了两个键, 'X' 和 'Y'。
这两个键是从不同的寄存器读取的,REG_KEYXY寄存器,在内存地址0x04000136处。不幸的是这个寄存器只能被ARM7读取。
为了让它能被ARM9读取,在LIBNDS的ARM7样板代码中,ARM7在垂直间隔中断时读取寄存器值并储存在IPC数据结构中,IPC可被ARM9读取。这是相关代码片:
void InterruptHandler(void) {
[...]
but = REG_KEYXY;
[...]
IPC->heartbeat = heartbeat;
IPC->buttons = but;
IPC->touchX = x;
[...]
}
REG_KEYXY 寄存器不仅包含X、Y键状态位,它还包括触控笔和NDS屏幕和上或打开的状态位:
XKEYS Bit Key 'ndslib' define Down if... Up if ...
0 X (1 << 0) Cleared Set
1 Y (1 << 1) Cleared Set
2 Pen Down (1 << 6) Cleared Set
3 Hinge (1 << 7) Set Cleared
读键:
使读取 REG_KEYINPUT 寄存器变的简单一点,我取它值的补码。这允许使用'&' 操作符来判断键是否被按下。我们可以这样写代码:
uint16 keysPressed = ~(REG_KEYINPUT);
if(keys_pressed & KEY_UP)
--shape_y;
来取代这个不直观的
if(!(REG_KEYINPUT & KEY_UP))
--shape_y;
同样的事ARM7可以这样做:
uint16 specialKeysPressed = ~IPC->buttons;
// Y Key
if(specialKeysPressed & (1 << 1))
shape_color = RGB15(7, 7, 7);
// X Key
if(specialKeysPressed & (1 << 0))
shape_color = RGB15(0, 15, 15);
// Pen Down
if(specialKeysPressed & (1 << 6))
shape_color = RGB15(0, 31, 31);
// Hinge closed
if(!(specialKeysPressed & (1 << 7)))
shape_color = RGB15(0, 0, 0);
通过键来控制图形移动:
我们对上一篇教程中的示例做一下轻微改动,以通过键来控制。
我们用方向键控制来代替图形的自动移动。其他的键控制图形的颜色。合上屏幕会使它消失,打开再按一个键又会让它重现。
我们使用一个公共变量来储存颜色值:
static uint16 shape_color = RGB15(31, 0, 0);
绘图代码也须改变:
void on_irq()
{
if(REG_IF & IRQ_VBLANK) {
draw_shape(old_x, old_y, VRAM_A, RGB15(0, 0, 0));
draw_shape(shape_x, shape_y, VRAM_A, shape_color);
// Tell the DS we handled the VBLANK interrupt
VBLANK_INTR_WAIT_FLAGS |= IRQ_VBLANK;
REG_IF |= IRQ_VBLANK;
}
else {
// Ignore all other interrupts
REG_IF = REG_IF;
}
}
图形通过方向键移动:
uint16 keysPressed = ~(REG_KEYINPUT);
// Based on the key pressed, move the shape.
if(keysPressed & KEY_UP)
--shape_y;
if(keysPressed & KEY_DOWN)
++shape_y;
if(keysPressed & KEY_LEFT)
--shape_x;
if(keysPressed & KEY_RIGHT)
++shape_x;
颜色通过测试IPC->buttons的值来改变,但首先取它的补码使其更加直观:
uint16 specialKeysPressed = ~IPC->buttons;
// Change the color of the shape if the relevant key was pressed.
if(keysPressed & KEY_A)
shape_color = RGB15(31, 0, 0);
if(keysPressed & KEY_B)
shape_color = RGB15(0, 31, 0);
if(keysPressed & KEY_SELECT)
shape_color = RGB15(0, 0, 31);
if(keysPressed & KEY_START)
shape_color = RGB15(31, 31, 31);
if(keysPressed & KEY_R)
shape_color = RGB15(15, 0, 15);
if(keysPressed & KEY_L)
shape_color = RGB15(7, 15, 7);
// Y Key
if(specialKeysPressed & (1 << 1))
shape_color = RGB15(7, 7, 7);
// X Key
if(specialKeysPressed & (1 << 0))
shape_color = RGB15(0, 15, 15);
// Pen Down
if(specialKeysPressed & (1 << 6))
shape_color = RGB15(0, 31, 31);
// Hinge closed
if(!(specialKeysPressed & (1 << 7)))
shape_color = RGB15(0, 0, 0);
小猫
2011-09-18 12:53:58
good