Шуман Х. - Python для детей - 2019. # Startwerte festlegen Red (255,0,0)
Скачать 5.95 Mb.
|
Глава Пора развлекаться 16 308 цветом. Разумеется, цвет также должен быть определен заранее: Blue = (0,0,255) ¾ Дополни исходный код своей программы Dodger кодом двух функций и связанных с ними переменных, как по- казано на рис. 16.1. Рис. 16.1.Добавленные инструкции Теперь давай посмотрим, где мы можем привнести новые функции в игру. С одной стороны, когда игрок уклонился, счет очков должен быть увеличен: if not Figure.isHit : Ball.move(-1, 0) if Ball.controlRestart(xMax-50, yMax/2) : setScore(1) Если мяч в персонажа не попал, мяч может двигаться даль- ше и запускаться снова, если находится слева, то есть в об- ласти игрока. Напомню, что метод controlRestart() имеет возвращаемое значение. Потому что мы можем воспользо- ваться этим. Игровой счет 309 Если мяч был успешно запущен и не попал в игрока – долж- ны увеличиться очки, которые сразу отображаются. Если хочешь, ты можешь быть более щедрым и начислять, на- пример, по десять очков. Я скупой, со мной игрок получает только одно очко за каждое уклонение. Чтобы ты мог видеть область со счетом, нам нужен еще один метод blit: Window.blit(Text, (xMax/2, 10)) Я разместил эту инструкцию первой, перед другими мето- дами blit (рис. 16.2). Рис. 16.2.Добавление кода, отвечающего за счет Если ты внимательно посмотришь на рисунок, то увидишь, что я добавил текст, уведомляющий об окончании игры. Эта строка находится непосредственно под той, в которой isHit получает значение True: if not Figure.dodge(Ball.y, yMax/2) : Figure.isHit = True showMessage("Игра окончена", Red) Если в объект Player попал мяч, вместо счета отображается текст «Игра окончена». ¾ Дополни исходный код, запусти программу и набирай очки (⇒ dodge5.py). Глава Пора развлекаться 16 310 Класс Game Теперь исходный код нашего «Ловкача» значительно уве- личился, хотя мы сохранили инструкции для игрока и мяча в разные файлы. Давай посмотрим, нет ли еще чего-нибудь лишнего, чтобы уменьшить размер основной программы. Прежде всего я думаю обо всех функциях, которые мы здесь объявили. А что, если мы создадим новый класс и превратим эти функции в методы данного класса? Давай попробуем. ¾ Создай новый файл и присвой ему имя game.py (это мой вариант). В исходном коде dodger5.py выдели код между двумя глобальными переменными и последней функ- цией getTime() (рис. 16.3). Рис. 16.3.Выделенный фрагмент кода, который станет классом ¾ Скопируй код в новый файл, а затем удали его из исход- ного файла (или вырежи и вставь). Класс Game 311 Я назвал новый класс Game, потому что там объявляются ме- тоды, касающиеся игры. Ты можешь постепенно расширять класс, когда придумаешь еще несколько (хороших) методов. Прежде чем мы начнем работу над методами, самая первая строка кода в game.py должна быть такой: import pygame as pg Затем напишем объявление класса: class Game : Давай перейдем к методам. Вот они в одном листинге (⇒ game.py): # Запуск и создание текстового поля def __init__(self, Color) : self.Start = 0 self.Score = 0 self.Text = pg.Surface((300,50)) self.Text.fill(Color) # Вывод информации def showMessage(self, text, Color) : self.Font = pg.font.SysFont("arial", 48) self.Text = self.Font.render(text, True, Color) # Подсчет и вывод очков def setScore(self, num, Color) : self.Score += num self.showMessage("Счет: " + str(self.Score), Color) # Таймер def getTime(self, Reset) : if Reset : self.Start = pg.time.get_ticks() self.Diff = pg.time.get_ticks() - self.Start return self.Diff # Счет и время def showAll(self, num, Color) : self.Score += num ptext = " | Счет: " + str(self.Score) ztext = "Время: " + str(int(self.Diff/1000)) self.showMessage(ztext+ptext, Color) Как видишь, различия и не так велики. Новым является ме- тод init, в котором генерируется текстовое поле, которое Глава Пора развлекаться 16 312 затем может служить для отображения всех видов инфор- мации и сообщений. Метод setScore нуждается в другом па- раметре, чтобы отображаемый цвет можно было выбирать свободно. Давай использовать наш новый модуль в основной про- грамме, код которой выглядит следующим образом (⇒ dodger6.py): # Ловкач import pygame as pg import random from dplayer import * from dthing import * from game import * # Установка начальных значений Red = (255,0,0) Blue = (0,0,255) Yellow = (255,255,0) xMax, yMax = 800, 400 # Запуск Pygame, создание игровых элементов pg.init() pg.key.set_repeat(20,20) pg.display.set_caption("Моя игра") Window = pg.display.set_mode((xMax, yMax)) Figure = Player(20,30) Ball = Thing("Bilder/ball1.png") Ball.setPosition(xMax-50, yMax/2, True) Game = Game(Yellow) # Цикл событий running = True while running : for event in pg.event.get() : if event.type == pg.QUIT : running = False # Установка клавиш if event.type == pg.KEYDOWN : if event.key == pg.K_UP : Figure.setState(2) Game.getTime(True) if event.key == pg.K_DOWN : Figure.setState(1) Game.getTime(True) # Тестирование Time = Game.getTime(False) Ошибка при сборке программы 313 if Time > 200 : Figure.setState(0) # Перемещение мяча, сброс при необходимости if not Figure.isHit : Ball.move(-1, 0) if Ball.controlRestart(xMax-50, yMax/2) : Game.setScore(1, Blue) # Проверка, находится ли мяч в игровой зоне if (Ball.x < Figure.x+150) : # Если игрок проиграл, игра заканчивается if not Figure.dodge(Ball.y, yMax/2) : Figure.isHit = True Game.showMessage("Игра окончена", Red) # Позиционирование спрайта в окне Window.fill(Yellow) Window.blit(Game.Text, (xMax/2, 10)) Window.blit(Figure.Bild, (Figure.x, Figure.y)) Window.blit(Ball.Bild, (Ball.x, Ball.y)) pg.display.update() # Завершение Pygame pg.quit() Я назвал новую игру Arcade следующим образом: Arcade = Game(Yellow) В самой игре вызываются методы Arcade.getTime(), Arcade. setScore() и Arcade.showMessage() (иногда в нескольких мес- тах). Обрати внимание, что даже в инструкции blit пара- метр Text теперь принадлежит Arcade. ¾ Измени исходный код и убедись, что программа вы- полняет те же действия, что и предыдущая. Ошибка при сборке программы Теперь вернемся к предыдущей игре с жуком. Как насчет того, чтобы там тоже установить подсчет набранных оч- ков? Собственно, зачем, спросишь ты: если жук мертв, игра окончена. Правильно, но что, если мы преследуем не одно- го, а множество жуков, движущихся в разных направлени- ях? И у тебя есть ограниченное количество времени, чтобы выследить их всех? Тогда подсчет очков имеет смысл. Глава Пора развлекаться 16 314 Давай возьмем наш последний проект с жуком и посмот- рим, как сделать несколько жуков из одного. Для этого мы объявляем переменную в начале, значение которой ты мо- жешь изменить по желанию: bugMax = 5 Далее нам нужен (пустой) список: Figure = [] Затем мы заполняем его с помощью цикла for насекомыми (⇒ buggy9.py): for Nr in range(0,bugMax) : xPos = random.randint(100,xMax-100) yPos = random.randint(50,yMax-100) Figure.append(Player(xPos, yPos)) Здесь я использовал два случайных значения для распо- ложения, чтобы жуки появлялись в разных местах каждый раз, когда запускается игра. В моем случае должно быть пять жуков. Нам также нужны инструкции для их направ- ления, чтобы жуки не двигались в одном направлении. Для этого создадим еще два списка: xStep = [] yStep = [] Затем мы упаковываем определение случайного начально- го направления в цикл for (⇒ buggy9.py): for Nr in range(0,bugMax) : xStep.append(random.randint(0,2)) if xStep[Nr] == 0 : xStep[Nr] = -1 yStep.append(random.randint(0,2)) if yStep[Nr] == 0 : yStep[Nr] = -1 В этом случае цикл должен проверять каждого жука отдель- но после щелчка мышью, был ли он раздавлен: if event.type == pg.MOUSEBUTTONDOWN : (xPos, yPos) = pg.mouse.get_pos() for Nr in range(0,bugMax) : Ошибка при сборке программы 315 if (xPos > Figure[Nr].x) and (xPos < Figure[Nr].x + 100) \ and (yPos > Figure[Nr].y) and (yPos < Figure[Nr].y + 100) : Figure[Nr].destroy() При попадании жук «сплющивается» (и переменной isKil led присваивается значение true). Теперь отслеживание столкновений должно выполняться для каждого жука (⇒ buggy9.py): for Nr in range(0,bugMax) : if (Figure[Nr].x < 0) or (Figure[Nr].x > xMax-110) : xStep[Nr] = -xStep[Nr] if (Figure[Nr].y < 0) or (Figure[Nr].y > yMax-110) : yStep[Nr] = -yStep[Nr] То же самое относится к ориентации жука по направлению движения: for Nr in range(0,bugMax) : degree = atan2(-yStep[Nr], xStep[Nr]) degree = degrees(degree) - 90 Figure[Nr].rotate(degree) Но это еще не все, движение настраивается также для каж- дого маленького насекомого: for Nr in range(0,bugMax) : if not Figure[Nr].isKilled : Figure[Nr].step(xStep[Nr]*2, yStep[Nr]*2) pg.time.delay(5) Я установил задержку после цикла for, иначе игра будет ускоряться, в зависимости от того, сколько жуков будет убито. (Если хочешь, добавь инструкцию delay в конструк- цию if и измени значение времени.) Теперь нужно убедиться, что все жуки отображаются. Это делается в этом последнем цикле (⇒ buggy9.py): for Nr in range(0,bugMax) : Window.blit(Figure[Nr].Bild, (Figure[Nr].x, Figure[Nr].y)) ¾ Дополни свой проект указанным кодом. Лучше всего в том порядке, как он указан в тексте главы. Или ис- пользуй файлы примеров для книги. Затем запусти программу и проверь, что все работает (рис. 16.4). Глава Пора развлекаться 16 316 Рис. 16.4.Жуки заполнили экран Очки при попадании Давай перейдем к игровым очкам. Поскольку сейчас это того стоит, я предлагаю, чтобы за каждого раздавленного жука игрок получал 50 или даже 100 очков. И если ты поз- же сделаешь поле значительно больше и позволишь на нем бегать большему количеству жуков, то будет возможность набирать много очков. Как хорошо, что мы определили и использовали класс Game в последней версии «Ловкача». Мы можем использовать его и здесь. Для начала импортируем модуль Game: from game import * Затем мы объявляем игровой объект (на этот раз с зеленым фоном): Arcade = Game(Green) Как только мы убиваем жука, метод setScore() вступает в действие: Очки при попадании 317 Arcade.setScore(50, Blue) Figure[Nr].destroy() Разумеется, синий цвет должен был быть предварительно определен: Blue = (0,0,255) Чтобы очки отображались, эта строка должна находиться в нижней части листинга (⇒ buggy10.py): Window.blit(Arcade.Text, (xMax/3, 10)) ¾ Напиши эти строки и попытайся набрать очки за каж- дое попадание. Ты заработал больше, чем ожидал? Конечно, потому что если ты щелкал мышью по мертвому жуку, очки все равно зачислялись. Но это не входило в наши планы, и мы долж- ны исправить сей недочет. Это проще, чем ожидалось: мы проверяем, убили ли мы жука, если да – начисляются очки (⇒ buggy10.py): if not Figure[Nr].isKilled : Arcade.setScore(50, Blue) Figure[Nr].destroy() Теперь ошибка устранена. ¾ Настрой свою программу и протестируй ее до тех пор, пока не будут убиты все жуки. Достигнут ли предел? Теперь ты всегда сможешь достичь наивысшего балла, но реальная привлекательность этой игры должна заключать- ся в том, что ты должен приложить в ней немного больше усилий. Может быть, ограничить время? Давай изменим программу так, чтобы у игрока было только определенное количество времени, чтобы убить всех жуков или как мож- но большее количество за отведенное время. Для этого сна- чала нужно запустить таймер (⇒ buggy11.py): Arcade.getTime(True) Конечно, это должно происходить за пределами цикла while. Затем нам нужна переменная, которая постоянно записы- вает текущее время в этом цикле, по которой мы сможем контролировать время прохождения игры: Глава Пора развлекаться 16 318 Time = Arcade.getTime(False) Будет полезно для игрока, если время будет отображаться. Но поскольку у нас нет подходящего метода, мы должны дополнить класс Game (⇒ game.py): def showAll(self, num, Color) : self.Score += num ptext = " | Счет: " + str(self.Score) ztext = "Время: " + str(int(self.Diff/1000)) self.showMessage(ztext+ptext, Color) Метод showAll() суммирует отображение времени и на- бранных очков: Arcade.showAll(0, Blue) То есть никакие очки не добавляются, это касается только отображения изменения времени. Также ниже следует заменить вызов метода setScore() (⇒ buggy11.py): if not Figure[Nr].isKilled : Arcade.showAll(50, Blue) После окончания игрового времени следующее сообщение выводит набранное количество очков: if Time > bugMax*1500 : Arcade.showMessage("Игра окончена", Red) running = False При этом я сделал игровое время зависимым от количест- ва существующих жуков. Сначала появляется сообщение «Игра окончена», а затем переменной running присваивает- ся значение False (рис. 16.5). Очки при попадании 319 Рис. 16.5.Внесенные в код изменения Чтобы после выхода из цикла while игра не заканчивалась слишком внезапно, мы должны установить небольшую паузу: pg.time.delay(1500) pg.quit() А теперь добавим метод showAll в класс Game. Затем ты мо- жешь играть в свою игру, но на этот раз будет сложнее пой- мать всех жуков (рис. 16.6). Рис. 16.6.Ура! Победа! Глава Пора развлекаться 16 320 Очень удобно, что ты можешь скачать все примеры, а не просто набирать их, на сайте dmkpress.com Подведение итогов и заключение К сожалению, мы подошли к концу книги. В предыдущих главах о Python и Pygame, безусловно, многие возможности не были описаны. Но у тебя уже есть более чем прочные осно- вы, и еще можно улучшить рассмотренные программы или даже разработать новые. В этой главе было не так много нового, но все же несколько слов мы добавили в твой словарь: Surface Класс для отображения текста и графики Font Класс для шрифтов render Рендеринг текста Конечно, что еще можно сделать с помощью Python, напри- мер, по следующим адресам в интернете: www.pygame.org/docs/ – здесь ты найдешь учебники по Pygame ; docs.python.org/3/ – исчерпывающая документация по Python; wiki.python.org/moin/FrontPage – ты узнаешь еще больше о Python, посетив этот сайт. Все эти сайты на английском языке. 321 A Установка Python Среду Python установить очень просто. Все, что нужно сде- лать, – это нажать пару кнопок для запуска процесса ин- сталляции. В случае затруднений ты можешь попросить помощи у взрослых. Сначала тебе нужно загрузить последнюю версию Python. Для этого выполни следующие действия. 1. Запусти веб-браузер (например, Google Chrome или Microsoft Edge) и перейди на страницу www.python.org/ downloads/ (рис. А.1). Рис. А.1.Страница с дистрибутивами Python Глава Установка Python A 322 Здесь доступны две различные ветви дистрибутива Py- thon. В этой книге используется последняя версия вет- ви Python 3. 2. Щелкни по ссылке для скачивания последней версии дистрибутива ветви Python 3. (Когда я писал эту книгу, актуальной была версия 3.7.1.) 3. Теперь найди и открой окно папки, в которую скачался файл. По умолчанию это папка Загрузки (рис. А.2). Рис. А.2.Содержимое папки Загрузки 4. Дважды щелкни мышью по значку скачанного файла. Запустится программа установки (рис. А.3). Рис. А.3.Окно мастера установки Python Подведение итогов и заключение 323 5. Перед запуском процесса установки убедись, что уста- новлены флажки Install launcher for all users (Устано- вить запуск для всех пользователей) и Add Python 3.7 to PATH (Добавить Python 3.7 к пути PATH). 6. Теперь выбери пункт Customize installation (Настрой- ка установки), потому что надо указать путь установки Python (рис. А.4). Рис. А.4.Настройка процесса установки 7. В следующем окне не надо ничего менять. Просто на- жми кнопку Next (Далее), чтобы установить все указан- ные компоненты (рис. А.5). Рис. А.5.Окно выбора дополнительных компонентов Глава Установка Python A 324 8. В следующем окне установи флажок Install launcher for all users (Установить запуск для всех пользователей). Теперь надо указать, в какую папку должен быть уста- новлен Python. Если этого не сделать, файлы будут ско- пированы в папку C:\Users\твое_имя\AppData. 9. Укажи путь C:\Python (как у меня на рисунке). Или на- жми кнопку Browse (Обзор), чтобы выбрать папку, в ко- торую должен быть установлен Python. Нажми кнопку Install (Установить). Начнется установка. Теперь наберись терпения и не- много подожди – процесс установки займет некоторое время. За процессом установки можно следить с по- мощью индикатора выполнения. Наконец, ты увидишь сообщение о том, что процесс установки успешно завершен (рис. А.6). Рис. А.6.Процесс установки завершен 10. Нажми кнопку Close (Закрыть). На странице www.python.org ты всегда можешь скачать по- следнюю версию Python, а также просмотреть документа- цию и другие материалы. Установка библиотеки Pygame, вариант 1 325 Установка библиотеки Pygame, вариант 1 Поскольку библиотека Pygame не входит в состав дистрибу- тива Python, нужно установить ее отдельно. Давай это сде- лаем. 1. Запусти веб-браузер и перейди на страницу pygame.org/ download.shtml (рис. А.7). Рис. А.7.Страница загрузки дистрибутива Pygame 2. Прокрути содержимое страницы вниз до списка Win- dows. Выбери предпоследнюю ссылку – нужна версия, подходящая для Python 3. Вероятно, на момент чтения книги появятся более новые версии. Поскольку Python непрерывно развивается, тебе также может по- требоваться загрузить и установить несколько дополнительных файлов, которые работают с твоей версией Python. 3. В папке Загрузки ты увидишь значок загруженного файла (рис. А.8). В его имени содержится слово pygame. |