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

  • Отображение начального экрана

  • rect . Объект Rect, который описывает, где находится спрайт злодея и какого он размера. Игра «Ловкач» с графикой и звуком 397 • speed

  • Обработка событий клавиатуры

  • Перемещение спрайтов игрока и злодеев

  • Учим 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
    страница38 из 39
    1   ...   31   32   33   34   35   36   37   38   39
    Установка шрифтов, изображений и звуков
    Поскольку в этой программе мы отображаем на экране текст, то нужно пре- доставить модулю pygame объект Font , который будет использоваться для текста.
    Код в строке 50 создает объект Font, вызывая функцию pygame.font.SysFont().
    49. # Настройка шрифтов.
    50. font = pygame.font.SysFont(None, 35)
    При передаче значения None выбирается шрифт по умолчанию, при пере- даче значения 48 — размер шрифта составит 48 пунктов.
    Затем мы создадим объекты Sound и настроим фоновую музыку.
    52. # Настройка звуков.
    53. gameOverSound = pygame.mixer.Sound('gameover.wav')
    54. pygame.mixer.music.load('background.mid')
    Функция-конструктор pygame.mixer.Sound() создает новый объект Sound и сохраняет ссылку на этот объект в переменной gameOverSound. В своих соб- ственных играх вы можете создавать столько объектов звуков, сколько за- хотите.
    Функция pygame.mixer.music.load() загружает звуковой файл для воспро- изведения в качестве фоновой музыки. Эта функция не возвращает никаких

    Игра «Ловкач» с графикой и звуком
    395
    объектов. Единовременно может быть загружен только один фоновый зву- ковой файл. Фоновая музыка будет воспроизводиться во время игры непре- рывно, но объекты Sound будут воспроизводиться только тогда, когда игрок столкнется со злодеем и проиграет.
    Для этой игры можно использовать любой WAV или MIDI-файл. Некото- рые звуковые файлы доступны в файлах примеров на веб-сайте https://eksmo.
    ru/files/python_games_sweigart.zip. Вы также можете использовать свои соб- ственные звуковые файлы, если только присвоите файлам имена gameover.
    wav и background.mid или измените строки 53 и 54 в соответствии с именами файлов.
    Затем нужно загрузить файлы изображений, которые будут использо- ваться для спрайтов игрока и злодеев.
    56. # Настройка изображений.
    57. playerImage = pygame.image.load('player.png')
    58. playerRect = playerImage.get_rect()
    59. baddieImage = pygame.image.load('baddie.png')
    Изображение для персонажа сохраняется в player.png, а изображение для каждого злодея — в файле baddie.png.
    Все злодеи выглядят одинаково, поэтому для них нужен только один файл изображения. Вы можете загрузить эти изображения с веб-сайта https://
    eksmo.ru/files/python_games_sweigart.zip.
    Отображение начального экрана
    Когда начинается игра, Python должен отобразить на экране ее название.
    Также нужно сообщить игроку, что он может начать игру, если нажмет любую клавишу. Этот экран отображается, чтобы после запуска программы у игрока было время приготовиться к игре. В строках 63 и 64 вводится код для вызова функции drawText().
    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()

    396
    Глава 21
    Мы передаем этой функции пять аргументов:
    1. Строка текста, который вы хотите отобразить.
    2. Шрифт этого текста.
    3. Объект
    Surface
    , на котором будет отображаться текст.
    4. Координата
    x на объекте Surface, где следует отобразить текст.
    5. Координата
    y на объекте Surface, где следует отобразить текст.
    Может показаться, что мы передаем много аргументов, но имейте в виду, что данный вызов каждый раз заменяет собой пять строк кода. Это сокра- щает код программы и упрощает поиск ошибок, поскольку проверять нужно меньше кода.
    Функция waitForPlayerToPressKey() приостанавливает игру, зацикливаясь до тех пор, пока не будет сгенерировано событие KEYDOWN. Затем интерпрета- тор прерывает цикл, и программа продолжает работу.
    Начало игры
    Определив теперь все функции, можем начать писать основной код игры.
    Строки 68 и далее будут вызывать функции, которые мы определили до этого.
    Значение переменной topScore начинается с 0 при первом запуске программы.
    Каждый раз, когда игрок проигрывает, побив предыдущий рекорд, он заме- няется последним набранным количеством очков.
    68. topScore = 0 69. while True:
    Бесконечный цикл, запущенный в строке 69, технически не является игровым циклом. Игровой цикл управляет событиями и отображает окно, пока игра работает. А этот цикл while повторяется каждый раз, когда игрок начинает новую игру. Когда игрок проигрывает, и игра сбрасывается, интер- претатор возвращается к строке 69.
    Сначала нужно присвоить baddies значение пустого списка.
    70. # Настройка начала игры.
    71. baddies = []
    72. score = 0
    Переменная baddies — это список словарей со следующими ключами:

    'rect'
    . Объект Rect, который описывает, где находится спрайт злодея и какого он размера.

    Игра «Ловкач» с графикой и звуком
    397

    'speed'
    . Указывает, с какой скоростью спрайт злодея падает на экране.
    Целое число обозначает количество пикселей на одну итерацию игро- вого цикла.

    'surface'
    . Объект Surface, на котором отображено масштабированное изображение злодея. Это тот Surface, который отображен на объекте
    Surface
    , возвращаемом pygame.display.set_mode().
    Код в строке 72 сбрасывает очки игрока до 0.
    Начальное расположение пользователя — по центру экрана по ширине и в 50 пикселях выше от нижней границы, что указано в строке 73.
    73. playerRect.topleft = (WINDOWWIDTH / 2, WINDOWHEIGHT - 50)
    Первым элементом кортежа в строке 73 является координата x левой сто- роны, вторым — координата y верхней стороны персонажа игрока.
    Затем мы устанавливаем переменные для перемещений игрока и чит- кодов.
    74. moveLeft = moveRight = moveUp = moveDown = False
    75. reverseCheat = slowCheat = False
    76. baddieAddCounter = 0
    Переменным перемещения moveLeft, moveRight, moveUp и moveDown присвоено значение False. Переменные reverseCheat и slowCheat также установлены рав- ными False. Они изменят значение на True только тогда, когда игрок включит эти чит-коды, удерживая клавишу Z или X, соответственно.
    Переменная baddieAddCounter выступает счетчиком, сообщающим про- грамме, когда в верхнюю часть экрана нужно добавить спрайт нового злодея.
    Значение baddieAddCounter увеличивается на 1 при каждой итерации игрового цикла. (Это напоминает код в разделе «Добавление новых блоков “еды”» гла- вы 19.)
    Когда переменная baddieAddCounter принимает значение ADDNEWBADDIERATE, значение переменной baddieAddCounter сбрасывается до 0, и в верхнюю часть экрана добавляется новый спрайт злодея (эта проверка выполняется позже в строке 130).
    Фоновая музыка начинает воспроизведение в строке 77 с вызовом функ- ции pygame.mixer.music.play().
    77. pygame.mixer.music.play(-1, 0.0)

    398
    Глава 21
    Поскольку первый аргумент равен −1, pygame повторяет музыку бесконеч- но. Второй аргумент — число с плавающей запятой, сообщающее, в скольких секундах после начала композиции находится момент, с которого ее следует проигрывать. Если передать 0,0, музыка начнет воспроизводиться с самого начала.
    Игровой цикл
    Код игрового цикла постоянно обновляет состояние игрового мира, из- меняя положение спрайтов игрока и злодеев, обрабатывая события, создан- ные pygame, и отображая новый игровой мир на экране. Все это происходит несколько десятков раз в секунду, что заставляет игру работать в режиме ре- ального времени.
    Строка 79 — начало основного игрового цикла.
    79. while True: # Игровой цикл выполняется, пока игра работает.
    80. score += 1 # Увеличение количества очков.
    Код в строке 80 увеличивает количество очков игрока при каждой итера- ции игрового цикла.
    Чем дольше игрок продолжает играть, не проигрывая, тем больше у него становится очков. Цикл прервется только тогда, когда игрок либо проиграет, либо выйдет из программы.
    Обработка событий клавиатуры
    Существуют четыре типа событий, которые программа будет обрабаты- вать : QUIT, KEYDOWN, KEYUP и MOUSEMOTION.
    В строке 82 начинается код, управляющий событиями.
    82. for event in pygame.event.get():
    83. if event.type == QUIT:
    84. terminate()
    Он вызывает функцию pygame.event.get(), которая возвращает список объектов Event. Каждый объект Event представляет собой событие, которое произошло с момента последнего вызова pygame.event.get(). Код проверяет атрибут type объекта Event, чтобы узнать, какой это тип события, а затем об- рабатывает его соответствующим образом.

    Игра «Ловкач» с графикой и звуком
    399
    Если атрибут type объекта Event равен QUIT, значит, пользователь закрыл программу. Константа QUIT была импортирована из модуля pygame.locals.
    Если тип события — KEYDOWN, значит, игрок нажал клавишу.
    86. if event.type == KEYDOWN:
    87. if event.key == K_z:
    88. reverseCheat = True
    89. if event.key == K_x:
    90. slowCheat = True
    С помощью event.key == K_z код в строке 87 проверяет, указывает ли со- бытие на нажатие клавиши Z.
    Если это условие истинно, интерпретатор присваивает переменной reverseCheat значение True, чтобы активировать чит-код обратного направле- ния. Аналогично код в строке 89 проверяет, нажата ли клавиша X для актива- ции чит-кода замедления.
    Код в строках 91–102 определяет, было ли создано событие, отвечающее за нажатие игроком одной из клавиш со стрелками или клавиш W, A, S или D.
    Этот код аналогичен обработке нажатий клавиш клавиатуры в программах из предыдущих глав.
    Если тип события — KEYUP, значит, игрок отпустил клавишу.
    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
    Код в строке 105 проверяет, отпустил ли игрок клавишу Z, что деактиви- рует чит-код обратного направления. В таком случае код в строке 106 при- сваивает переменной reverseCheat значение False, а код в строке 107 сбрасы- вает счет до 0. Сброс очков предназначен для того, чтобы отбивать у игрока желание использовать чит-коды.
    Код в строках 108 — 110 выполняет то же самое для клавиши X и чит- кода замедления. Когда клавиша X отпускается, переменной slowCheat при- сваивается значение False, а счет игрока сбрасываются до 0.

    400
    Глава 21
    В любой момент игры игрок может нажать клавишу Esc, чтобы завершить игру.
    111. if event.key == K_ESCAPE:
    112. terminate()
    Код в строке 111 определяет, была ли отпущена клавиша Esc, проверяя event.key == K_ESCAPE
    . Если так и есть, код в строке 112 вызывает функцию terminate()
    для выхода из программы.
    Код в строках 114–121 проверяет, была ли отпущена одна из клавиш со стрелками или W, A, S или D.
    В этом случае интерпретатор присваивает соответствующей переменной перемещения значение False. Это напоминает код перемещения в програм- мах из глав 19 и 20.
    Обработка событий мыши
    Теперь, когда вы разобрались с событиями клавиатуры, давайте обрабо- таем все возможные события мыши. Игра «Ловкач» не реагирует на нажатие игроком кнопки мыши, но откликается на движение ее курсора. Благодаря этому у игрока есть два способа управления персонажем в игре: клавиатурой или мышью.
    Событие MOUSEMOTION генерируется каждый раз, когда мышь перемещает- ся.
    123. if event.type == MOUSEMOTION:
    124. # Если мышь движется, переместить игрока к указателю мыши.
    125. playerRect.centerx = event.pos[0]
    126. playerRect.centery = event.pos[1]
    Объекты Event с атрибутом type, имеющим значение MOUSEMOTION, также содержат атрибут pos для обработки позиции события мыши. Атрибут pos хранит кортеж координат x и y места, куда в окне переместился указатель мыши.
    Если тип события — MOUSEMOTION, персонаж игрока перемещается в поло- жение указателя мыши.
    Код в строках 125 и 126 устанавливает координаты x и y центра спрайта игрока равными координатам указателя мыши.

    Игра «Ловкач» с графикой и звуком
    401
    Добавление новых злодеев
    При каждой итерации игрового цикла код увеличивает значение пере- менной baddieAddCounter на единицу.
    127. # Если необходимо, добавить новых злодеев в верхнюю часть экрана.
    128. if not reverseCheat and not slowCheat:
    129. baddieAddCounter += 1
    Это происходит, только если чит-коды не включены. Помните, что значе- ние переменных reverseCheat и slowCheat равно True, пока удерживаются кла- виши Z и X, соответственно. Пока они удерживаются, значение переменной baddieAddCounter не увеличивается, так что в верхней части экрана не появятся новые злодеи.
    Когда значение переменной baddieAddCounter достигает значения
    ADDNEWBADDIERATE
    , приходит время добавить нового злодея. Сначала значение переменной baddieAddCounter сбрасывается до 0.
    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. }
    Код в строке 132 определяет размер злодея в пикселях. Размер будет слу- чайным целым числом в диапазоне от BADDIEMINSIZE до BADDIEMAXSIZE, то есть между константами со значениями 10 и 40, присвоенными им в строках кода 9 и 10, соответственно.
    В строке 133 создается новая структура данных злодея. Запомните, структура данных для baddies — это просто словарь с ключами 'rect', 'speed' и 'surface'. Ключ 'rect' содержит ссылку на объект Rect, который хранит ме- стоположение и размер злодея.
    Функция-конструктор pygame.Rect() имеет четыре параметра: координа- ту x верхней стороны области, координату y левой стороны области, а также ширину и высоту в пикселях.
    Злодей должен появиться в случайной позиции в верхней части окна, по- этому передайте random.randint(0, WINDOWWIDTH − baddieSize) для координаты

    402
    Глава 21
    x злодея. Причина, по которой вы передаете WINDOWWIDTH — baddieSize вместо переменной WINDOWWIDTH, заключается в том, что если левая сторона злодея на- ходится слишком далеко справа, тогда часть злодея выйдет за пределы окна, и не будет видна на экране.
    Нижняя сторона злодея должна располагаться прямо над верхней грани- цей окна, координата y которой равна 0. Чтобы поместить туда нижнюю сто- рону злодея, присвойте его верхней стороне значение 0 — baddieSize.
    Ширина и высота спрайта злодея должны быть одинаковыми (его изо- бражение имеет квадратную форму), поэтому передайте значение baddieSize в качестве третьего и четвертого аргументов.
    Скорость, с которой злодей перемещается вниз по экрану, задается в ключе 'speed'. Установите его равным случайному целому числу между
    BADDIEMINSPEED
    и BADDIEMAXSPEED.
    Затем код в строке 138 добавит недавно созданную структуру данных зло- дея в список структур данных злодея.
    138. baddies.append(newBaddie)
    Программа использует этот список, чтобы проверить, столкнулся ли спрайт игрока с каким-либо спрайтом злодея, и определить, где в окне ото- бражать злодеев.
    Перемещение спрайтов игрока и злодеев
    Четыре переменных перемещения moveLeft, moveRight, moveUp и moveDown принимают значения True и False, когда pygame генерирует события KEYDOWN и KEYUP, соответственно. Если спрайт игрока перемещается влево, а его левая сторона больше 0 (то есть больше левой границы окна), то объект playerRect должен перемещаться влево.
    140. # Перемещение игрока по экрану.
    141. if moveLeft and playerRect.left > 0:
    142. playerRect.move_ip(-1 * PLAYERMOVERATE, 0)
    Метод move_ip() будет перемещать объект Rect горизонтально или верти- кально на определенное количество пикселей. Первым аргументом move_ip() является количество пикселей, на которое объект Rect нужно переместить вправо (чтобы переместить его влево, передайте отрицательное целое чис- ло). Второй аргумент — на сколько пикселей переместить объект Rect вниз

    Игра «Ловкач» с графикой и звуком
    403
    (для перемещения вверх передайте отрицательное целое число). Например, playerRect.move_ip(10, 20)
    переместит объект Rect на 10 пикселей вправо и на
    20 пикселей вниз, а playerRect.move_ip(-5, -15) — на 5 пикселей влево и на
    15 пикселей вверх. Буквы ip в конце имени метода move_ip() означают «in place — на месте». Это связано с тем, что метод изменяет сам объект Rect вме- сто того, чтобы возвращать новый объект Rect с внесенными изменениями.
    Существует также метод move() , который не изменяет объект Rect, но вместо этого создает и возвращает новый объект Rect в новом расположении.
    Объект playerRect всегда будет перемещаться на количество пикселей
    PLAYERMOVERATE
    . Чтобы сделать отрицательное целое число из положительного, умножьте его на −1. В строке 142 выражение −1 * PLAYERMOVERATE равно −5, по- скольку в PLAYERMOVERATE хранится 5. Поэтому вызов playerRect.move_ip(-1 *
    PLAYERMOVERATE, 0)
    переместит playerRect на 5 пикселей влево от его текущего местоположения.
    Код в строках 143 по 148 делает то же самое для трех остальных направ- лений: вправо, вверх и вниз.
    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)
    Каждая из трех инструкций if в строках с 143 по 148 проверяет, присвое- но ли значение True соответствующей переменной перемещения и находится ли сторона объекта Rect игрока внутри окна. Затем она вызывает метод move_
    ip()
    для перемещения объекта Rect.
    Теперь код перебирает каждую структуру данных злодея в списке baddies, чтобы немного переместить злодеев вниз.
    150. # Перемещение злодеев вниз.
    151. for b in baddies:
    152. if not reverseCheat and not slowCheat:
    153. b['rect'].move_ip(0, b['speed'])
    Если ни один из чит-кодов не был активирован, то местоположение зло- дея изменяется на количество пикселей, равное его скорости (хранящейся в ключе 'speed').

    1   ...   31   32   33   34   35   36   37   38   39


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