Nintendo DS開発入門 - Day 1: 環境構築とキー入力
今日やったこと
- devkitProを使ったDS開発環境の確認
- hello_worldプログラムをmelonDSで実行
- キー入力の検知と画面表示
開発環境
- SDK: devkitPro (devkitARM + libnds)
- エミュレータ: melonDS
- OS: WSL2 (Ubuntu)
学んだこと
1. volatileキーワード
static volatile int frame = 0;
割り込みハンドラで変更される変数にはvolatileを付ける。コンパイラの最適化を防ぎ、毎回メモリから値を読み直すよう指示する。
2. libndsのヘッダ構造
#include <nds.h>一つで必要な機能がすべてインクルードされる。
<nds.h>
└─ <nds/interrupts.h> → IRQ_VBLANK など
└─ <nds/system.h> → pmMainLoop() など
└─ <nds/arm9/input.h> → scanKeys(), keysDown() など
3. キー入力の基本
scanKeys(); // ハードウェアからキー状態を読み取る
int down = keysDown(); // 今押された瞬間のキー
int held = keysHeld(); // 押し続けているキー
int up = keysUp(); // 今離された瞬間のキー
使えるキー定数:
| 定数 | ボタン |
|---|---|
KEY_A, KEY_B, KEY_X, KEY_Y
|
A/B/X/Y |
KEY_L, KEY_R
|
L/R |
KEY_START, KEY_SELECT
|
START/SELECT |
KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT
|
十字キー |
4. 関数定義と関数呼び出しの違い
// 定義(型が必要)
void printKeys(int keys) { ... }
// 呼び出し(型は不要、セミコロン必要)
printKeys(keys);
今日書いたコード
#include <nds.h>
#include <stdio.h>
static volatile int frame = 0;
static void Vblank() {
frame++;
}
void printKeys(int keys) {
if(keys == KEY_A) {
iprintf("\x1b[12;0HKeys = A\n");
} else if(keys == KEY_B) {
iprintf("\x1b[12;0HKeys = B\n");
} else if(keys == KEY_X) {
iprintf("\x1b[12;0HKeys = X\n");
} else if(keys == KEY_Y) {
iprintf("\x1b[12;0HKeys = Y\n");
} else {
iprintf("\x1b[12;0HKeys = %04X\n", keys);
}
}
int main(void) {
touchPosition touchXY;
irqSet(IRQ_VBLANK, Vblank);
consoleDemoInit();
iprintf(" Hello DS dev'rs\n");
while(pmMainLoop()) {
swiWaitForVBlank();
scanKeys();
int keys = keysDown();
int heldKeys = keysHeld();
if (keys & KEY_START) break;
touchRead(&touchXY);
iprintf("\x1b[10;0HFrame = %d", frame);
printKeys(heldKeys);
iprintf("\x1b[16;0HTouch x = %04X, %04X\n", touchXY.rawx, touchXY.px);
iprintf("Touch y = %04X, %04X\n", touchXY.rawy, touchXY.py);
}
return 0;
}
ビルド方法
make clean && make
生成された.ndsファイルをmelonDSで開いて実行。
ハマったポイント
melonDSでキー入力が反応しない
Config → Input and hotkeys でキーボードとDSボタンのマッピングを確認・設定する必要があった。
次回やること
- 十字キーの上下左右の検知
- スプライト表示の基礎