Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Гущин_SDL.pdf
Скачиваний:
168
Добавлен:
17.03.2018
Размер:
1.09 Mб
Скачать

return 0;

}

Конкретный способ или комбинация способов для имитации движения зависят от требований к производительности программы, от сложности ее разработки и сопровождения, а также от индивидуального управления отдельных перемещаемых по экрану объек-тов.

8. Вывод текста с помощью библиотеки SDL_ttf

Непосредственно в составе библиотеки SDL отсутствуют сред-ства вывода на графические поверхности текстовой информации, отличные от программного попиксельного отображения каждого символа. Отсутствуют они и в библиотеке SDL_draw. Основной проблемой для разработки таких средств в составе многоплат-форменных графических библиотек является обеспечение единообразного отображения текста на различных целевых платформах, поскольку далеко не все они могут поддерживать одинаковые по своим возможностям средства отображения текста. Это приводит к необходимости обеспечивать единый интерфейс к множеству раз-личных реализаций средств отображения текста, что существенно усложнило бы библиотеку. Еще большей проблемой при этом является возможное отсутствие единообразия в представлении используемых шрифтов. Для устранения указанных проблем разработчиками библиотеки SDL создано расширение – библиотека SDL_ttf, версия которой 2.0.11 и будет рассмотрена далее.

Библиотека SDL_ttf является интерфейсом-надстройкой над кроссплатформенной библиотекой FreeType 2.0, обеспечивающей единообразное построение в операционных системах семейств Linux, Mac OS X и Windows изображений символов по их двух-байтовым обозначениям согласно UNICODE, с использованием векторных шрифтов формата TrueType (.ttf), а также некоторых шрифтов формата .fon. При этом библиотека FreeType непосредственно не отвечает за перенесение построенных изображений на устройство отображения. Библиотека SDL_ttf обеспечивает формирование на основе текстовой строки специально создаваемой временной поверхности, содержащей изображение данного текста, выполненное указанным шрифтом с указанными параметрами. Собственно перенос на устройство отображения сводится к наложению созданной поверхности на непосредственно отображаемую поверхность. Также библиотека SDL_ttf содержит средства по преобразованию кодировок символов, определению размеров области, которую будет занимать конкретный текст при его отображении с указанными параметрами, средства выбора шрифтов и задания параметров и т.п. Более подробно с возможностями библиотеки SDL_ttf можно ознакомиться из комментариев в заголовочном файле SDL_ttf.h (на английском языке, непосредственно от разработчика SDL и SDL_ttf).

Для возможности использования в программе функций SDL_ttf необходимо подключить заголовочный файл SDL_ttf.h:

#include "SDL_ttf.h"

Перед обращением к функциям из библиотеки ее необходимо проинициализировать с помощью функции TTF_Init:

extern DECLSPEC int SDLCALL TTF_Init(void);

При успешной инициализации TTF_Init возвращает 0, в случае ошибки –1, что может использоваться для определения возмож-ности продолжения программы. Соответственно для корректного освобождения ресурсов при завершении работы программы необходимо вызвать функцию деинициализации TTF_Quit:

extern DECLSPEC void SDLCALL TTF_Quit(void);

Для работы в программе с конкретным шрифтом конкретного размера необходимо по файлу с данным шрифтом создать необхо-димые структуры данных – «открыть шрифт». Для этого служит функция TTF_OpenFont:

extern DECLSPEC TTF_Font * SDLCALL TTF_OpenFont(const char *file, int ptsize);

43

Первым параметром передается имя файла со шрифтом (либо полное имя, либо относительно текущего каталога, как правило – каталога с исполняемым файлом программы). Независимо от наличия пути к файлу в первом аргументе собственно имя файла не может как-либо сокращаться. Например, если расширение имени файла в данной операционной системе считается отдельным компонентом, а не частью имени после последней точки, оно также должно быть явно указано. Второй параметр – требуемый размер шрифта в пунктах (как в текстовых редакторах). Функция возвращает указатель на динамически размещаемую структуру типа TTF_Font (такой указатель при работе с библиотекой SDL_ttf часто также называют шрифтом по аналогии с указателями на файловый поток), содержащую информацию, необходимую для отображения символов данным шрифтом данного размера. При невозможности создания такой структуры (не найден файл шрифта, в нем отсутствует описание для запрашиваемого размера символов, закончилась память или при иных ошибках) функция возвращает NULL. Когда сведения о данном размере шрифта из указанного файла перестают быть необходимыми, нужно освободить память, выделенную под структуру TTF_font и свя-занные с ней другие структуры данных, для чего вызвать функцию TTF_CloseFont, передав ей в качестве аргумента указатель на структуру TTF_Font. Объявление функции TTF_CloseFont выгля-дит так:

extern DECLSPEC void SDLCALL TTF_CloseFont(TTF_Font *font);

Она корректно обрабатывает значение font, равное NULL, – просто ничего не делая.

Кроме функции OpenFont, в некоторых случаях могут быть полезны функции

TTF_OpenFontIndex, TTF_OpenFontRW, TTF_OpenFontIndexRW, различающиеся своими параметрами, более подходящими для специфических ситуаций. Рекомендуется самостоятельно изучить способы применения данных функций по комментариям в заголовочном файле SDL_ttf.h и исходному тексту определения данных функций – файлу SDL_ttf.c.

Выполнение основной задачи библиотеки SDL_ttf, а именно отображение текста на поверхность, организовано с помощью ряда специальных функций, имена которых начинаются на

TTF_RenderText_, TTF_RenderUTF8_, TTF_RenderUNICODE_, а последнее слово – Solid, Shaded

или Blended. Для примера рассмотрим объявления функций TTF_RenderText_Solid, TTF_RenderUTF8_Solid, TTF_RenderUNICODE_Solid:

extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Solid(TTF_Font *font, const char *text, SDL_Color fg);

extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_Solid(TTF_Font *font, const char *text, SDL_Color fg);

extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_Solid(TTF_Font *font, const Uint16 *text, SDL_Color fg);

Первый параметр всех трех функций – указатель на ранее успешно открытый шрифт требуемого размера, третий параметр – структура SDL_Color, в компонентах r, g и b которой описан тре-буемый цвет шрифта (значениями красной, зеленой и синей сос-тавляющей цвета). Второй параметр задает собственно отобра-жаемый текст в виде указателя на последовательность в памяти кодов отображаемых символов, заканчивающуюся символом с кодом 0. Функция TTF_RenderText_Solid предполагает, что коды символов соответствуют кодировке Latin-1 по принципу «один байт – один символ», функция TTF_RenderUTF8_Solid рассмат-ривает текст как закодированный согласно UTF8, где одному символу соответствует либо один байт, либо последовательность из двух и более байтов. Функция TTF_RenderUNICDOE_Solid предполагает, что все символы представлены непосредственно в кодировке UNICODE по принципу «один символ – одно 16-раз-рядное целое число без знака (двухбайтовое целое без знака)». Фактически два предыдущих варианта сводятся к использованию TTF_RenderUNICDOE_Solid после соответствующего перекоди-рования текста, однако для задания текстовых констант в теле программы чаще всего легче использовать UTF8 внутри обычных строковых констант языка C (не все компиляторы пока еще корректно поддерживают тип wchar и соответствующие строковые константы).

44

Все функции отображения текста возвращают указатель на созданную новую поверхность минимально необходимого размера, содержащую изображение текста или NULL в случае ошибки.

Функции, заканчивающиеся на _Shaded и _Blended, отличаются наборами параметров и качеством отображения текста: оно выше, чем у функций с суффиксом _Solid. Соответственно изменяется и формат возвращаемой поверхности.

Кроме функций отображения целой строки текста, в библиотеке существуют функции отображения отдельного символа, заданного своим кодом в кодировке UNICODE –

TTF_RenderGlyph_Solid, TTF_RenderGlyph_Shaded и TTF_RenderGlyph_Blended. Подроб-ности о параметрах и возвращаемых результатах всех функций отображения текста можно узнать из комментариев в файле SDL_ttf.h.

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

Тот факт, что функции семейства TTF_Render возвращают указатель на вновь создаваемую поверхность, позволяет увели-чивать быстродействие программы за счет увеличения расхода памяти: для многократно повторяющегося текста можно одно-кратно создать содержащую его поверхность, а затем многократно ее отображать, возможно, в разных точках и даже на разных целевых поверхностях. Однако это требует обязательного осво-бождения получаемых поверхностей, как только исчезает необхо-димость в их отдельном сохранении для предотвращения утечки ресурсов. Для этого служит функция SDL_FreeSurface основной библиотеки SDL:

extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface *surface);

Таким образом, процесс вывода традиционного текста «При-вет, Мир!» с отступом от верхнего левого угла окна на 200 пик-селей по горизонтали и 100 пикселей по вертикали шрифтом типа TrueType, расположенным в файле 1.ttf в каталоге с исполняемым файлом программы, яркозеленым цветом размером 14 пунктов с максимальным быстродействием за счет уменьшения качества, будет выглядеть следующим образом (при условии, что среда раз-работки и компилятор поддерживают исходные тексты в кодиров-ке UTF8 и именно в ней был набран текст программы):

/* Фрагмент, отвечающий за вывод текста. Переменная screen – поверхность, соответствующая окну программы. Ей присвоен результат функции

SDL_SetVideoMode*/ if(screen){

SDL_Color text_color; SDL_Rect dest;

SDL_Surface *text_surface = NULL;

TTF_Font * text_font = TTF_OpenFont("1.ttf", 14); if(text_font){

text_color.r = 0; text_color.g = 255; text_color.b = 0; dest.x = 200; dest.y = 100;

text_surface = TTF_RenderUTF8_Solid(text_font, "Привет, Мир!", text_color);

if(text_surface){

SDL_BlitSurface(text_surface, NULL, screen, &dest); SDL_FreeSurface(text_surface);

}

TTF_CloseFont(fnt);

}

}

В данном примере следует обратить внимание на проверку корректности выделения всех динамических ресурсов и их освобождение, а также на то, что после наложения поверхности с

45

текстом на поверхность окна программы собственно поверхность с текстом можно удалить, а изображение в окне программы (точнее, на соответствующей окну поверхности) тем не менее останется до тех пор, пока не будет каким-либо образом замещено другим изображением или до завершения программы. Аналогично можно работать не только с текстовыми константами, но и с перемен-ными данными, располагающимися в некотором буфере – массиве или динамически выделяемой области памяти. При этом, как и при стандартной работе со строками, необходимо обеспечивать при заполнении такого буфера контроль выхода за его пределы и гарантировать наличие ограничивающего нулевого символа в конце строки внутри буфера. Дополнительно необходимо следить за соответствием типа данных в буфере используемой кодировки и соответствующей кодировке версии функции отображения текста. Пример программы с использованием нескольких шрифтов и одного шрифта в нескольких размерах и стилях приведен в приложении 2.

9. Обработка событий средствами библиотеки SDL

Подсистема обработки событий в библиотеке SDL достаточно сложна, поскольку ее основная задача – объединить потребности разработчиков мультимедийных приложений (особенно игр) в быстром отклике на действия пользователя с возможностями сов-ременных многозадачных ОС по обработке событий от множества независимых источников, причем механизмы такой обработки могут существенно различаться на различных платформах. При этом библиотека SDL должна еще сделать логически идентичную обработку событий на различных платформах существенно более простой и единообразной для программиста, чем непосредственное использование возможностей ОС. Для обеспечения поставленных задач библиотека SDL предоставляет ряд механизмов по обработке событий, возникающих «извне» программы, таких как нажатие клавиш клавиатуры, перемещение мыши или нажатие клавиш на ней, изменение размера окна программы или его закрытие средствами ОС и т.д.

Основной способ обработки событий – использование внут-ренней очереди событий программы. Дополнительными спосо-бами являются непосредственный опрос текущего состояния окру-жения с последующей проверкой состояния отдельных устройств ввода: клавиатуры, мыши, джойстиков и т.д. в сочетании с фильт-рацией отдельных типов событий. Еще один дополнительный способ – установка специальных функций фильтров событий, определяющих, должно ли то или иное конкретное событие обрабатываться программой в общем порядке или же отбра-сываться после обработки в данной функции. Активизация всех способов обработки событий средствами библиотеки SDL происходит при инициализации графической подсистемы

SDL,

т.е. при наличии в аргументе функции SDL_Init флага SDL_INIT_VIDEO.

Рассмотрим основной способ обработки событий с исполь-зованием внутренней очереди библиотеки SDL. Для получения событий из очереди в порядке их поступления служат функции

SDL_PollEvent и SDL_WaitEvent:

extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event *event);

extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event *event);

Функция SDL_PollEvent вызывает функцию принудительного обновления очереди событий (однократный опрос возможных источников событий – функция PumpEvents, не имеющая аргументов и не возвращающая никакого значения), затем проверяет, имеется ли в очереди хотя бы одно событие любого типа, ожидающее обработки. Если очередь пуста, функция SDL_PollEvent возвращает 0. Если очередь не пуста и параметр event не равен NULL, то очередное (первое) событие извлекается из очереди и сохраняется в объединении SDL_Event, на которое указывает параметр event, при этом функция SDL_PollEvent возвращает 1. Если очередь не пуста и параметр event равен NULL, то событие остается в очереди без изменений, а функция SDL_PollEvent также возвращает 1.

Функция SDL_WaitEvent отличается тем, что при отсутствии событий в очереди не возвращает управление вызвавшей функции, а ожидает наступления хотя бы одного события, для чего периодически (с интервалом не менее 10 мс, возможно больше, в зависи-мости от особенностей конкретной операционной системы) вызы-вает функцию SDL_PumpEvents с последующим анализом

46

состоя-ния очереди. При появлении в очереди события функция завершает работу и возвращает 1. При обнаружении ошибок в процессе рабо-ты с очередью событий функция возвращает 0. Параметр event обрабатывается аналогично функции SDL_PollEvent.

Важной особенностью функций SDL_PollEvent и SDL_WaitEvent является требование использования их исклю-чительно в том же потоке исполнения (для многопоточных ОС), в котором была вызвана функция установки видеорежима, поскольку в них вызывается функция SDL_PumpEvents, получаю-щая события и внутренние события видеоподсистемы. Для работы с очередью сообщений не только из данного потока, но и из других потоков в программе (при их наличии) служит функция SDL_PeepEvents, прототип и описание параметров (на английском языке) которой находятся в заголовочном файле SDL_events.h. В нем же находятся прототипы и описания большинства прочих функций работы с сообщениями, а также используемых структур данных. При этом для работы с подсистемой обработки событий (как и с остальными подсистемами) подключение к программе данного заголовочного файла (и других заголовочных файлов с прототипами функций подсистем SDL) не требуется. Все необходимые директивы препроцессора будут выполнены при подключении единственного общего заголовочного файла

SDL.h.

Для сохранения каждого полученного сообщения в общем виде и последующего анализа используется объединение типа SDL_Event:

typedef union SDL_Event { Uint8 type;

SDL_ActiveEvent active; SDL_KeyboardEvent key; SDL_MouseMotionEvent motion; SDL_MouseButtonEvent button; SDL_JoyAxisEvent jaxis; SDL_JoyBallEvent jball; SDL_JoyHatEvent jhat; SDL_JoyButtonEvent jbutton; SDL_ResizeEvent resize; SDL_ExposeEvent expose; SDL_QuitEvent quit; SDL_UserEvent user; SDL_SysWMEvent syswm;

} SDL_Event;

Поле type представляет тип события, заданный целым числом без знака, представленным одним байтом. Для символического представления констант, описывающих разные типы событий, в SDL используется перечисление SDL_EventType. Рассмотрим основные типы событий, обозначая их здесь и далее соответ-ствующими константами из данного перечисления (т.е. «событие SDL_KEYDOWN» – событие, при котором поле type объединения SDL_Event имеет значение, равное значению константы SDL_KEYDOWN):

SDL_ACTIVEEVENT – приложение стало активным (с кото-рым работает пользователь) или перестало быть активным;

SDL_KEYDOWN – нажата клавиша на клавиатуре;

SDL_KEYUP – отпущена клавиша на клавиатуре;

SDL_MOUSEMOTION – перемещена мышь; SDL_MOUSEBUTTONDOWN – нажата клавиша мыши;

SDL_MOUSEBUTTONUP – отпущена клавиша мыши;

SDL_QUIT – запрос выхода из программы по действию поль-зователя (например, по нажатию мышью системной кнопки закры-тия окна);

SDL_VIDEORESIZE – пользователь изменил размер окна и требуется изменение видеорежима;

SDL_VIDEOEXPOSE – необходимо перерисовать экран или окно.

Для каждого типа события или группы событий в объеди-нении SDL_Event имеется отдельное поле – структура, содержа-щая тип события (это поле type, имеющее тот же тип и совпадаю-щее в памяти с полем type самого объединения), а также, для неко-торых типов событий, поля параметров, требующихся для обра-ботки таких событий. Рассмотрим подробнее данные структуры для некоторых типов событий или их групп.

47

При обработке событий SDL_KEYDOWN и SDL_KEYUP используется структура

SDL_KeyboardEvent следующего вида:

typedef struct SDL_KeyboardEvent { Uint8 type;

Uint8 which; Uint8 state;

SDL_keysym keysym; } SDL_KeyboardEvent;

Поле type указывает на тип события – SDL_KEYDOWN или SDL_KEYUP. Поле which содержит индекс устройства клавиа-туры, на которой была нажата или отпущена клавиша. Поле state указывает на состояние клавиши – она нажата (SDL_PRESSED) или отпущена (SDL_RELEASED). Поле keysym содержит инфор-мацию о конкретной нажатой клавише и, возможно, о преобра-зовании ее в конкретный символ UNICODE. Оно имеет тип SDL_keysym, объявленный в заголовочном файле SDL_keyboard.h так:

typedef struct SDL_keysym { Uint8 scancode; SDLKey sym;

SDLMod mod; Uint16 unicode;

} SDL_keysym;

Поле scancode содержит зависящий от аппаратуры скан-код клавиши и, как правило, не должно использоваться. Если данная платформа не поддерживает скан-коды, его значение равно нулю. Поле sym содержит значение виртуального кода клавиши, одина-ковое на различных платформах для одинаковых клавиш неза-висимо от фактических скан-кодов или способов ввода. Тип SDLKey – это объявленное в заголовочном файле SDL_keysym.h перечисление, содержащие символьные константы для исполь-зуемых в библиотеке SDL виртуальных кодов клавиш (или, кратко, виртуальных клавиш). Значения части из них совпадают с кодами символов или строчных букв в кодировке ASCII (в диапазоне от 8 до 127), однако общее число различимых клавиш составляет более 300, включая клавиши «международных клавиатур» или специ-фические функциональные клавиши некоторых типов компьютеров. Поле mod содержит состояние модификаторов на момент нажатия клавиши. Тип SDLMod – это объявленное также в заголовочном файле SDL_keysym.h перечисление, содержащее символьные константы для битовых масок состояния клавиш модификаторов. Значение данного поля является объединением (операцией побитового ИЛИ) значений для всех одновременно установленных модификаторов.

Поле unicode, если оно отлично от нуля, содержит результат преобразования нажатия клавиши в конкретный двухбайтовый символ UNICODE, но поскольку подобные преобразования являются достаточно ресурсоемкими, то по умолчанию они отключены. Для управления режимом трансляции виртуальных клавиш в символы UNICODE служит объявленная в SDL_keyboard.h

функция SDL_EnableUNICODE:

extern DECLSPEC int SDLCALL SDL_EnableUNICODE(int enable);

Если значение параметра enable равно 1, разрешается трансля-ция в UNICODE, если равно 0, трансляция запрещается, если равно –1, состояние трансляции остается без изменений. Функция возвращает предыдущее значение состояния трансляции (0 или 1).

При обработке события SDL_VIDEORESIZE используется структура SDL_ResizeEvent:

typedef struct SDL_ResizeEvent { Uint8 type; /**< SDL_VIDEORESIZE */

int

w;

/**<

New

width */

int

h;

/**<

New

height */

} SDL_ResizeEvent;

Поле type указывает на тип события и должно быть равно SDL_VIDEORESIZE. Поле w указывает новую ширину окна, поле h – новую высоту окна. При обнаружении такого события прог-рамма обязана установить новый видеорежим (размер окна) с соответствующей шириной и

48

высотой. Событие возникает только в том случае, если при задании видеорежима (создании графического окна) был установлен флаг «окно изменяемого размера». Если установить точно заданные размеры невозможно, необхо-димо установить ближайшие осмысленные для приложения размеры окна (например, для сохранения пропорций изображения).

Для обработки события SDL_VIDEOEXPOSE используется структура SDL_ExposeEvent, содержащая только поле type, зна-чение которого должно быть равно SDL_VIDEOEXPOSE. При возникновении данного события программа должна перерисовать весь экран или все окно. Если же при этом необходимо только частичное обновление окна, то у соответствующей ему поверхности будет установлено значение компонента clip_rect, отличное от размеров самой поверхности. При этом если производить вывод за пределы данного прямоугольника, то многие функции (напри-мер, SDL_BlitSurface) не изменяют состояние поверхности за его пределами для ускорения работы.

Для обработки события SDL_QUIT используется структура SDL_QuitEvent, содержащая только поле type, значение которого должно быть равно SDL_QUIT. Это событие возникает, если поль-зователь пытается закрыть программу средствами операционной системы (например, используя специальные сочетания клавиш или системную кнопку закрытия окна). При обработке данного собы-тия можно, например, запросить пользователя, действительно ли он хочет завершить работу с программой и следует ли сохранять результаты работы или просто корректно завершить ее с освобож-дением ресурсов и выгрузкой библиотек.

В заголовочном файле SDL_events.h описаны и проком-ментированы также структуры для обработки событий от мыши (причем возможно от нескольких), джойстиков и т.д.

Рассмотрим два примера обработки событий. В обоих приме-рах рассматривается только тот фрагмент функции main, который отвечает за обработку событий и завершение программы, и не рассматривается инициализация видеорежима с созданием окна для вывода графики.

Первый пример для SDL_WaitEvent демонстрирует отобра-жение в окне некоторого статического изображения функцией draw_picture с единственным параметром SDL_Surface* who_draw, определяющим, на какую поверхность производится вывод. Выход из программы осуществляется при наступлении события SDL_QUIT или нажатии клавиши Esc. Также, при необходимости, производится перерисовка изображения при наступлении события

SDL_VIDEOEXPOSE.

/* в соответствующем месте объявляем указатель на поверхность: */

SDL_Surface *screen; SDL_Event event;

/* инициализация библиотеки и установка видеорежима*/ if (!screen)

{

fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError()); SDL_Quit();

return 1; /* Выход с одним кодом ошибки */

}

draw_picture(screen);

/* Принудительное обновление окна программы */

SDL_Flip(screen);

/* цикл ожидания событий */ while(SDL_WaitEvent(&event))

{

if(event.type == SDL_QUIT || (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))

{

SDL_Quit();

return 0; /* пусть 0 – нормальное завершение*/

}

if(event.type == SDL_VIDEOEXPOSE) draw_picture(screen);

}

fprintf(stderr,"WaitEvent failed: %s\n",SDL_GetError()); SDL_Quit();

return 2; /* Выход с другим кодом ошибки */

49

Второй пример для SDL_PollEvent – рисование прямоуголь-ника, перемещающегося по экрану вверх-вниз при нажатии на клавиатуре стрелок управления курсором, как отдельных, так и на цифровой клавиатуре. Если же никаких действий не происходит, он сам перемещается слева направо и обратно. Но пределы окна он покинуть не может: при перемещении по вертикали он упирается в край, а при перемещении по горизонтали «ударяется» о край и изменяет направление движения.

/* в соответствующем месте объявляем указатель на поверхность: */

SDL_Surface *screen; SDL_Event event;

SDL_Rect r; /* сам прямоугольник*/

SDL_Rect r_new; /* новое положение прямоугольника*/ Sint16 leftright = 1; /* слева направо = 1, справа налево =-1 */

Sint16 max_x, max_y;

int nextstep = 1; /* для цикла обработки сообщений */ /* инициализация библиотеки и установка видеорежима */ if (!screen)

{

fprintf(stderr,"SDL mode failed: %s\n",SDL_GetError()); SDL_Quit();

return 1; /* Выход с одним кодом ошибки */

}

/* В объявленных ранее переменных Sint16 max_x и Sint16 max_y записаны фактическая ширина и высота области, в которой перемещается прямоугольник после установки видеорежима – фрагмент опущен */

/* Первоначальное рисование по центру экрана синего прямоугольника с шириной 40 и высотой 20 пикселей */

r.x = max_x / 2 - 20; r.y = max_y / 2 - 10; r.w = 40;

r.h = 20; r_new = r;

SDL_FillRect(screen, &r, 0x000000FF); /* ярко-синий */

/* цикл перерисовки и обработки событий */ while(nextstep)

{

if(SDL_PollEvent(&event))

{

if(event.type == SDL_QUIT ||

( event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_ESCAPE))

nextstep = 0; /* Выход */ if(event.type == SDL_KEYDOWN &&

event.key.keysym.sym == SDLK_DOWN) { /* Вниз*/

r_new.y = (r.y + r.h) < max_y ? r.y +1 : r.y;

}

if(event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_UP)

{ /* Вверх*/

r_new.y = r.y > 0 ? r.y -1 : r.y;

}

}

/* расчет перемещения по горизонтали */ r_new.x = r.x + 1*leftright;

if(r_new.x < 0 || r_new.x + r.w > max_x)

{/* отскок от стенки */ leftright = -leftright;

}

/* собственно перерисовка: */

SDL_LockSurface(screen);

SDL_FillRect(screen, &r, 0x00000000); /* стерли черным */ r = r_new; /* используем новые координаты */

50

Соседние файлы в предмете Программирование