Программируем для PSP: Часть II. Тотальный контроль

В прошлом туториале мы разобрались с "хелловорлдом", теперь пришло время к следующей, не менее важной вещи: вводе информации. Умея выводить что-то на экран и узнавать, что нажал пользователь, уже можно сделать полезную программу. Фактически, после этого урока уже можно будет начинать что-то свое, однако я бы посоветовал дождаться, хотя бы, спрайтов.

Создадим проект по шаблону, описанному в первой части. Найдем в фаиле функцию main() -- основную функцию программы, а в ней главный цикл ( while(1) { ... } ). Кстати, насчет while(1): в программировании для psp не считается дурным тоном делать бесконечные циклы внутри программы, т.к. выход все равно осуществляется по кнопке HOME, и только так.

Сделаем стандартный цикл обработки сообщений: получение и переваривание. Первое, что нужно сделать -- определить переменную, в которой будет хранится состояние клавиатуры:

SceCtrlData pad; // переменная, где хранится информация о состоянии кнопок (нажаты/не нажаты).

Структура SceCtrlData хранит в себе TimeStamp - количество фреймов, похоже, от запуска программы (надо уточнить!), Buttons -- битовую маску состояния кнопок (учитываются кнопки Select, Start, крестик, треугольник, квадрат, шифты, стрелки, состояние Hold и Home. Все остальное учитывается только в Kernel Mode, за подробностями смотрите фаил devkitPSPpspsdkincludepspctrl.h) и координаты стика Lx и Ly. Поскольку она определена только в pspctrl.h, придется добавить в начало фаила

#include <pspctrl .h>

Итак, стираем все внутренности while'ла, и пишем

sceCtrlReadBufferPositive(&pad, 1); // читаем содержимое буфера э-э клавиатуры

Эта функция заполняет структуру pad текущими значениями состояния кнопок и стика. Кстати, чтобы получить координаты стика удавалось, надо перед while'ом впихнуть 2 строки:

sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); // настраиваем на прием информации о положении стика

Иначе джойстик так и застынет на положении (128:128) (это -- середина, сами координаты меняются от 0 до 255).

Итак, мы считали информацию, теперь нужно ее вывести. Вот что получилось у меня:

pspDebugScreenPrintf("TimeStamp %i | Pressed: ", pad.TimeStamp); // выводим TimeStamp
if (pad.Buttons == 0) // ничего не нажато
{
    pspDebugScreenPrintf("NONE ");
} else {
    if (pad.Buttons & PSP_CTRL_TRIANGLE) pspDebugScreenPrintf("TRIANGLE ");
    if (pad.Buttons & PSP_CTRL_CIRCLE) pspDebugScreenPrintf("CIRCLE ");
    if (pad.Buttons & PSP_CTRL_CROSS) pspDebugScreenPrintf("CROSS ");
    if (pad.Buttons & PSP_CTRL_SQUARE) pspDebugScreenPrintf("SQUARE ");
    // какие кнопки нажаты?
}
pspDebugScreenPrintf("(%i) | Stick: %i:%in", pad.Buttons, pad.Lx, pad.Ly);
// выводим координаты стика

Как видите, я учитываю только состояние кнопок с картинками (ну, треугольника, круга, квадрата и крестика), дописать поддержку остальных легко, за константами обращайтесь к devkitPSPpspsdkincludepspctrl.h. Код в цикле будет выводить нечто такое:

TimeStamp 68832112 | Pressed NONE (0) | Stick: 126:150
TimeStamp 72317982 | Pressed TRIANGLE CIRCLE (12288) | Stick: 119:167

Итак, компилируйте весь полученный код:

/*
    © va1en0k, 2008
    enjoy ;)
*/
#include <pspkernel .h>

#include <pspdebug .h>

#include <pspctrl .h>


PSP_MODULE_INFO("Hello World", 0, 1, 1);

int ExitCallback(int Arg1, int Arg2, void *Common)
{
    sceKernelExitGame();
    return 0;
}

int CallbackThread(SceSize Args, void *Argp)
{
    int CallbackId;

    CallbackId = sceKernelCreateCallback("Exit Callback", ExitCallback, NULL);
    sceKernelRegisterExitCallback(CallbackId);

    sceKernelSleepThreadCB();

    return 0;
}

int SetupCallbacks(void)
{
    int ThreadId = 0;

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

    return ThreadId;
}

SceCtrlData pad; // переменная, где хранится информация о состоянии кнопок (нажаты/не нажаты).

int main(int argc, char ** argv)
{
    pspDebugScreenInit();
    SetupCallbacks();

    sceCtrlSetSamplingCycle(0);
    sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); // настраиваем на прием информации о положении стика

    while(1) // главный цикл программы
    {
         sceCtrlReadBufferPositive(&pad, 1); // читаем содержимое буфера э-э клавиатуры
         pspDebugScreenPrintf("TimeStamp %i | Pressed: ", pad.TimeStamp); // выводим TimeStamp
         if (pad.Buttons == 0) // ничего не нажато
         {
            pspDebugScreenPrintf("NONE ");
         } else {
            if (pad.Buttons & PSP_CTRL_TRIANGLE) pspDebugScreenPrintf("TRIANGLE ");
            if (pad.Buttons & PSP_CTRL_CIRCLE) pspDebugScreenPrintf("CIRCLE ");
            if (pad.Buttons & PSP_CTRL_CROSS) pspDebugScreenPrintf("CROSS ");
            if (pad.Buttons & PSP_CTRL_SQUARE) pspDebugScreenPrintf("SQUARE ");
            // какие кнопки нажаты?
         }
         pspDebugScreenPrintf("(%i) | Stick: %i:%in", pad.Buttons, pad.Lx, pad.Ly);
         // выводим координаты стика
    }

    sceKernelSleepThread();

    return 0;
}

Теперь преобразовывайте в EBOOT, закидывайте на приставку и наслаждайтесь. Как домашнее задание можно попробовать сделать бродилку, или еще какую-нибудь невероятно полезную штуку; я думаю, что посвящу третюю часть всяким прочим фичам text mode, а потом перейду к графике. Удачи!

Источник: http://psp.va1en0k.net/



Опубликовал admin
16 Апр, Среда 2008г.



Программирование для чайников.