Главная страница
Навигация по странице:

  • Завершение игры и добавление паузы

  • Отслеживание столкновений со злодеями

  • Отображение текста в окне

  • Инициализация pygame и настройка окна

  • Учим Python, делая крутые игры 2018. Invent your owncomputer gameswith python


    Скачать 6.56 Mb.
    НазваниеInvent your owncomputer gameswith python
    Дата10.12.2022
    Размер6.56 Mb.
    Формат файлаpdf
    Имя файлаУчим Python, делая крутые игры 2018.pdf
    ТипДокументы
    #837554
    страница37 из 39
    1   ...   31   32   33   34   35   36   37   38   39
    pygame.time.Clock
    Объект
    Clock в модуле pygame.time пригодится для того, чтобы игры работали на нормальной скорости, а не на очень высокой. Объект
    Clock имеет метод tick(), которому может быть передано значение количества кадров в секунду (FPS, frames per second), с которым тре- буется запустить игру. Чем выше значение FPS, тем быстрее работает игра.

    Игра «Ловкач» с графикой и звуком
    383
    Пример запуска игры «Ловкач»
    Когда вы запустите эту программу, окно будет выглядеть как показано на рис. 21.1.
    Рис. 21.1.
    Снимок игры «Ловкач»
    Исходный код игры «Ловкач»
    В редакторе файлов создайте новый файл, выбрав команду меню File
    New File (Файл ⇒ Новый файл).
    В открывшемся окне введите приведенный ниже ис- ходный код и сохраните файл под именем dodger.py.
    Поместите файлы изображений и звуков в папку с файлом dodger.py. Затем нажмите клавишу F5 и за- пустите программу. Если при выполнении програм- мы возникают ошибки, сравните код, который вы набрали, с оригинальным кодом с помощью онлайн- инструмента на сайте inventwithpython.com/diff/.
    Make sure you’re using Python 3, not Python 2!
    УБЕ ДИТЕСЬ,
    ЧТО ИСПО ЛЬЗУЕТЕ
    PY THON 3,
    А НЕ PY THON 2!

    384
    Глава 21
    dodger.py
    1. import pygame, random, sys
    2. from pygame.locals import *
    3.
    4. WINDOWWIDTH = 600 5. WINDOWHEIGHT = 600 6. TEXTCOLOR = (0, 0, 0)
    7. BACKGROUNDCOLOR = (255, 255, 255)
    8. FPS = 60 9. BADDIEMINSIZE = 10 10. BADDIEMAXSIZE = 40 11. BADDIEMINSPEED = 1 12. BADDIEMAXSPEED = 8 13. ADDNEWBADDIERATE = 6 14. PLAYERMOVERATE = 5 15.
    16. def terminate():
    17. pygame.quit()
    18. sys.exit()
    19.
    20. def waitForPlayerToPressKey():
    21. while True:
    22. for event in pygame.event.get():
    23. if event.type == QUIT:
    24. terminate()
    25. if event.type == KEYDOWN:
    26. if event.key == K_ESCAPE: # Нажатие ESC осуществляет выход.
    27. terminate()
    28. return
    29.
    30. def playerHasHitBaddie(playerRect, baddies):
    31. for b in baddies:
    32. if playerRect.colliderect(b['rect']):
    33. return True
    34. return False
    35.
    36. def drawText(text, font, surface, x, y):
    37. textobj = font.render(text, 1, TEXTCOLOR)
    38. textrect = textobj.get_rect()
    39. textrect.topleft = (x, y)
    40. surface.blit(textobj, textrect)

    Игра «Ловкач» с графикой и звуком
    385
    41.
    42. # Настройка pygame, окна и указателя мыши.
    43. pygame.init()
    44. mainClock = pygame.time.Clock()
    45. windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
    46. pygame.display.set_caption('Ловкач')
    47. pygame.mouse.set_visible(False)
    48.
    49. # Настройка шрифтов.
    50. font = pygame.font.SysFont(None, 35)
    51.
    52. # Настройка звуков.
    53. gameOverSound = pygame.mixer.Sound('gameover.wav')
    54. pygame.mixer.music.load('background.mid')
    55.
    56. # Настройка изображений.
    57. playerImage = pygame.image.load('player.png')
    58. playerRect = playerImage.get_rect()
    59. baddieImage = pygame.image.load('baddie.png')
    60.
    61. # Вывод начального экрана.
    62. windowSurface.fill(BACKGROUNDCOLOR)
    63. drawText('Ловкач', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
    64. drawText('Нажмите клавишу для начала игры', font, windowSurface, (WINDOWWIDTH / 5) - 30, (WINDOWHEIGHT / 3) + 50)
    65. pygame.display.update()
    66. waitForPlayerToPressKey()
    67.
    68. topScore = 0 69. while True:
    70. # Настройка начала игры.
    71. baddies = []
    72. score = 0 73. playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50)
    74. moveLeft = moveRight = moveUp = moveDown = False
    75. reverseCheat = slowCheat = False
    76. baddieAddCounter = 0 77. pygame.mixer.music.play(-1, 0.0)
    78.
    79. while True: # Игровой цикл выполняется, пока игра работает.
    80. score += 1 # Увеличение количества очков.
    81.
    82. for event in pygame.event.get():

    386
    Глава 21 83. if event.type == QUIT:
    84. terminate()
    85.
    86. if event.type == KEYDOWN:
    87. if event.key == K_z:
    88. reverseCheat = True
    89. if event.key == K_x:
    90. slowCheat = True
    91. if event.key == K_LEFT or event.key == K_a:
    92. moveRight = False
    93. moveLeft = True
    94. if event.key == K_RIGHT or event.key == K_d:
    95. moveLeft = False
    96. moveRight = True
    97. if event.key == K_UP or event.key == K_w:
    98. moveDown = False
    99. moveUp = True
    100. if event.key == K_DOWN or event.key == K_s:
    101. moveUp = False
    102. moveDown = True
    103.
    104. if event.type == KEYUP:
    105. if event.key == K_z:
    106. reverseCheat = False
    107. score = 0 108. if event.key == K_x:
    109. slowCheat = False
    110. score = 0 111. if event.key == K_ESCAPE:
    112. terminate()
    113.
    114. if event.key == K_LEFT or event.key == K_a:
    115. moveLeft = False
    116. if event.key == K_RIGHT or event.key == K_d:
    117. moveRight = False
    118. if event.key == K_UP or event.key == K_w:
    119. moveUp = False
    120. if event.key == K_DOWN or event.key == K_s:
    121. moveDown = False
    122.
    123. if event.type == MOUSEMOTION:
    124. # Если мышь движется, переместить игрока к указателю мыши.

    Игра «Ловкач» с графикой и звуком
    387
    125. playerRect.centerx = event.pos[0]
    126. playerRect.centery = event.pos[1]
    127. # Если необходимо, добавить новых злодеев в верхнюю часть экрана.
    128. if not reverseCheat and not slowCheat:
    129. baddieAddCounter += 1 130. if baddieAddCounter == ADDNEWBADDIERATE:
    131. baddieAddCounter = 0 132. baddieSize = random.randint(BADDIEMINSIZE, BADDIEMAXSIZE)
    133. newBaddie = {'rect': pygame.Rect(random.randint(0, WINDOWWIDTH - baddieSize), 0 - baddieSize, baddieSize, baddieSize),
    134. 'speed': random.randint(BADDIEMINSPEED, BADDIEMAXSPEED),
    135. 'surface':pygame.transform.scale(baddieImage, (baddieSize, baddieSize)),
    136. }
    137.
    138. baddies.append(newBaddie)
    139.
    140. # Перемещение игрока по экрану.
    141. if moveLeft and playerRect.left > 0:
    142. playerRect.move_ip(-1 * PLAYERMOVERATE, 0)
    143. if moveRight and playerRect.right < WINDOWWIDTH:
    144. playerRect.move_ip(PLAYERMOVERATE, 0)
    145. if moveUp and playerRect.top > 0:
    146. playerRect.move_ip(0, -1 * PLAYERMOVERATE)
    147. if moveDown and playerRect.bottom < WINDOWHEIGHT:
    148. playerRect.move_ip(0, PLAYERMOVERATE)
    149.
    150. # Перемещение злодеев вниз.
    151. for b in baddies:
    152. if not reverseCheat and not slowCheat:
    153. b['rect'].move_ip(0, b['speed'])
    154. elif reverseCheat:
    155. b['rect'].move_ip(0, -5)
    156. elif slowCheat:
    157. b['rect'].move_ip(0, 1)
    158.
    159. # Удаление злодеев, упавших за нижнюю границу экрана.
    160. for b in baddies[:]:
    161. if b['rect'].top > WINDOWHEIGHT:
    162. baddies.remove(b)
    163.
    164. # Отображение в окне игрового мира.
    165. windowSurface.fill(BACKGROUNDCOLOR)
    166.

    388
    Глава 21 167. # Отображение количества очков и лучшего результата.
    168. drawText('Счет: %s' % (score), font, windowSurface, 10, 0)
    169. drawText('Рекорд: %s' % (topScore), font, windowSurface, 10, 40)
    170.
    171. # Отображение прямоугольника игрока.
    172. windowSurface.blit(playerImage, playerRect)
    173.
    174. # Отображение каждого злодея.
    175. for b in baddies:
    176. windowSurface.blit(b['surface'], b['rect'])
    177.
    178. pygame.display.update()
    179.
    180. # Проверка, попал ли в игрока какой-либо из злодеев.
    181. if playerHasHitBaddie(playerRect, baddies):
    182. if score > topScore:
    183. topScore = score # установка нового рекорда
    184. break
    185.
    186. mainClock.tick(FPS)
    187.
    188. # Отображение игры и вывод надписи 'Игра окончена'.
    189. pygame.mixer.music.stop()
    190. gameOverSound.play()
    191.
    192. drawText('ИГРА ОКОНЧЕНА!', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
    193. drawText('Нажмите клавишу для начала новой игры', font, windowSurface, (WINDOWWIDTH /
    3) - 120, (WINDOWHEIGHT / 3) + 50)
    194. pygame.display.update()
    195. waitForPlayerToPressKey()
    196.
    197. gameOverSound.stop()
    Импорт модулей
    Игра «Ловкач» импортирует те же модули, что и предыдущие pygame- программы — pygame, random, sys и pygame.locals.
    1. import pygame, random, sys
    2. from pygame.locals import *

    Игра «Ловкач» с графикой и звуком
    389
    Модуль pygame.locals содержит несколько констант, используемых pygame, таких как типы событий (QUIT, KEYDOWN и так далее) и клавиши клавиатуры
    (K_ESCAPE, K_LEFT и так далее). Используя синтаксис from pygame.locals import *, вы можете использовать в исходном коде просто QUIT вместо pygame.locals.QUIT.
    Создание констант
    Код в строках 4–7 устанавливают константы для размеров окна, цвета текста и цвета фона.
    4. WINDOWWIDTH = 600 5. WINDOWHEIGHT = 600 6. TEXTCOLOR = (0, 0, 0)
    7. BACKGROUNDCOLOR = (255, 255, 255)
    Мы используем константы, потому что это гораздо более наглядно, чем если бы мы набирали значения вручную. Например, строка кода windowSurface.
    fill(BACKGROUNDCOLOR)
    более понятна, чем windowSurface.fill((255, 255, 255)).
    Также это позволит вам легко модифицировать игру. Изменив значения переменной WINDOWWIDTH в строке 4, вы автоматически меняете код везде, где используется переменная WINDOWWIDTH. Если бы вместо этого вы использовали значение 600, вам пришлось бы изменить каждое вхождение 600 в коде. Про- ще один раз изменить значение константы.
    В строке 8 вы создаете константу для FPS, количества кадров в секунду, необходимого для запуска игры.
    8. FPS = 60
    Кадр — это экран, отображаемый при одном переборе игрового цикла.
    В строке 186 вы передаете значение переменной FPS методу mainClock.tick(), чтобы функция знала, на какое количество времени приостанавливать про- грамму. Здесь переменной FPS присвоено значение 60, но вы можете изменить значение переменной FPS в большую сторону, чтобы игра работала быстрее, или в меньшую, чтобы замедлить ее.
    Код в строках 9–13 создают еще несколько констант для падающих спрай- тов злодеев.
    9. BADDIEMINSIZE = 10 10. BADDIEMAXSIZE = 40 11. BADDIEMINSPEED = 1

    390
    Глава 21 12. BADDIEMAXSPEED = 8 13. ADDNEWBADDIERATE = 6
    Значения ширины и высоты спрайтов злодеев будут находиться в диапа- зоне между BADDIEMINSIZE и BADDIEMAXSIZE. Скорость, с которой спрайты зло- деев падают на экране, будет находиться в диапазоне между BADDIEMINSPEED и BADDIEMAXSPEED пикселей за одну итерацию игрового цикла. А новый спрайт злодея будет добавляться в верхней части окна каждые ADDNEWBADDIERATE ите- раций игрового цикла.
    Наконец, константа PLAYERMOVERATE хранит количество пикселей, на кото- рое спрайт игрока перемещается в окне при каждой итерации игрового цик- ла (если перемещается).
    14. PLAYERMOVERATE = 5
    Увеличивая это число, вы увеличиваете скорость перемещения персо нажа.
    Определение функций
    Для этой игры вы создадите несколько функций. Функции terminate() и waitForPlayerToPressKey() будут, соответственно, завершать и приостанав- ливать игру, функция playerHasHitBaddie() будет отслеживать столкновения спрайта игрока со спрайтами злодеев, а функция drawText() будет отображать на экране счет и другой текст.
    Завершение игры и добавление паузы
    Модуль pygame требует, чтобы для завершения игры вы вызывали как функцию pygame.quit(), так и sys.exit(). Строки 16–18 помещают их обеих в функцию terminate().
    16. def terminate():
    17. pygame.quit()
    18. sys.exit()
    Теперь, вместо того, чтобы вызывать и pygame.quit(), и sys.exit(), вам нужно вызвать только функцию terminate().
    В некоторых случаях вам понадобится приостановить выполнение про- граммы до тех пор, пока игрок не нажмет клавишу, — например, в самом начале игры, когда появится заголовок «Ловкач», или в конце, когда отобра-

    Игра «Ловкач» с графикой и звуком
    391
    жается надпись «Игра окончена». В строках 20–24 создается новая функция waitForPlayerToPressKey()
    20. def waitForPlayerToPressKey():
    21. while True:
    22. for event in pygame.event.get():
    23. if event.type == QUIT:
    24. terminate()
    Внутри этой функции используется бесконечный цикл, который преры- вается только при получении события KEYDOWN или QUIT. В начале цикла pygame.
    event.get()
    возвращает список объектов Event для проверки.
    Если игрок закрыл окно во время ожидания программой, когда он на- жмет клавишу, pygame сгенерирует событие QUIT, наличие которого вы про- веряете в строке 23 с помощью event.type. Если игрок завершил игру, Python вызывает функцию terminate() в строке 24.
    Если игра получает событие KEYDOWN, сначала нужно проверить, была ли нажата клавиша Esc.
    25. if event.type == KEYDOWN:
    26. if event.key == K_ESCAPE: # Нажатие ESC осуществляет выход.
    27. terminate()
    28. return
    Если игрок нажал клавишу Esc, программа должна завершиться. Если дело было не в этом, то интерпретатор пропустит блок if в строке 27 и пе- рейдет прямо к инструкции return, что приведет к выходу из функции waitForPlayerToPressKey()
    Если события QUIT или KEYDOWN не генерируются, код продолжает цикл.
    Поскольку цикл ничего не выполняет, все будет выглядеть так, будто игра замерла, пока игрок не нажмет клавишу.
    Отслеживание столкновений со злодеями
    Функция playerHasHitBaddie() вернет True, если спрайт игрока столкнулся со спрайтом одного из злодеев.
    30. def playerHasHitBaddie(playerRect, baddies):
    31. for b in baddies:
    32. if playerRect.colliderect(b['rect']):

    392
    Глава 21 33. return True
    34. return False
    Параметр baddies представляет собой список структур данных словаря злодея. Каждый из этих словарей имеет ключ 'rect', а значение для этого клю- ча — объект Rect, который представляет размер и местоположение злодея.
    playerRect также является объектом Rect. Объекты Rect имеют метод с именем colliderect() , который возвращает True, если объект Rect столкнулся с тем объектом Rect, который был передан этому методу. В противном случае colliderect()
    возвращает False.
    Цикл for в строке 31 выполняет перебор каждого словаря злодея в списке baddies
    . Если любой из этих злодеев сталкивается с персонажем игрока, то playerHasHitBaddie()
    возвращает True. Если код перебрал всех злодеев в списке baddies
    , не обнаружив столкновения, playerHasHitBaddie() возвращает False.
    Отображение текста в окне
    Отображение текста в окне включает в себя несколько шагов, которые мы выполним с помощью функции drawText(). Таким образом, есть только одна функция, которую мы вызываем, когда хотим отобразить на экране количе- ство очков игрока или надпись 'Игра окончена'.
    36. def drawText(text, font, surface, x, y):
    37. textobj = font.render(text, 1, TEXTCOLOR)
    38. textrect = textobj.get_rect()
    39. textrect.topleft = (x, y)
    40. surface.blit(textobj, textrect)
    Сначала вызов метода render() в строке 37 создает объект Surface, кото- рый форматирует текст определенным шрифтом.
    Затем вам нужно узнать размер и местоположение объекта Surface. Можно получить объект Rect с этой информацией, используя метод Surface get_rect().
    Объект Rect, возвращаемый из функции get_rect() в строке 38, содержит копию информации о ширине и высоте объекта Surface. Код в строке 39 из- меняет местоположение объекта Rect, устанавливая новый кортеж для его атрибута topleft.
    Наконец, код в строке 40 отображает объект Surface с отформатирован- ным текстом на объекте Surface, который был передан функции drawText().
    Отображение текста в pygame занимает на несколько шагов больше, чем про-

    Игра «Ловкач» с графикой и звуком
    393
    сто при вызове функции print(). Но если вы поместите этот код в единую функцию с именем drawText(), тогда для отображения текста на экране вам нужно будет вызвать лишь эту функцию.
    Инициализация pygame и настройка окна
    Теперь, когда с константами и функциями покончено, начнем вызывать функции pygame, которые настраивают окно и скорость работы.
    42. # Настройка pygame, окна и указателя мыши.
    43. pygame.init()
    44. mainClock = pygame.time.Clock()
    Код в строке 43 устанавливает модуль pygame, вызывая функцию pygame.
    init()
    . Код в строке 44 создает объект pygame.time.Clock() и сохраняет его в переменной mainClock. Этот объект поможет нам обеспечить выполнение программы с надлежащей скоростью.
    Код в строке 45 создает новый объект Surface, который используется для отображения окна.
    45. windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))
    Обратите внимание, что функции pygame.display.set_mode() передается только один аргумент — кортеж. Аргументы pygame.display.set_mode() — не два целых числа, а один кортеж из двух целых чисел. Вы можете указать ши- рину и высоту этого объекта Surface (и окна), передав кортеж с константами
    WINDOWWIDTH и WINDOWHEIGHT.
    Функция pygame.display.set_mode() имеет второй необязательный пара- метр. Вы можете передать константу pygame.FULLSCREEN, чтобы окно заполнило весь экран. Взгляните на строку 45 с данной модификацией.
    45. windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), pygame.FULLSCREEN)
    Для обозначения ширины и высоты окна по-прежнему передаются па- раметры WINDOWWIDTH и WINDOWHEIGHT, но изображение будет растянуто больше, чтобы соответствовать размеру экрана. Попробуйте запустить программу в полноэкранном режиме и в оконном.

    394
    Глава 21
    Код в строке 46 создает заголовок окна со строкой 'Ловкач':
    46. pygame.display.set_caption('Ловкач')
    Эта надпись отображается в строке заголовка в верхней части окна.
    В игре «Ловкач» указатель мыши должен быть невиден. Вам нужно, чтобы мышь перемещала персонажа игрока по экрану, но при этом указатель мыши помешал бы изображению персонажа. Мы можем сделать мышь невидимой с помощью всего одной строки кода.
    47. pygame.mouse.set_visible(False)
    Вызов pygame.mouse.set_visible(False) сообщает pygame, что указатель мыши нужно сделать невидимым.
    1   ...   31   32   33   34   35   36   37   38   39


    написать администратору сайта