PSP SDKのcontroller周りについて


PSP SDKのサンプルでcontrollerのやつがあって、それを読んでるんだけど、ゲームプログラミング初心者なので、へーと思うことが多い。ボタンが押されたかどうかは、監視スレッドとループで書いてて、PSPコーディングて結構、原始的なプログラミングが必要なんですね。関数やら構造体やらが出てきて覚えることが多そうなのでソースの解説でもしてみたいと思います。

まず、コントローラーの情報を保持する構造体であるSceCtrlDataについて。
sceCtrlReadBufferPositiveにSceCtrlDataの変数を入れることで現在入力されているボタンの情報を得ることができます。構造体の中身は以下のような感じ。

  • SceCtrlData


struct SceCtrlData {
unsigned int TimeStamp //現在読み込んでいるフレーム?
unsigned int Buttons  //ボタンのbit列。
unsigned char Lx //アナログスティクのX座標
unsigned char Ly  //アナログスティクのY座標
unsigned char Rsrv [6] //予約
}
どのボタンが押されたかを調べるために、なぜ&(AND)が使われているかは「SceCtrlDataについて〜ビット演算とは?」に詳しく書かれています。同時に押されたときに、どれが押されたのかを調べるのに基礎的なビット演算が使われています。

  • 押されたボタン情報をprintするプログラム


#include
#include
#include
#include
#include

/* Define the module info section */
PSP_MODULE_INFO("CONTROLTEST", 0, 1, 1);

/* Define the main thread's attribute value (optional) */
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);

/* Define printf, just to make typing easier */
#define printf pspDebugScreenPrintf

void dump_threadstatus(void);

int done = 0;

/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
done = 1;
return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
int cbid;

cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();

return 0;
}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
int thid = 0;

thid = sceKernelCreateThread("update_thread", CallbackThread,
0x11, 0xFA0, 0, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}

return thid;
}

int main(void)
{
SceCtrlData pad;
//デバッグスクリーンの初期化
pspDebugScreenInit();
SetupCallbacks();
//コントローラーの入力サイクルを設定(通常は0に設定する)
sceCtrlSetSamplingCycle(0);
// アナログスティックの入力を有効にする
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);

while(!done){
//デバッグスクリーンの開始位置(x,y)
pspDebugScreenSetXY(0, 2);
        //コントローラの入力を取得する(ブロッキング
sceCtrlReadBufferPositive(&pad, 1);
//アナログスティクの座標
printf("Analog X = %d ", pad.Lx);
printf("Analog Y = %d \n", pad.Ly);

if (pad.Buttons != 0){
//□ボタン
if (pad.Buttons & PSP_CTRL_SQUARE){
printf("Square pressed \n");
}
            //△ボタン
if (pad.Buttons & PSP_CTRL_TRIANGLE){
printf("Triangle pressed \n");
}
//○ボタン
if (pad.Buttons & PSP_CTRL_CIRCLE){
printf("Cicle pressed \n");
}
            //×ボタン
if (pad.Buttons & PSP_CTRL_CROSS){
printf("Cross pressed \n");
}
//上ボタン
if (pad.Buttons & PSP_CTRL_UP){
printf("Up pressed \n");
}
            //下ボタン
if (pad.Buttons & PSP_CTRL_DOWN){
printf("Down pressed \n");
}
            //左ボタン
if (pad.Buttons & PSP_CTRL_LEFT){
printf("Left pressed \n");
}
            //右ボタン
if (pad.Buttons & PSP_CTRL_RIGHT){
printf("Right pressed \n");
}
//startボタン
if (pad.Buttons & PSP_CTRL_START){
printf("Start pressed \n");
}
            //selectボタン
if (pad.Buttons & PSP_CTRL_SELECT){
printf("Select pressed \n");
}
            //Lボタン
if (pad.Buttons & PSP_CTRL_LTRIGGER){
printf("L-trigger pressed \n");
}
            //Rボタン
if (pad.Buttons & PSP_CTRL_RTRIGGER){
printf("R-trigger pressed \n");
}
}
}
    //ゲーム終了
sceKernelExitGame();
return 0;
}

監視スレッドでHOMEボタンからゲームを終了するを選択するまでループで"ボタン情報取得"→"ボタン情報出力"を繰り返します。