PyGame. Введение
Довелось мне как-то пообщаться с этой библиотекой, чем и хотелось бы поделиться с вами, и себе зарубочку оставить, дабы не забывать:) В этом небольшом, надеюсь, посте, я на наглядном примере, опуская некоторые самые-самые теоретические основы (которые изложены в документации), покажу базовые принципы работы с библиотекой.
Задача.
Создать «игровое» пространство, в котором, при помощи клавиш-стрелок, можно будет перемещать объект.
Теория.
Прежде чем выкладывать листинги, остановлюсь на используемых методах из модулей библиотеки, описание которых взято из оф. документации.
Модуль image
1. pygame.image.load (filename): return Surface
Как можно догадаться, функция загружает некоторое изображение, и возвращеает в виде поверхности, типа, с которым при помощи функций pygame уже можно выполнять какие-либо операции (трансформировать, перемащать, удалять и пр.)
Модуль Surface
2. Surface.blit (source, dest, area=None, special_flags = 0)
Отрисовывает заданную поверхность (source) поверх базовой (Surface), где dest — кортеж (x, y), кординат отрисвоки, area — (width, height) — размеры source поверхности. На счет флагов, если честно пока не разбирался))
3. Surface.get_rect ()
Возвращет кортеж вида (x, y, width, height), где x, y — кординаты левого верхнего угла поверхности (Surface), width, height — соответственно ее размеры.
Модуль event
Он позволяет взаимодействовать с событиями и запросами. Иными словами, любое событие в pygame, нажатие клавиши например, помещается в список, состоящий из Event objects. Все эти «событийные объекты» имеют тип, получить доступ к которому можно путем Event.type.
4. pygame.event.get ()
Метод get () позволяет получить список событий.
Модуль Rect
Модуль для работы с кортежами типа rect.
5. Rect.move (X, Y)
Возвращает новый rect, в котором координаты смещены, относительно исходных, на заданные X, Y, в качестве которых может быть положительное или отрицательное целое число.
Практика.
Взяв на вооружение вышесказанное, получаем:
- # -*- coding: cp1251 -*-
- # Пример реализации движения при помощи pygame.
- from pygame import *
- import sys
- # Инициализируем загруженную библиотеку.
- init ( )
- # Создаем окно разрешением 640х480
- screen = display. set_mode ( ( 640 , 480 ) )
- # Устанавливаем название окна
- display. set_caption ( ‘example’ )
- # Загружаем фоновый рисунок, в формате:
- # jpg, png, gif(без анимации), bmp, pcx, tga(без сжатия), tif.
- background = image. load ( ‘background.bmp’ )
- # Отрисовываем рисунок в нашем окне
- screen. blit ( background, ( 0 , 0 ) )
- # Создаем игровой объект
- class GameObj:
- def __init__ ( self , img, x, y, step ) :
- self . img = img # Картинка объекта
- self . x = x # x, y — коодинаты начального положения
- self . y = y
- self . step = step # Шаг, на который будет смещаться объкт
- self . pos = img. get_rect ( ) . move ( x, y )
- def _move ( self , event ) :
- if event. key == K_UP: #273 код клавиши вверх
- self . pos = self . pos . move ( 0 , — self . step )
- if event. key == K_DOWN:
- self . pos = self . pos . move ( 0 , self . step )
- if event. key == 276 :
- self . pos = self . pos . move ( — self . step , 0 )
- if event. key == 275 :
- self . pos = self . pos . move ( self . step , 0 )
- avatar = image. load ( ‘player.bmp’ )
- # Инициируем игровой объект
- x = GameObj ( avatar, 320 , 220 , 10 )
- # Рисуем картинку объекта, в его координатах
- screen. blit ( x. img , x. pos )
- # Запускаем бесконечный цикл, чтобы окно не схлопнулось после появления 🙂
- while 1 :
- for i in event. get ( ) : # Перебор в списке событий
- if i. type == QUIT: # Обрабатываем событие шечка по крестику закрытия окна
- sys . exit ( )
- if i. type == KEYDOWN:
- screen. blit ( background, x. pos , x. pos )
- x._move ( i )
- screen. blit ( x. img , x. pos )
- # Обновляем изображение в окне, чтобы изменения в нем стали видны
- display. flip ( )
Послесловие.
Собственно вот и все, коротко и сердито:) Полистав огромное колл-во игр, выложенных на оф. сайте, и обнаружив там настоящие 3д поделки — удивился и возрадовался одновременно)) Хоть я и не собираюсь покорять игродельческие вершины, но приятно, что любимый язык настолько многомерен. Если кому-то будет интересна эта тема, и у меня не пропадет желание записывать — то непременно будет продолжение).
Работа с событиями
Дальше предполагается, что мы уже проходимся по собятиям в цикле for event in pygame.event.get:
Нажатие на кнопки
if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: vel_y = vel_y - 10 if event.key == pygame.K_DOWN: vel_y = vel_y + 10
На что стоит обратить внимание.
- Это проверка именно на cобытие нажатия а не «держания» клавиши, то есть сколько бы вы не держали нажатой клавишу, скорость изменится только 1 раз. Чтобы реагировать на постоянно зажатую кнопку, нужно делать немного иначе.
- pygame.KEYDOWN — это тип события (нажатие на кнопку)
- pygame.K_DOWN , pygame.K_UP — «ключи» события ( event.key )
Коды кнопок
Полный список здесь. Те которые вам могут пригодиться:
- K_UP , K_DOWN , K_RIGHT , K_LEFT — стрелки
- K_SPACE — пробел
- K_w , K_a , K_s , K_d — кнопки w a s d
Клик мышкой
if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: # левая кнопка мыши bird_pos = event.pos if event.button == 3: # правая кнопка мыши bird_image = new_image
- Определить какая кнопка была нажата на мышке можно используя значение event.button : 1 — left click
2 — middle click
3 — right click
4 — scroll up
5 — scroll down - Координаты нажатия находятся в event.pos .
Движение мышки
Не только нажатие, но и движение мышки тоже является событием. Действительно, что если нам нужно чтобы какой нибудь объект постоянно следил за курсором? Нужно запускать его движение тогда когда мышка движется.
Координаты хранятся также как и в предыдущем случае — в переменной event.pos .
if event.type == pygame.MOUSEMOTION: cursor_pos = event.pos
Как проверить зажата ли клавиша?
Часто бывает, что хочется реагировать не на одиночное событие нажатия клавиши, а проверять зажата ли она. Для этого можно в каждом кадре написать например такое условие
if pygame.key.get_pressed()[pygame.K_RIGHT]: x = x + 1
Работает это так: функция
pygame.key.get_pressed()
< pygame.K_UP: True, pygame.K_DOWN: False, pygame.K_RIGHT: True, pygame.K_LEFT: False, . >
Введение в объектно-ориентированное программирование: создание среды для нашего объекта с Pygame
А что если мы захотим, чтобы наша клякса танцевала? Тогда мы просто добавим в нашу функцию draw_environment метод blob.move() . Мы можем это сделать в любом месте, но добавим его в конец:
def draw_environment(blob): game_display.fill(WHITE) pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size) pygame.display.update() blob.move()
Наш полнй код на данный момент времени:
import pygame import random WIDTH = 800 HEIGHT = 600 WHITE = (255, 255, 255) BLUE = (0, 0, 255) RED = (255, 0, 0) game_display = pygame.display.set_mode((WIDTH,HEIGHT)) pygame.display.set_caption('Blob World') clock = pygame.time.Clock() class Blob: def __init__(self, color): self.x = random.randrange(0, WIDTH) self.y = random.randrange(0, HEIGHT) self.size = random.randrange(4,8) self.color = color def move(self): self.move_x = random.randrange(-1,2) self.move_y = random.randrange(-1,2) self.x += self.move_x self.y += self.move_y if self.x < 0: self.x = 0 elif self.x >WIDTH: self.x = WIDTH if self.y < 0: self.y = 0 elif self.y >HEIGHT: self.y = HEIGHT def draw_environment(blob): game_display.fill(WHITE) pygame.draw.circle(game_display, blob.color, [blob.x, blob.y], blob.size) pygame.display.update() blob.move() def main(): red_blob = Blob(RED) while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() draw_environment(red_blob) clock.tick(60) if __name__ == '__main__': main()
Теперь при запуске этого кода у нас будет прекрасная, извивающаяся клякса!
При подготовке материала использовались источники:
https://habr.com/ru/articles/56255/
https://mrtsepa.gitbooks.io/pygame-tutorial/content/reference/pygame/events.html
Введение в объектно-ориентированное программирование: создание среды для нашего объекта с Pygame