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

  • Enter

  • Получение объектов Event

  • В ЭТОЙ ГЛАВЕ РАССМАТРИВАЮТСЯ СЛЕДУЮЩИЕ ТЕМЫ: • Анимация объектов в игровом цикле• Изменение направления движения объектаПример запуска игры программы

  • Исходный код программы В редакторе файлов создайте новый файл, вы- брав команду меню File ⇒ New File

  • Перемещение и контроль отскока блоков

  • Константы для направлений

  • Создание структуры данных блока

  • Обработка решения игрока завершить игру

  • Перемещение каждого блока Чтобы обновлять положение каждого блока, мы будем перебирать список boxes внутри игрового цикла.44. for b in boxes: 348

  • Учим 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
    страница33 из 39
    1   ...   29   30   31   32   33   34   35   36   ...   39
    События и игровой цикл
    Все наши текстовые игры осуществляли полный вывод, пока не достигли бы вызова функции input(). Тогда программа остановилась бы и ждала, когда пользователь что-то наберет и нажмет клавишу Enter. Но pygame-программы

    Создание графики
    337
    постоянно находятся в игровом цикле , выполняя каждую строку кода в этом цикле около 100 раз в секунду.
    Игровой цикл постоянно проверяет наличие новых событий, обновляет состояние окна и отображает окно на экране. События генерируются pygame каждый раз, когда пользователь нажимает клавишу на клавиатуре, кнопку мыши, перемещает курсор или выполняет иные распознаваемые программой действия, которые должны повлиять на что-то в игре. Event — объект типа данных pygame.event.Event.
    Строка 59 — начало игрового цикла.
    58. # Запуск игрового цикла.
    59. while True:
    Условие для инструкции while установлено истинным, чтобы этот цикл выполнялся бесконечно. Цикл прервется исключительно в том случае, если событие приведет к завершению работы программы.
    Получение объектов Event
    Функция pygame.event.get() проверяет любые новые объекты pygame.event.
    Event
    (сокращенно объекты Event ), созданные с момента последнего вызова pygame.event.get()
    . Эти события возвращаются как список объектов Event, кото- рые программа затем выполнит, чтобы произвести некоторые действия в ответ на событие. Все объекты Event имеют атрибут с именем type, который сообщает нам тип события. В этой главе нам нужно использовать только тип события
    QUIT
    , который сигнализирует о выходе пользователя из программы.
    60. for event in pygame.event.get():
    61. if event.type == QUIT:
    В строке 60 мы используем цикл for для итерации по каждому объекту
    Event в списке, возвращаемом pygame.event.get(). Если атрибут type события равен константе QUIT, содержащейся в модуле pygame.locals, который мы им- портировали в начале программы, тогда понятно, что было сгенерировано событие QUIT.
    Модуль pygame генерирует событие QUIT, когда пользователь закрывает окно программы или когда компьютер выключается и пытается завершить все запущенные программы. Далее мы сообщим программе что делать, когда она обнаруживает событие QUIT.

    Выход из программы
    Если событие QUIT было сгенерировано, программа последовательно вы- зовет функции pygame.quit() и sys.exit().
    62. pygame.quit()
    63. sys.exit()
    Функция pygame.quit() является, по сути, противоположностью init().
    Вы должны вызвать ее перед выходом из программы. Если забудете, процесс
    IDLE может зависнуть после завершения работы вашей программы . Ин- струкции в строках 62 и 63 завершают работу pygame и программы.
    Заключение
    В этой главе мы рассмотрели множество новых тем, которые позволят нам сделать гораздо более занимательные игры. Взамен обычной работы с текстом и вызовов функций print() и input(), pygame-программа выглядит как окно (созданное методом pygame.display.set_mode()), в котором мы можем отображать разные объекты. Функции рисования модуля pygame позволяют отображать в этом окне фигуры разного цвета. Кроме того, вы можете соз- давать текст различного размера. Такие рисунки могут находиться в любых позициях внутри окна, в отличие от текста, создаваемого функцией print().
    pygame
    -программы могут быть намного интереснее текстовых игр. Теперь давайте узнаем, как создавать игры с анимированной графикой.

    Анимированная графика
    339
    18
    АНИМИРОВАННАЯ ГРАФИКА
    Теперь, когда у нас есть некоторые на- выки работы с модулем pygame, мы на- пишем программу c анимацией блоков, перемещающихся в окне. У этих блоков разные цвета и размеры, а перемещаются они только по диагонали. Для создания ани- мации мы будем на несколько пикселей перемещать блоки при каждом переборе игрового цикла. Тогда возникнет эффект, будто блоки двигаются по экрану.
    В ЭТОЙ ГЛАВЕ РАССМАТРИВАЮТСЯ СЛЕДУЮЩИЕ ТЕМЫ:
    • Анимация объектов в игровом цикле
    • Изменение направления движения объекта
    Пример запуска игры программы
    Когда вы запустите программу , ее окно будет выглядеть примерно так, как показано на рис. 18.1. Блоки будут отскакивать от границ окна.
    Исходный код программы
    В редакторе файлов создайте новый файл, вы- брав команду меню File
    New File (Файл ⇒ Но- вый файл). В открывшемся окне введите приве- денный ниже исходный код и сохраните файл под именем animation.py. Затем нажмите клавишу F5
    Make sure you’re using Python 3, not Python 2!
    УБЕ ДИТЕСЬ,
    ЧТО ИСПО ЛЬЗУЕТЕ
    PY THON 3,
    А НЕ PY THON 2!

    340
    Глава 18
    и запустите программу. Если при выполнении программы возникают ошиб- ки, сравните код, который вы набрали, с оригинальным кодом с помощью онлайн-инструмента на сайте inventwithpython.com/diff/.
    Рис. 18.1.
    Снимок программы с анимированными блоками
    animation.py
    1. import pygame, sys, time
    2. from pygame.locals import *
    3.
    4. # Установка pygame.
    5. pygame.init()
    6.
    7. # Настройка окна.
    8. WINDOWWIDTH = 400 9. WINDOWHEIGHT = 400 10. windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
    11. pygame.display.set_caption('Анимация')
    12.
    13. # Создание переменных направления.
    14. DOWNLEFT = 'downleft'
    15. DOWNRIGHT = 'downright'
    16. UPLEFT = 'upleft'
    17. UPRIGHT = 'upright'

    Анимированная графика
    341
    18.
    19. MOVESPEED = 4 20.
    21. # Настройка цвета.
    22. WHITE = (255, 255, 255)
    23. RED = (255, 0, 0)
    24. GREEN = (0, 255, 0)
    25. BLUE = (0, 0, 255)
    26.
    27. # Создание структуры данных блока.
    28. b1 = {'rect':pygame.Rect(300, 80, 50, 100), 'color':RED, 'dir':UPRIGHT}
    29. b2 = {'rect':pygame.Rect(200, 200, 20, 20), 'color':GREEN, 'dir':UPLEFT}
    30. b3 = {'rect':pygame.Rect(100, 150, 60, 60), 'color':BLUE, 'dir':DOWNLEFT}
    31. boxes = [b1, b2, b3]
    32.
    33. # Запуск игрового цикла.
    34. while True:
    35. # Проверка наличия события QUIT.
    36. for event in pygame.event.get():
    37. if event.type == QUIT:
    38. pygame.quit()
    39. sys.exit()
    40.
    41. # Создание на поверхности белого фона.
    42. windowSurface.fill(WHITE)
    43.
    44. for b in boxes:
    45. # Перемещение структуры данных блока.
    46. if b['dir'] == DOWNLEFT:
    47. b['rect'].left -= MOVESPEED
    48. b['rect'].top += MOVESPEED
    49. if b['dir'] == DOWNRIGHT:
    50. b['rect'].left += MOVESPEED
    51. b['rect'].top += MOVESPEED
    52. if b['dir'] == UPLEFT:
    53. b['rect'].left -= MOVESPEED
    54. b['rect'].top -= MOVESPEED
    55. if b['dir'] == UPRIGHT:
    56. b['rect'].left += MOVESPEED
    57. b['rect'].top -= MOVESPEED
    58.

    342
    Глава 18 59. # Проверка, переместился ли блок за пределы окна.
    60. if b['rect'].top < 0:
    61. # Прохождение блока через верхнюю границу.
    62. if b['dir'] == UPLEFT:
    63. b['dir'] = DOWNLEFT
    64. if b['dir'] == UPRIGHT:
    65. b['dir'] = DOWNRIGHT
    66. if b['rect'].bottom > WINDOWHEIGHT:
    67. # Прохождение блока через нижнюю границу.
    68. if b['dir'] == DOWNLEFT:
    69. b['dir'] = UPLEFT
    70. if b['dir'] == DOWNRIGHT:
    71. b['dir'] = UPRIGHT
    72. if b['rect'].left < 0:
    73. # Прохождение блока через левую границу.
    74. if b['dir'] == DOWNLEFT:
    75. b['dir'] = DOWNRIGHT
    76. if b['dir'] == UPLEFT:
    77. b['dir'] = UPRIGHT
    78. if b['rect'].right > WINDOWWIDTH:
    79. # Прохождение блока через правую границу.
    80. if b['dir'] == DOWNRIGHT:
    81. b['dir'] = DOWNLEFT
    82. if b['dir'] == UPRIGHT:
    83. b['dir'] = UPLEFT
    84.
    85. # Создание блока на поверхности.
    86. pygame.draw.rect(windowSurface, b['color'], b['rect'])
    87.
    88. # Вывод окна на экран.
    89. pygame.display.update()
    90. time.sleep(0.02)
    Перемещение и контроль отскока блоков
    В этой программе у нас будет три блока разного цвета, движущихся и от- скакивающих от границ окна. В следующих главах мы используем эту про- грамму в качестве основы для создания игры, в которой одним из блоков можно будет управлять. Для этого сначала нужно определиться с желаемым способом перемещения блоков.

    Анимированная графика
    343
    Каждый блок будет двигаться в одном из четырех диагональных направ- лений. Когда блок сталкивается с границей окна, он должен отскакивать и двигаться в противоположном диагональном направлении. Блоки будут от- скакивать так, как показано на рис. 18.2.
    Рис. 18.2.
    Как будут отскакивать блоки
    Новое направление, в котором движется блок после отскока, зависит от двух факторов: в каком направлении он двигался перед отскоком и от какой границы окна отскочил. Существуют восемь возможных способов отскока — по два разных способа для каждой из четырех границ. Например, если блок движется вниз и направо, а затем отскакивает от нижней границы окна, нуж- но, чтобы новым направлением блока было вверх и вправо.
    Мы можем использовать объект Rect для представления положения и размера блока, кортеж из трех целых чисел для представления цвета блока и одного целого числа, представляющего, в каком из четырех диагональных направлений в данный момент двигается блок.
    Игровой цикл установит координаты x и y блока в объекте Rect и при каждой итерации отобразит на экране все блоки в их текущем положении.
    По мере работы цикла блоки будут постепенно перемещаться по экрану, что- бы это выглядело, будто они плавно двигаются и отскакивают.
    Создание констант
    Строки с 1 по 5 устанавливают наши модули и инициализируют pygame, аналогично тому, что мы делали в главе 17.
    1. import pygame, sys, time
    2. from pygame.locals import *
    3.
    4. # Установка pygame.
    5. pygame.init()

    344
    Глава 18 6.
    7. # Настройка окна.
    8. WINDOWWIDTH = 400 9. WINDOWHEIGHT = 400 10. windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
    11. pygame.display.set_caption('Анимация')
    В строках 8 и 9 мы определяем две константы для ширины и высоты окна, после чего в строке 10 используем эти константы для задания переменной windowSurface
    , которая будет представлять окно pygame. Код в строке 11 со- держит функцию set_caption(), позволяющую вывести название в заголовке окна — 'Анимация'.
    В этой программе вы увидите, что значения ширины и высоты окна ис- пользуются не только для вызова функции set_mode(). Мы будем использовать константы на случай, если вы когда-либо захотите изменить размер окна, — тогда вам нужно будет изменить код только в строках 8 и 9. Поскольку во время выполнения программы ширина и высота окна никогда не меняются, константы — неплохая мысль.
    Константы для направлений
    Мы будем использовать константы для каждого из четырех направлений, в которых могут перемещаться блоки.
    13. # Создание переменных направления.
    14. DOWNLEFT = 'downleft'
    15. DOWNRIGHT = 'downright'
    16. UPLEFT = 'upleft'
    17. UPRIGHT = 'upright'
    Для этих направлений вы могли бы использовать любое значение вместо константы. Например, можно использовать строку 'downleft' непосредствен- но для представления диагонального направления вниз и влево, и повторять строку каждый раз, когда вам нужно указать это направление. Однако если вы хоть раз опечатаетесь в значении 'downleft', то получите ошибку, из-за которой ваша программа будет вести себя странно, даже несмотря на то что сбоя не случится.
    Если вместо этого вы использовали константы и случайно ошиблись в имени переменной, Python обнаружит, что переменной с таким именем не

    Анимированная графика
    345
    существует, и устроит сбой программы, выдав ошибку. Это все равно будет довольно значительным дефектом, но, по крайней мере, вы сразу узнаете об этом и сможете все исправить.
    Мы также создаем константу, чтобы определить, как быстро блоки долж- ны двигаться.
    19. MOVESPEED = 4
    Значение 4 константы MOVESPEED сообщает программе, на сколько пик- селей должен перемещаться каждый блок при каждой итерации игрового цикла .
    Константы для цвета
    Код в строках 22–25 устанавливает константы для цветов. Помните, pygame использует кортежи из трех целых значений для совокупностей красного, зе- леного и синего цветов, называемых моделью RGB. Целые числа находятся в диапазоне от 0 до 255.
    21. # Настройка цвета.
    22. WHITE = (255, 255, 255)
    23. RED = (255, 0, 0)
    24. GREEN = (0, 255, 0)
    25. BLUE = (0, 0, 255)
    Константы используются для удобства чтения кода, так же, как и в pygame- программе «Привет, мир!».
    Создание структуры данных блока
    Теперь определим блоки. Чтобы было проще, создадим словарь в виде структуры данных (см. раздел «Словари» в главе 9) для представления каж- дого перемещающегося блока. Словарь будет иметь ключи 'rect' (с объектом
    Rect в качестве значения), 'color' (с кортежем из трех целых чисел в качестве значения) и 'dir' (с одной из констант направления в качестве значения).
    Пока что мы создадим только три блока, но вы можете создать больше бло- ков, определив больше структур данных. При помощи кода анимации, кото- рый мы будем использовать позже, вы можете анимировать столько блоков, сколько определите при создании своих структур данных.

    346
    Глава 18
    Переменная b1 будет хранить одну из этих структур данных блока.
    27. # Создание структуры данных блока.
    28. b1 = {'rect':pygame.Rect(300, 80, 50, 100), 'color':RED, 'dir':UPRIGHT}
    Верхний левый угол этого блока расположен в позиции с координатами
    x=300 и y=80. Его ширина составляет 50 пикселей, а высота — 100 пикселей.
    Блок окрашен в красный (RED), а начальное направление — UPRIGHT (вправо вверх). Код в строках 29 и 30 создает еще две аналогичные структуры данных для блоков, у которых разные размеры, положения, цвета и направления.
    29. b2 = {'rect':pygame.Rect(200, 200, 20, 20), 'color':GREEN, 'dir':UPLEFT}
    30. b3 = {'rect':pygame.Rect(100, 150, 60, 60), 'color':BLUE, 'dir':DOWNLEFT}
    31. boxes = [b1, b2, b3]
    Если вам понадобилось извлечь блок или значение из списка, это можно сделать с помощью индексов и ключей. Ввод значения boxes[0] обращается к структуре данных словаря в b1. Если бы мы ввели boxes[0]['color'], выра- жение обратилось бы к ключу 'color' в b1, поэтому значение boxes[0]['color'] равнялось бы (255, 0, 0). Вы можете ссылаться на любое из значений в любой из структур данных блока, используя переменную boxes. Три словаря b1, b2 и b3 затем сохраняются в списке в переменной boxes.
    Игровой цикл
    Игровой цикл управляет анимацией движущихся блоков. Эффект ани- мации создается за счет того, что мы показываем друг за другом изображе- ния с небольшими различиями. В нашей анимации изображениями высту- пят движущиеся блоки, а небольшие различия будут состоять в положениях каждого блока. Каждый блок на изображении будет перемещаться на 4 пик- селя. Изображения будут чередоваться так быстро, что создастся впечатле- ние плавного перемещения по экрану. Если блок столкнется с границей окна, тогда игровой цикл заставит его отскочить, изменив направление.
    Теперь, когда мы немного знаем о том, как будет работать игровой цикл, давайте же его напишем!
    Обработка решения игрока завершить игру
    Когда игрок закрывает окно и завершает работу, мы должны прекратить выполнение программы так же, как мы делали это с pygame-программой «При- вет, мир!». Нам нужно осуществить это в игровом цикле, так что наша про-

    Анимированная графика
    347
    грамма постоянно проверяет, произошло ли событие QUIT. Код в строке 34 за- пускает цикл, а код в строках 36–39 руководит процессом выхода.
    33. # Запуск игрового цикла.
    34. while True:
    35. # Проверка наличия события QUIT.
    36. for event in pygame.event.get():
    37. if event.type == QUIT:
    38. pygame.quit()
    39. sys.exit()
    После этого следует убедиться, что windowSurface уже можно отображать.
    Позже мы отобразим каждый блок на windowSurface с помощью метода rect().
    При каждой итерации игрового цикла код «перерисовывает» все содержимое окна, заменяя на нем блоки на новые на расстоянии в несколько пикселей от старых. При этом мы не отображаем заново весь объект Surface; взамен мы просто добавляем отображение объекта Rect на windowSurface. Но когда игро- вой цикл повторяется, «перерисовывая» каждый объект Rect, он не стирает старую версию Rect. Если мы просто позволим циклу отображать на экране объекты Rect, то получим их след вместо гладкой анимации. Чтобы этого из- бежать, необходимо очищать окно при каждой итерации игрового цикла.
    Для этого код в строке 42 заполняет Surface белым цветом, чтобы все, что было отображено там, стерлось.
    41. # Создание на поверхности белого фона.
    42. windowSurface.fill(WHITE)
    Без вызова windowSurface.fill(WHITE) для заливки белым всего окна перед отображением прямоугольников в новых положениях, вы увидите след объ- ектов Rect. Если хотите испробовать это и посмотреть, что произойдет, може- те закомментировать строку 42, указав символ # в ее начале.
    Как только windowSurface заполняется, можно приступать к отображению всех наших объектов Rect.
    Перемещение каждого блока
    Чтобы обновлять положение каждого блока, мы будем перебирать список boxes внутри игрового цикла.
    44. for b in boxes:

    348
    Глава 18
    Чтобы упростить код для ввода, внутри цикла for вы будете ссылаться на текущий блок как на b. Нам нужно изменить каждый блок в зависимости от направления, в котором он уже перемещается, поэтому мы будем использо- вать инструкции if, чтобы выяснить направление движения блока, проверяя ключ dir внутри структуры данных блока. Затем мы изменим положение бло- ка в зависимости от этого направления.
    45. # Перемещение структуры данных блока.
    46. if b['dir'] == DOWNLEFT:
    47. b['rect'].left -= MOVESPEED
    48. b['rect'].top += MOVESPEED
    49. if b['dir'] == DOWNRIGHT:
    50. b['rect'].left += MOVESPEED
    51. b['rect'].top += MOVESPEED
    52. if b['dir'] == UPLEFT:
    53. b['rect'].left -= MOVESPEED
    54. b['rect'].top -= MOVESPEED
    55. if b['dir'] == UPRIGHT:
    56. b['rect'].left += MOVESPEED
    57. b['rect'].top -= MOVESPEED
    Новое значение атрибутов left и top каждого блока зависит от направле- ния его движения. Если это направление DOWNLEFT или DOWNRIGHT, нужно увели-
    чить значение атрибута top. Если это направление UPLEFT или UPRIGHT, нужно
    уменьшить значение атрибута top.
    Если направление блока — DOWNRIGHT или UPRIGHT, нужно увеличить значе- ние атрибута left. А если DOWNLEFT или UPLEFT — нужно уменьшить значение атрибута left.
    Значения этих атрибутов будут увеличиваться или уменьшаться на ве- личину целого числа, хранящегося в переменной MOVESPEED, то есть там, где хранится количество пикселей, на которые перемещаются блоки при каждой итерации игрового цикла. Мы присваиваем переменной MOVESPEED значение в строке 19.
    Например, если значение b['dir'] установлено равным 'downleft', b['rect'].left
    — равным 40 и b['rect'].top — 100, тогда условие в строке
    46 будет истинным. Если переменной MOVESPEED присвоено значение 4, тог- да код в строках 47 и 48 изменит объект Rect так, что b['rect'].left станет
    36
    , а b['rect'].top — 104. Затем изменение значения Rect приводит к тому, что код в строке 86 «опускает» прямоугольник немного вниз и влево от его предыдущего положения.

    Анимированная графика
    1   ...   29   30   31   32   33   34   35   36   ...   39


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