
- •Урок 1: Создание среды программирования, глава 1
- •Урок 1: Создание среды программирования, глава 2
- •Урок 1: Создание среды программирования, глава 3
- •Урок 1: Создание среды программирования, глава 4
- •Урок 1: Создание среды программирования, глава 5
- •Урок 2: Создание первой собственной программы, глава 1
- •Урок 2: Создание первой собственной программы, глава 2
- •Урок 2: Создание первой собственной программы, глава 3
- •Урок 3: Шпаргалки для начинающих программистов, глава 1
- •Урок 3: Шпаргалки для начинающих программистов, глава 2
- •Урок 3: Шпаргалки для начинающих программистов, глава 3
- •Урок 4: Простейшие способы обработки изображений, глава 1
- •Урок 4: Простейшие способы обработки изображений, глава 2
- •Урок 4: Простейшие способы обработки изображений, глава 3
- •Урок 4: Простейшие способы обработки изображений, глава 4
- •Урок 4: Простейшие способы обработки изображений, глава 5
- •Урок 5: Новые методы программирования на psp, глава 1
- •Урок 5: Новые методы программирования на psp, глава 2
- •Урок 5: Новые методы программирования на psp, глава 3
- •Урок 5: Новые методы программирования на psp, глава 4
- •Урок 5: Новые методы программирования на psp, глава 5
- •Урок 6: Добавление звука в программу, глава 1
- •Урок 6: Добавление звука в программу, глава 2
- •Урок 6: Добавление звука в программу, глава 3
- •Считывание всего файла, глава 1
- •Считывание всего файла, глава 2
- •Считывание всего файла, глава 3
- •Считывание всего файла, глава 4
- •Считывание всего файла, глава 5
Урок 4: Простейшие способы обработки изображений, глава 3
Мы возвращаемся. Перед вами третья часть урока 4. Если вы не прочитали первую и вторую части, то вам следует ознакомиться с ними.
После некоторых трудностей, возникших в конце последнего раздела, следующую строку нам необходимо обновить. Она представляет обычное определение модуля, который мы использовали во всех остальных наших программах:
PSP_MODULE_INFO("Image Display Program", 0, 1, 1);
Снова добавим уже знакомый код и нашу стандартную функцию обратного вызова:
/* Exit callback */ int exit_callback(int arg1, int arg2, void *common) {sceKernelExitGame();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, 0×11, 0xFA0, 0, 0); if(thid >= 0) {sceKernelStartThread(thid, 0, 0);} return thid;}
Что-то знакомое, не так ли? Итак, мы добрались до самого интересного — запуска нашей функции main():
int main() { char buffer[200]; Image* ourImage;
До этого момента все, что мы проделали со строками, будет выведено на экран с помощью printf (). Отлично! Теперь пришло время узнать, что представляет собой строка. Итак, в С (Си) строка – это массив символов. В С (Си) нет такого понятия, как «myString». Есть совокупность только 8 символьных переменных, помещенных вместе в память. Чтобы создать строку, сначала мы должны выделить необходимое количество памяти. Тем самым мы зарезервировали нужное количество памяти, и при дальнейших действиях (определение переменной или что-либо еще) наша строка сможет расшириться. Иначе произойдет переполнение буфера, но это мы не будем рассматривать сейчас. Просто помните, что нежелательно и может привести к зависанию вашего PSP. Для определения массива в С (Си), вы добавляете желаемый величины массив (данного типа) в скобки после имени переменной. Когда мы используем строку char buffer[200], мы отводим под память 200 символьных переменных. 200 – это максимальное количество символов, которое может содержать наша строка. Существует способ, позволяющий изменить размер, но это уже выходит за рамки данного учебного руководства.
Вторая строка в нашей функции main() задает новую переменную, названную «ourImage» с типом данных Image. Этот тип данных был определен в заголовочном файле graphics.h, который мы включили. Все, что мы делаем с ним, окажется в файле graphics.h благодаря использованию других функций. Вы против того, чтобы мы использовали этот файл? Но в ином случае программа стала для нас головной болью.
Догадываетесь, что будет дальше? Мы завершаем третью часть урока 4 и неспешно переходим к четвертой части.
Урок 4: Простейшие способы обработки изображений, глава 4
Мы уже близки к запуску программы. Перед вами четвертая часть из урока 4. Если вы не читали первую, вторую и третью части, то вернитесь в начало учебных материалов.
Итак, у нас есть несколько строк установочного кода:
pspDebugScreenInit(); SetupCallbacks(); initGraphics();
Первые две строки из этого кода схожи с теми строками, которые мы использовали в других программах для установки экрана. Третья строка вызывает другую функцию в graphics.h, которая позволяет выводить на экран графику; она полностью выполняет начальную настройку.
Вот и вся установка, которую нам следовало осуществить перед работой с нашими изображениями. После этого нам необходимо перейти к загрузке файла PNG.
sprintf(buffer, "ourImage.png"); ourImage = loadImage(buffer);
Первая срока данного кода подобна вызову printf (). Но вместо вывода на экран, она представляет последовательность символов. Это довольно полезно. До того, как я узнал об этой функции, я пытался написать свою собственную. Но допустил ошибку. Первым параметром, который задает sprintf(), был символьный массив (иначе строка). Мы используем буферный массив, который определили выше. Остальное подобно printf(). Мы хотели сохранить путь к нашему изображению в буфер. Мы бы могли использовать это для вставки переменных в строку так же, как и при синтаксическом анализе аналогичного пути printf () (если вы забыли как это делать — освежите свою память, повторно прочитав третий урок).
Следующая строка загружает наше изображение через переменную ourImage, которую мы задали ранее. loadImage () является следующей функцией, которая определена в файле graphics.h. Требуется один параметр, и это строка, содержащая путь к изображению.
Теперь сделаем быструю проверку, чтобы посмотреть, успешно ли загрузилось изображение:
if (!ourImage) { //Image load failed printf("Image load failed!\\n"); } else {
Если функция loadImage найдет ошибку, то значение нашей переменной будет равно 0 (или ложь). Значит, есть какие-то ошибки в коде. В таком случае мы должны проверить через оператор if. Если была сделана ошибка, то будет выдано сообщение об этом. Надеемся, что мы не столкнемся с проблемой загрузки изображения. Иначе следующая часть программы будет выполнена:
int x = 0; int y = 0; sceDisplayWaitVblankStart();
Это только установка для вывода изображения на экран. Данные процессы должны быть знакомы вам. Сейчас мы объявляем и задаем начальные целые значения, после вызываем sceDisplayWaitVblankStart (если вы помните, то эта та же самая функция, применяемая нами при чтении из панели управления). Данная операция позволяет работать кнопке «Home».
Теперь с помощью цикла захватим весь экран. Экран представляет собой 480 пикселей по ширине и 272 пикселя по высоте:
while (x < 480) { while (y < 272) {
Здесь простые циклы «while», о которых вы должны помнить из урока 3. Внешний цикл будет продолжаться до тех пор, пока x меньше 480 (ширина экрана), а внутренний цикл – до тех пор, пока y меньше 272 (высота экрана).
Далее помещаем код с целью вывода на экран изображения:
blitAlphaImageToScreen(0 ,0 ,32 , 32, ourImage, x, y); y += 32; }
Первая строка – ваш код. С помощью него на экран выводится 32-битное изображение, которое включает альфа канал! Альфа-канал – это информация о прозрачности. Функция blitAlphaImageToScreen задает семь параметров. Первые два являются офсетами. Если вы используете seperate PNGs для каждого изображения, то они должны равняться нулю. Чтобы учесть эти два параметра, вам нужно иметь один основной файл изображения, содержащий все ваши спрайты. Как правило, имея два изображения в одном и том же двоичном файле (например, следующие друг за другом), вам нужно использовать офсеты для того, чтобы сообщить программе, какую часть основного изображения вы хотите вывести на экран. Вторые два параметра необходимы для указания ширины и высоты соответственно. Так как наше изображение 32×32 пикселя, то мы используем 32 в обоих случаях. Пятый параметр должен вызвать функцию, необходимую переменную изображения (понятно, что используем переменную ourImage). И наконец, последние два параметра необходимы для определения x и y позиции изображения, выводимого на экран. В программировании это напоминает перевернутую координатную плоскость. Ось X такая же, как ив математике (то есть, значения увеличиваются при перемещении слева направо). С другой стороны ось Y перевернута. Увеличивая Y, вы перемещаетесь вниз по координатной плоскости. Если вы привыкли к математическим координатам, то сначала будете путаться. Однако со временем приспособитесь.
Следующая строка постепенно увеличивает счетчик цикла. Увеличение происходит на 32, поскольку данное число характеризует высоту нашего изображения. Оператор «+ =» с каждым шагом увеличивает переменную. Таким образом, «x + = 32» эквивалентен «x = x +32«. Наша цель – собрать элементы мозаичного изображения на экране.
Пора двигаться дальше к последней главе урока 4. Продолжаем!