Веселая сторона Python'a. Юзаем библиотеку PyGame на примере игры «Лестница»Лейтенант Роман «presidentua» Хоменко (http://tutamc.com) Игры - одно из лучших изобретений человечества. В них все мечты сбываются, в них мы рыцари, короли, боги! За десятки лет существования игростроя сценаристы придумали для нас множество миров, но порой так хочется создать что-то свое – тот мир, где будут царить только твои правила. В рамках этой статьи я постараюсь научить тебя использовать волшебную палочку для создания игр - PyGame. Год назад я познакомился с PyGame и влюбился в него с первых строк документации. Сразу же я вспомнил все свои мучения, связанные с программированием на С++ в связке с DirectX, вспомнил, как все жутко тормозило, и я мучился над оптимизацией… а оно все равно тормозило. Вспомнил, как для элементарных вещей нужно было писать десятки строк кода. PyGame берет все заботы на себя. Нам остается лишь написать саму игру, а не думать, к примеру, как правильно загрузить картинку. Если ты не собираешься писать игры, то можешь заюзать PyGame для создания оригинальных интерфейсов в своих прогах или визуализации какой-либо информации. Колобок на лестницеPyGame - это кроссплатформенный набор модулей, построенный поверх SDL-библиотеки и предназначенный для написания видеоигр. Он включает в себя библиотеки для работы с графикой и звуком, реализованные с использованием язык Python. Автор этого чуда - Pete Shinners. Чтобы все сказанное о PyGame не было лишь теорией, разберем написание простой игры «Лестница». Выбор был обусловлен словами редактора рубрики. Он прямо сказал, что или я напишу об этой игре, или он не отдаст мне ящик минералки, который проспорил на последней «научной конференции» в баре. Однако, наша «Лестница» уже не будет текстовой игрушкой. У нас появится хакерский Колобок, который должен будет пройти снизу вверх по лестницам к двери. А сверху вниз будут падать камни, так и норовящие подвергнуть нашего Колобка кровавому прессингу. Сперва я хотел рассказать тебе о каждой строчке в этой игре, но, к сожалению, игруха получилась аж на 300 строк, поэтому я поведаю только основные моменты. Они позволят тебе понять принципы работы с PyGame, а полный код игры ждет тебя на диске. Погружение, или Базовые знанияУстановка PyGame в Windows проходит в несколько кликов с инсталяхи, которую можно взять с http://www.pygame.org или с нашего диска. Для Linux PyGame находится в репозитариях. Я же, как ламер, пишу под виндой и юзаю версию Python 2.5 и соответствующую ей версию библиотеки (поскольку так советует поступать сам автор библиотеки из соображений скорости). Но хватит лирики, давай скорее перейдем к кодингу. Как всегда в Python'e, использование PyGame начинается с подключения библиотек:
Замечу, что pygame.locals мы полностью включили в область глобальной видимости, потому что это рекомендуют на официальном сайте. Именно там собраны основные константы, к которым мы будем часто обращаться, например, константы клавиш клавиатуры. Теперь проинициализируем PyGame и создадим окно размером 640x480 и с заглавием '][акер':
Посредством этого небольшого куска кода мы создали не только окно, но и главную поверхность (surface) для рисования, которую в любой точке программы можно получить командой pygame.display.get_surface(). Для самого же рисования реализовано множество функций. Они описаны в документации на официальном сайте. В качестве примера разберем рисование линии:
Здесь window – поверхность, на которой рисуется линия; затем идет цвет линии в формате (R,G,B), начальные и конечные точки линии в формате (X,Y), и, наконец, ширина линии. Кстати, эта линия будет не сглажена! Чтобы нарисовать сглаженную линию, нужно line изменить на aaline. Но это все не очень важно, ведь красивую графику таким образом не нарисуешь. Нам придется подгружать картинки с файлов и их отображать, но об этом позже. Если мы попробуем сейчас нарисовать линию на главной поверхности, то все равно ничего не увидим - PyGame автоматически использует двойную буферизацию, и для того, чтобы все это хозяйство перебросить с главной поверхности на поверхность, которая проецируется на видеокарту, нужно вызвать pygame.display.flip().
У этого тестового примера есть небольшой минус: он не обрабатывает события, а ведь нам нужно хотя бы научить его закрываться при нажатии на «крестик». Для получения событий существует функция
Теперь приложение нормально отображается, не кажется зависшим и даже закрывается :), потому что мы принимаем события и корректно их обрабатываем. Среди типов событий есть и события, связанные с клавишами – например, KEYDOWN и KEYUP. И если мы захотим, чтобы наше приложение закрывалось еще и при нажатии клавишу Esc, то можно добавить условие:
Тут мы видим, что нажатая клавиша сохраняется в event.key, а мы сравниваем ее с константой клавиши Esc и должным образом реагируем. Все эти константы перечислены в документации, правда, мне почему-то не удалось найти константу на Enter, поэтому в этой ситуации я сравнивал key с числом 13 - кодом Enter'a. Начало гейм-кодинга, или АрхитектураОвладев этими базовыми знаниями, мы готовы к гейм-кодингу. Начнем с самого трудного - архитектуры, ведь при неправильно выбранной архитектуре разработка превращается в ад, и последующие изменения в каждой строчке кода можно приравнять к принудительному прослушиванию песни Димы Билана. Архитектура «Лестницы» полностью основана на объектах. Основной объект - general порожден классом General. Он проводит первоначальную инициализацию и впоследствии обрабатывает глобальные события.
Как видно из вышеуказанного кода, в конструкторе он создает окно и обрабатывает события, ведущие к переходу к локации exit_location.
Локации имеют конструктор, функцию по обработке событий и функцию по прорисовке экрана. Все выглядит достаточно запутано, но давай посмотрим на всю программу целиком (без самих объектов):
Как можно заметить, сначала создается general объект. Далее создаются три локации: start_location - показывает юзеру приглашение начать игру, game_location - непосредственно игра, exit_location - показывает набранный уровень. Дальше в переменную general.location сохраняется стартовая локация, то есть она как бы становится активной. Затем в бесконечном цикле мы получаем список событий и передаем их как текущей локации, так и на глобальную обработку. Затем вызывается метод draw активной локации и прорисовывает экран. Удачно выбранная архитектура дает возможность разделить код, относящий к разным локациям. Но я пропустил объяснение строчки clock.tick(30). Это очень важная часть, которая не дает 4-ядерному CoreDuo проиграть игру еще до того, как пользователь что-то успеет увидеть :). Строчка делает FPS статическим и равным 30. Иначе говоря, она оценивает разницу между последними вызовами и следит, чтобы эта разница была равна 1/30 секунды. Конечно, современные игры обычно имеют динамический FPS, но это несколько сложнее в реализации, да и в аркадах бессмысленно. Посмотрим, как реализована первая локация:
В конструкторе вызывается функция pygame.image.load('f.png'), которая считывает рисунок, переданный в параметре, и возвращает поверхность с ним. Реализация функции draw также состоит из одной функции главной поверхности. Функция blit копирует на свою поверхность (передана в первом параметре), начиная с позиции, которая передается во втором параметре. Обработка событий реагирует лишь на нажатия <Enter>, после чего выставит локацию игры как текущую. Выбранная архитектура позволяет достаточно просто разбрасывать код в отдельные обособленные объекты. Локация Exit_location сделана аналогично этой, и мы не будем ее рассматривать (изучай код на диске). Но переходить к Game_location нам рановато. Мы еще ничего не знаем о спрайтах. СпрайтыСпрайт - графический объект в игре, который может перемещаться по игровому пространству. Это важнейшая деталь в 2D-играх, хотя замечу, что и в 3D они также используются, например, при рисовании далеких объектов (при приближении они рисуются полигонами) и в процессе создания некоторых спецэффектов. То есть, спрайт - это объект, который содержит картинку или серию картинок (для анимации спрайта), координаты его нахождения и другие свойства, а также - логику движения спрайта и пр. В PyGame спрайты нужно наследовать от pygame.sprite.Sprite. Рассмотрим спрайт Камень:
Итак, объект содержит в себе некоторые переменные, необходимые нам для логики - а именно, скорость и направление движения. Также здесь есть конструктор, подгружающий изображения. На процесс загрузки изображения придется обратить пристальное внимание - сначала мы загружаем картинку, а потом в ней, с помощью функции set_colorkey, заменяем все пиксели, одинаковые по цвету с пикселем из левого верхнего угла на прозрачный. Конечно, это выглядит несколько дико. На практике я советую использовать встроенную в png прозрачность, изменив convert() на convert_alpha(). Дело в том, что во время написания проги у меня не было денег на покупку лицензионного фотошопа :), поэтому картинки я рисовал в Paint, а там прозрачности я не обнаружил. Красота спрайтов особенно проявляется при их количестве. Для их удобного объединения существует класс pygame.sprite.Group.
Если нам нужно, чтобы камни немного продвинулись, вызовем kamens.update(args), и эта функция вызовет функцию update для каждого спрайта из группы. Для прорисовки всех спрайтов существует функция draw, – она принимает параметр «поверхность», на которой нужно прорисовать спрайты:
Теперь мы готовы посмотреть на главную локацию - Game_location, а точнее - на функцию draw:
В начале этой функции на главную поверхность отображается фоновое изображение, затем - рисуется спрайт колобка. Далее, в группе спрайтов «Камни», появляются движения, которые рисуются на экране. Наконец, последние две строчки наиболее интересны, ведь с помощью одной простой функции pygame.sprite.spritecollide() мы проверяем, пересекся ли колобок с каким-то камнем. Эта функция возвращает булевый список, и если произошло столкновение, то мы изменяем локацию на exit_location. Обработка клавишНа этом повествование можно было бы завершить, но я упустил два интересных момента. Сначала рассмотрим, как двигается колобок, ведь он не принимает входящих событий о нажатии клавиш! Объект колобка использует функцию pygame.key.get_pressed(), которая возвращает булевый список с состоянием нажатия каждой клавиши. Мы потом можем его проверить, используя константы. «Движущий» кусок кода колобка выглядит так:
МузыкаИгра без музыки - это не игра. К тому же, «поставить пластиночку» можно очень просто:
Эти функции загружают mp3-файл и начинают его проигрывание. Далее мы можем управлять процессом проигрывания. Например, пауза и снятие с паузы будут выглядеть так: Кстати, музыка не будет играть, если в mp3-шном файле есть теги второй версии. И это баг, а не фича. Game overНа этом ознакомление с PyGame можно считать завершенным. Осталось лишь зайти на диск, найти там игру и поиграть в нее. Удачи тебе в создании собственных миров! История PyGame. Рассказ создателяИдея проекта PyGame родилась летом 2000 года. Будучи С-программистом с большим стажем, я почти одновременно обнаружил для себя Python и SDL. Библиотека SDL (Simple Directmedia Library) была создана Sam Lantinga как кросплатформенная С-библиотека для контроля мультимедиа. Она использовалась в сотнях коммерческих и бесплатных игр. Я был под впечатлением от нее и понял, что, если совместить Python и SDL, получится очень интересная вещь. Работу над PyGame я начал в октябре 2000 года, и через 6 месяцев была выпущена версия 1.0. Вспоминания Александра Лозовского (из статьи «Шаг в прошлое», http://www.xakep.ru/magazine/xs/064)В далеком 1989 году я впервые увидел компьютер. Мне купили «Микрошу» — суперсоветскую ЭВМ, которая не может существовать без телевизора и магнитолы. На многократно зажеванной и разглаженной пленке кассеты МК60, помимо кучи полезных программ, были и игры, а среди них — та самая «Лестница». Идея ее проста: человечек идет снизу вверх по лабиринту (точнее, даже не по лабиринту, а просто по уровням, соединенным лестницами, причем игровое поле открывается взору полностью). Наверху же игрового поля находится один (несколько) источников, из которых вываливаются скачущие камни. Камни (в виде символа «0») катятся вниз по уровням и лестницам, подпрыгивают и норовят раздавить игрока. Цель — долезть до верха. Уровней, причем самого разного дизайна, было куча. Я, к примеру, дошел до 14-го и нисколько не растерял игровой интерес :). CDНа диске смотри игруху со всеми исходниками. WWW
|