Шуман Х. - Python для детей - 2019. # Startwerte festlegen Red (255,0,0)
Скачать 5.95 Mb.
|
Глава Создание анимации 12 242 Рис. 12.12. Создаем переменную при объявлении класса Есть еще одна нерешенная проблема. Она возникает, когда ты нажимаешь кнопку Движение несколько раз. Факт, что персонаж просто продолжает движение, не проблема, но в конце концов он просто исчезает. Это можно предотвратить, отслеживая координаты фигу- ры. Для этого нужно знать текущее положение фигуры. Ты можешь получить его с помощью Canvas-метода coords(). Он возвращает координаты объекта в четырех значениях от- носительно вершин слева и справа. Нам нужна только одна строка: self.x, self.y = self.Graphic.coords(self.Figure) Точнее, нам нужен лишь self.x, потому что наша фигура движется только горизонтально. Нужно сделать так, чтобы фигура остановилась около правого края окна, оставаясь при этом полностью видимой: if self.x <= bis+100 : Здесь в ход идет «улучшенная» версия метода moveImage() (⇒ mplayer.py): def moveImage(self, von, bis) : for pos in range(von, bis, 10) : if self.PictureNr == 2 : self.PictureNr = 6 else : self.PictureNr = 2 self.Graphic.itemconfig(self.Figure, \ image=self.Picture[self.PictureNr]) self.x, self.y = self.Graphic.coords(self.Figure) if self.x <= bis+100 : Вопрос... 243 self.Graphic.move(self.Figure, 10, 0) self.Graphic.update() self.Graphic.after(100) self.Graphic.itemconfig(self.Figure, image=self.Picture[1]) Теперь фигура может перемещаться только в том случае, если ее позиция находится в диапазоне допустимых значе- ний. В противном случае движение прекращается. ¾ Открой определение класса и измени его код. Затем убедись, что вместо класса mplayer импортируется класс mplayerX , и запусти программу. Программа работает так, как должно? У меня теперь появляются сообщения об ошибках или предупреждения, только если в процессе работы програм- мы я не вовремя нажимаю кнопки, особенно Сокрытие. Но программа не завершает работу, поэтому проблема может быть легко решена. Подведение итогов Вот мы и добрались до конца этой главы. Ты добавил изо- бражения, а также анимировал фигуру и заставил ее дви- гаться. Давай посмотрим, что ты узнал о Python и tkinter: PhotoImage() Класс для загрузки файлов изображений create_Image() Создает объект изображения itemconfig() Принимает новое изображение (изменяет содержимое объекта изображения) update() Обновляет содержимое окна move() Перемещает объекты изображений after() Приостанавливает работу программы (собственный метод в tkinter) coords() Определяет (или задает) положение графического объекта delete() Удаляет объект (повторяюсь) file= Присваивает имя, например открываемого файла image() Изображение (из файла) Вопрос... 1. Как добавить изображение на холст? Глава Создание анимации 12 244 ...и несколько задач 1. В первом примере этой главы смени класс Circle на Square , и пусть квадратный объект блуждает по экрану. 2. В последней версии проекта перемести персонажа вле- во и назад вправо. 245 13 Игра с насекомыми Существует множество возможностей программирования игр на Python. Нам даже не нужен сложный внешний мо- дуль, чтобы превратить простое Python-приложение в на- стоящую графическую игру. Задачи из этой главы могут быть решены даже с помощью модуля tkinter. Но иног- да подобный подход недостаточно элегантен, к тому же tkinter довольно ограничен, когда дело касается игрового программирования. Вот почему сейчас мы познакомимся с новым пакетом. Итак, в этой главе ты узнаешь: что такое пакет pygame; кое-что о спрайтах; как управлять объектами с помощью клавиш; о вращении объектов; об управлении границами поля. Начало работы с Pygame Пакет, который будет обсуждаться в этой главе, называет- ся Pygame. Он состоит из нескольких модулей и основан на библиотеке для программирования игр под названием SDL. Эта аббревиатура расшифровывается как «Simple DirectMe dia Layer» и переводится как «Простой мультимедийный Глава Игра с насекомыми 13 246 слой». Эта библиотека отвечает за управление графикой, звуком, клавиатурой и мышью. Пакет SDL изначально раз- рабатывался для других языков программирования, таких как C и C ++, а Pygame предлагает соответствующие возмож- ности и в Python. Загрузка и установка этого пакета продемонстрированы в приложении A. Для моих проектов я поместил все моду- ли в каталоге C:\Python во вложенные папки include и Lib. Необходимые модули должны импортироваться в соответ- ствующую программу. ¾ Если у тебя уже установлен пакет pygame, создай новый пустой файл. Укажи в нем первую строку: import pygame Это необходимо, чтобы Pygame инициализировался со всеми его модулями. Далее нам нужно создать окно: pygame.display.set_mode((600, 400)) Это выполняется с помощью метода set_mode(), который от- носится к классу display. Двойные круглые скобки обязательны, поскольку метод set_ mode() принимает значения не как два отдельных параметра, а как связанные значения в качестве параметра. Указанных строк достаточно, чтобы создать окно. Однако программа еще не закончена. Для завершения необходима последняя строка: pygame.quit() Если ты запустишь эту программу, на мгновение откроется окно и тут же исчезнет. Для решения проблемы нам нуж- но что-то, способное заморозить окно, пока мы не закроем его сами. Для этого мы используем следующий цикл: running = True while running : for event in pygame.event.get() : if event.type == pygame.QUIT : running = False Начало работы с Pygame 247 Здесь вновь используется логическая переменная (или переменная переключения). Ранее такая переменная ис- пользовалась в программе-лотерее. Напомню, что логи- ческие переменные принимают только значения True или False , поэтому переключаются при смене значения. Логи- ческие переменные также хорошо подходят для создания условий. В моем примере в логической переменной используется значение true. Пока оно остается таким, выполняется цикл while , внутри которого вложен еще один цикл, for: for event in pygame.event.get() : Каждое возникающее событие последовательно извлекает- ся из цепочки событий, и проверяется, является ли оно со- бытием pygame.QUIT. Оно означает: окно Pygame должно быть закрыто: if event.type == pygame.QUIT : running = False Если это событие обнаруживается, присваивается значение False , а цикл while больше не выполняется. Только тогда вы- полняется pygame.quit(), программа завершает работу. Если ты считаешь, что этот цикл похож на mainloop() из модуля tkinter , то ты прав. Разница в том, что хотя нам пришлось само- стоятельно написать код этого цикла, мы можем определить, что находится в данном цикле. Теперь мы соберем все вместе и создадим небольшую про- мо-программу (⇒ game0.py): # Импорт Pygame import pygame # Запуск Pygame, создание окна pygame.init() pygame.display.set_mode((600, 400)) # Цикл событий running = True while running : for event in pygame.event.get() : Глава Игра с насекомыми 13 248 if event.type == pygame.QUIT : running = False # Завершение Pygame pygame.quit() ¾ Введи весь показанный код в своем файле, а затем за- пусти программу. Рис. 13.1.Окно pygame В отличие от tkinter, окно окрашено в черный цвет. Его, разумеется, можно изменить. Как и в случае с tkinter, ты можешь отображать в этом окне графику, но возможности этим не исчерпываются. Ты можешь запускать настоящие игры. И мы это сейчас рассмотрим. Создаем в окне объект Начнем с простого. Давай создадим круг, как мы это дела- ли с tkinter. Программа выглядит следующим образом (⇒ game1.py): # Импорт Pygame import pygame Создаем в окне объект 249 # Определение цветов Red = (255,0,0) Green = (0,255,0) # Запуск Pygame, создание окна pygame.init() Window = pygame.display.set_mode((600, 400)) Window.fill(Green) # Цикл событий running = True while running : for event in pygame.event.get() : if event.type == pygame.QUIT : running = False # Рисование круга Circle = pygame.draw.circle(Window, Red, (300, 200), 100) pygame.display.update() # Завершение Pygame pygame.quit() Чтобы использовать оттенки цвета в Pygame, нам нуж- но указывать их значения по модели RGB, как показано в табл. 13.1. Таблица 13.1. Примеры цветов и их значения Red = (255,0,0) Красный Green = (0,255,0) Зеленый Blue = (0,0,255) Синий Cyan = (0,255,255) Бирюзовый Magenta = (255,0 255) Фиолетовый Yellow = (255,255,0) Желтый White = (255,255,255) Белый Black = (0,0,0) Черный Любой оттенок получается указанием значений насыщен- ности трех основных цветов, красного, зеленого и синего. Допускаются значения в диапазоне от 0 до 255. Так можно создать любой из многих миллионов оттенков. Метод display.set_mode() имеет возвращаемое значение, которое я присвоил переменной Window. Также мы создаем объект типа Surface. Это своего рода контейнер для получе- ния и отображения изображений (аналогично компоненту Canvas в tkinter). Вместо черного я заполню окно зеленым цветом: Глава Игра с насекомыми 13 250 Window.fill(Green) Представление объекта содержится в цикле while. Сначала рисуется круг: pygame.draw.circle(Window, Red, (300, 200), 100) В данном примере параметры – это окно, в котором нужно создать круг, его цвет, центральная точка (пара значений) и радиус. Затем этот метод нужно вызвать, иначе ничего не получится: pygame.display.update() Метод update() отвечает за обновление содержимого окна. Чтобы это происходило постоянно, его вызывает цикл while. Думаю, сейчас стоит упомянуть о рендеринге: когда отображается графический объект, он рендерится. Объектом или сценой игры изначально является только (невидимая) модель, а при рендерин- ге она становится видна. Скорость рендеринга зависит от возмож- ностей графической подсистемы компьютера. Повторный вызов метода обновления в цикле необходим, так как сцена может постоянно меняться и необходимо отображать но- вое содержимое. ¾ Теперь проверь свою программу и запусти ее (рис. 13.2). Рис. 13.2.Вид запущенной программы Насекомое в качестве персонажа 251 Разумеется, Pygame способен рисовать и другие объекты, не только круги. Ты можешь попробовать, заменив слово cir cle одним из следующих значений: pygame.draw.rect(Window, Blue, (100, 50, 400, 100)) pygame.draw.ellipse(Window, Yellow, (100, 250, 400, 100)) pygame.draw.line(Window, Black, (50,50), (550,350), 5) Так ты можешь рисовать прямоугольники, эллипсы и ли- нии. Параметры перечислены в табл. 13.2 (включая круг). Таблица 13.2. Параметры методов для разных кругов Метод Параметры line() Окно, цвет, (начальная точка, конечная точка), толщина линии rect() Окно, цвет, (x, y, ширина, высота), толщина линии ellipse() Окно, цвет, (х, у, ширина, высота), толщина линии circle() Окно, цвет, (х, у, радиус, толщина линии) Параметр «толщина линии» можно не указывать. В таком случае фигуры полностью заполняются цветом. Если ука- зать значение толщины линии, например 1, будет нарисо- вана только цветная граница фигуры без заливки. Если ты взглянешь на окно программы с кругом (или другой фигурой), то увидишь основные игровые элементы: игровое поле и фигуру. Объект window – это игровое поле, на котором может выполняться все игровое действие. А объект Circle – это игровой персонаж, только очень примитивный: Circle = pygame.draw.circle(Window, Red, (300, 200), 100) То есть можно сказать, что ты можешь поиграть с кругом (объектом Circle). Объект становится настоящим игровым персонажем, когда начинает двигаться. К этому мы вер- немся чуть позже. Насекомое в качестве персонажа Прежде всего мы должны заменить круг чем-то более «сим- патичным» (и поменьше размером). Для этого в Pygame есть класс Sprite. Графический объект этого типа предоставляет собой прямоугольную область, которая изначально пуста. Ты можешь поместить в нее любую графику и даже загру- зить изображение. Глава Игра с насекомыми 13 252 Спрайт подобен плитке, которая изначально прозрачна. Ты мо- жешь «приклеить» спрайт к шаблону в загруженном графическом файле. Так ты получишь так называемую текстуру. Текстура также может изображать, например, животное или чело- века (или его часть, например лицо). Лучший способ определить класс для нашего нового персо- нажа показан ниже (⇒ game2.py): class Player(pg.sprite.Sprite) : def __init__(self) : super().__init__() self.image = pg.image.load("Bilder\Insekt1.png") Этот класс получен из спрайта Pygame. В скобках обычно указывается строка pygame.sprite.Sprite, но я воспользовал- ся возможностью сократить имя модуля. Если ты тоже так хочешь поступить, измени строку импор- та следующим образом: import pygame as pg Почему бы нам просто не написать инструкцию импорта, которую мы знаем по tkinter? from pygame import * Разумеется, эта инструкция работает, но такой подход не всегда целесообразен. При разработке сложных программ со многими импортируемыми модулями (а игры могут быть действительно большими) всегда полезно знать, какой метод к какому модулю относится. Нередко существуют одинаковые методы, которые нужно уметь отличать. Поэтому гейм-дизайнеры обычно реко- мендуют импортировать Pygame так: import pygame Чтобы ты мог сокращать часто используемые (длинные) слова, ты можешь воспользоваться строкой import pygame as pg И ты увидишь, насколько этот подход удобен, потому что Pygame в основном используется для программирования игр. Насекомое в качестве персонажа 253 Вернемся к классу Player. На данный момент есть только один метод для инициализации спрайта. Во-первых, он ссылается на тот же метод родительского класса: super().__init__() Для этого используется вспомогательное слово super. Так ты передашь спрайту все характеристики от Pygame. Добавь- те к ним собственные, например ссылку на графический файл, которой спрайт должен быть «заполнен»: self.image = pg.image.load("Bilder\Insekt1.png") Метод image.load() загружает файл изображения, располо- женный в подпапке Bilder. Ты уже знаком с похожим мето- дом, изученным в главах про tkinter. Разумеется, изображение с указанным именем должно на- ходиться в папке, сообщение об ошибке не появится, если файл не будет найден. Я выбрал изображение жука, которо- го позже заставлю ползать по игровому полю. ¾ Прежде всего найди подходящее изображение и скопи- руй его в папку Bilder своего Pygame-проекта. Ты должен знать, что Pygame поддерживает больше форма- тов изображений, чем tkinter. Здесь можно не ограничи- ваться GIF, и поэтому я рекомендую формат PNG, который позволяет сделать фон рисунка прозрачным. Как сделать фон прозрачным? Если изображение сохранено в формате, отличном от PNG, тебе нужно открыть его в графиче- ском редакторе, например paint.net (бесплатно) или Photoshop (который наверняка у тебя установлен) и сохранить в нем рисунок в виде файла формата PNG. В программе paint.net выбери инструмент «Волшебная палочка» и щелкни мышью по фону, чтобы его область была выделена цве- том и «бегущими муравьями». Затем нажми клавишу Del, и фон станет клетчатым, обозначая прозрачность (рис. 13.3). Глава Игра с насекомыми 13 254 Рис. 13.3. Жук на белом фоне (слева) и прозрачном (справа) В программе Photoshop процесс аналогичен: инструмент тоже на- зывается «Волшебная палочка», и щелчка мышью по фону и на- жатия клавиши Del достаточно, чтобы сделать фон прозрачным. Ты также можешь использовать файлы примеров из папки, до- ступной по адресу dmkpress.com (рис. 13.4). Рис. 13.4. Рисунки жуков для проекта Все необходимые файлы расположены в папке bilder. После того как класс Player готов, мы можем сразу его ис- пользовать. Итак, давай создадим объект прямо сейчас: Figure = Player() Как спрайт отобразить в окне? Взгляни на следующую строку: Window.blit(Figure.image, (250, 150)) Последний параметр используется для указания позиции нашего будущего игрового персонажа. Первый принимает изображение спрайта, которое будет отображаться. Насекомое в качестве персонажа 255 В этом примере персонаж, он же жук, располагается в цент- ре окна. Думаю, тебе понятно, что вызов метода blit нахо- дится в цикле while. Перестрой свою программу в соответствии со следующим листингом (⇒ game2.py): # Pygame-графика import pygame as pg # Класс Player class Player(pg.sprite.Sprite) : def __init__(self) : super().__init__() self.image = pg.image.load("Bilder\Insekt1.png") # Определение цветов Green = (0,255,0) # Запуск Pygame, создание игры pg.init() Window = pg.display.set_mode((600, 400)) Window.fill(Green) # Создание персонажа Figure = Player() # Цикл событий running = True while running : for event in pg.event.get() : if event.type == pg.QUIT : running = False # Позиционирование спрайта в окне Window.blit(Figure.image, (250, 150)) pg.display.update() # Завершение Pygame pg.quit() Запусти программу, и ты увидишь спрайт в центре окна (рис. 13.5). Глава Игра с насекомыми 13 256 Рис. 13.5.Наш милый жучок Как видишь, фон изображения жука прозрачен. Если бы это было не так, тогда ты увидел бы белый фон, как показано на рис. 13.6 (слева). Рис. 13.6. Изображение жука с непрозрачным фоном (слева) и прозрачным (справа) Слева показан жук из файла формата GIF или JPG, а справа – из PNG. Управление персонажем Зеленый лужок – это игровое поле, а жук – игровой пер- сонаж. Мы должны сейчас как-то заставить его двигаться. Лучший способ управления – использовать клавиши со стрелками. Управление персонажем 257 Для этого нам нужно создать следующее событие в цикле for : if event.type == pg.KEYDOWN : Теперь важно сопоставить действие с нажатой клавишей (в коде выше – «Стрелка вниз» – Keydown). Но что именно должно произойти, если ты нажмешь одну из клавиш со стрелками? Жук (т. е. спрайт) должен изменить свое поло- жение. Во-первых, нам понадобятся две переменные, кото- рые отвечают за позицию персонажа. Для этого мы расши- рим определение класса Player (⇒ buggy1): class Player(pg.sprite.Sprite) : def __init__(self, xPos=0, yPos=0) : super().__init__() self.image = pg.image.load("Bilder\Insekt1.png") self.x, self.y = xPos, yPos Я переименовал проект в buggy в честь английского слова «баг», т. е. «ошибка». Чтобы создать объект Player, воспользуемся уже знакомым способом: Figure = Player() Затем атрибуты объекта Player устанавливаем равными 0. Параметры xPos и yPos опциональны, ты можешь их ис- пользовать, а потом переданные значения передаются как положение по осям x и y. В нашем случае мы используем следующую строку кода: Figure = Player(250, 150) Теперь атрибуты имеют новые значения. И они увеличи- ваются или уменьшаются в зависимости от нажатой кла- виши: if event.key == pg.K_LEFT : Figure.x -= 5 if event.key == pg.K_RIGHT : Figure.x += 5 if event.key == pg.K_UP : |