Pygame: Обучающий курс

Урок 0. Каркас программы

Установка

Лучший способ установить pygame — использовать инструмент pip, мы можем установить pygame с помощью следующей команды:

pip install pygame

Импорт библиотеки Pygame

Чтобы импортировать библиотеку pygame, убедитесь, что вы уже установили pygame. Откройте терминал или IDE, с которой вы хотите работать, и импортируйте эту библиотеку, чтобы проверить, установлен ли pygame или нет, с помощью приведенной ниже команды:

import pygame 

Эта библиотека импортирует все доступные модули pygame в пакет pygame. На изображении ниже показано, как это сделать с помощью командной строки. Если вы не обнаружите никаких ошибок и получите сообщение, как показано на изображении, это означает, что библиотека pygame успешно импортирована, и теперь вы можете продолжить. 

Урок 1. Каркас программы

Окно Pygame — это простое окно, как и любое другое окно, в котором мы отображаем экран нашей игры. Это первая задача, которую мы выполняем, чтобы мы могли отобразить наш вывод на что-то. Наша главная цель здесь — создать окно и поддерживать его работу до тех пор, пока пользователь не захочет выйти. Для выполнения этих задач сначала нам нужно установить пакет pygame и импортировать в него некоторые предопределенные функции.

Поэтапная реализация:

Шаг 1: Сначала мы импортируем и инициализируем все импортированные модули. Мы используем import pygame для импорта всех модулей и функцию .init() для инициализации этих модулей.

import pygame
pygame.init() 

Шаг 2: Инициализируйте окно для отображения. Мы используем функцию .set_mode() для создания окна. Мы передаем ширину и высоту нашего окна в качестве параметров функции set_mode().

pygame.display.set_mode((width_of_window,height_of_window))

Шаг 3: Держите это окно открытым, пока пользователь не нажмет кнопку выхода. Мы используем переменную, которая имеет значение true, пока пользователь не нажмет кнопку выхода. Чтобы игра продолжалась, мы используем цикл while и проверяем нашу переменную, истинна она или нет.

running  = True

while running:  
  
    for event in pygame.event.get():  
        if event.type == pygame.QUIT:  
           running = False

Файл 1_1

# импорт пакета pygame
import pygame

# инициализация импортированного модуля
pygame.init()

# отображение окна высоты
# 500 на 400
pygame.display.set_mode((400, 500))

# создание значения bool, которое проверяет
# если игра запущена
running = True

# продолжайте игру, все еще запущенно, это true
while running:
	
	# Проверьте наличие события, если пользователь нажал
	# любое событие в очереди
	for event in pygame.event.get():
		
		# если событие имеет тип quit, то
		# установите для running bool значение false
		if event.type == pygame.QUIT:
			running = False

Как получить размер окна PyGame?

Пошаговый подход:

  1. Импортировать pygame.
  2. Инициализировать pygame.
  3. Сформируйте экран, используя метод pygame.display.set_mode() .
  4. Получить размер сформированного экрана с помощью метода screen.get_size() .
  5. Выйти из pygame.

Ниже приведены некоторые примеры, основанные на описанном выше подходе:

# import package pygame
import pygame
 
# initialize pygame
pygame.init()
 
# Экран формы
screen = pygame.display.set_mode()
 
# получите размер по умолчанию
x, y = screen.get_size()
 
# выйти из pygame
pygame.display.quit()
 
# размер экрана (width x height)
print(x, y)

Выход :

1536 864

Пример 2:

# import package pygame
import pygame
 
# initialize pygame
pygame.init()
 
# Form screen
screen = pygame.display.set_mode((500, 500))
 
# get the size
x, y = screen.get_size()
 
# quit pygame
pygame.display.quit()
 
# view size (width x height)
print(x, y)

Выход :

500 500

Разрешение изменения размера окна в PyGame

Обычное окно PyGame

Пошаговый подход:

  1. Импортировать pygame .
  2. Установите заголовок и добавьте контент.
  3. Запустите пигейм.
  4. Выйти из pygame.

boolean buttonWasUp = true;
boolean ledEnabled = false;

void setup() {
  pinMode(10, OUTPUT); // определяем пин 10 как выход
  pinMode(2, INPUT_PULLUP); // определяем пин 2 как вход и подтягиваем его
}

Окно PyGame с изменяемым размером

Пошаговый подход:

  1. Импортировать pygame .
  2. Сформируйте экран с помощью метода pygame.display.set_mode() и разрешите изменение размера с помощью pygame.RESIZABLE .
  3. Установите заголовок и добавьте контент.
  4. Запустите пигейм.
  5. Выйти из pygame.

Пример:

# import package pygame
import pygame
  
# Установка первоначального размера 400x400
# и возможность менять размер
screen = pygame.display.set_mode((400, 400), 
                                 pygame.RESIZABLE)
  
# установить заголовок
pygame.display.set_caption('Resizable')
  
# run window
running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
  
# quit pygame after closing window
pygame.quit()

Как изменить цвет фона экрана в Pygame?

Pygame — это библиотека Python, предназначенная для разработки видеоигр. Pygame добавляет функциональность поверх превосходной библиотеки SDL. Это позволяет создавать полнофункциональные игры и мультимедийные программы на языке Python.

Используемые функции:

  • pygame.init(): эта функция используется для инициализации всех модулей pygame.
  • pygame.display.set_mode(): эта функция используется для инициализации экрана для отображения.
  • fill(): этот метод используется для заполнения экрана указанным цветом.

Пример 1. В этом примере для фона экрана устанавливается красный цвет.

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# Initializing surface
surface = pygame.display.set_mode((400, 300))

# Initializing RGB Color
color = (255, 0, 0)

# Changing surface color
surface.fill(color)
pygame.display.flip()

Пример 2: В этом примере используется цвет RGB, чтобы установить синий цвет экрана.

# Importing the library
import pygame

# Initializing Pygame modules
pygame.init()

# Initializing surface
surface = pygame.display.set_mode((400, 300))

# Initializing RGB Color
color = (0, 0, 255)

# Changing surface color
surface.fill(color)
pygame.display.flip()

Как изменить имя окна Pygame?

Окно PyGame — это простое окно, которое отображает нашу игру на экране окна. По умолчанию pygame использует «окно Pygame» в качестве заголовка и значок pygame в качестве логотипа для окна pygame. Мы можем использовать функцию set_caption() для изменения имени и set_icon() для установки значка нашего окна.

Чтобы изменить имя окна pygame:

Синтаксис: pygame.display.set_caption('Название окна')

Чтобы изменить значок окна pygame:

Синтаксис: pygame.display.set_icon(Иконка_имя)

Поэтапная реализация:

Шаг 1: Сначала мы импортируем и инициализируем все импортированные модули. Мы используем import pygame для импорта всех модулей и функцию .init() для инициализации этих модулей.

import pygame
pygame.init() 

Шаг 2: Инициализируйте окно для отображения. Мы используем функцию .set_mode() для создания окна. Мы передаем ширину и высоту нашего окна в качестве параметров функции set_mode().

pygame.display.set_mode((width_of_window,height_of_window))

Шаг 3: Чтобы изменить заголовок и значок окна pygame по умолчанию, мы используем функции .set_caption() и .set_icon() . Чтобы изменить значок, сначала мы загружаем изображение значка с помощью функции pygame.image.load («image_path»), а затем используем .set_icon() для изменения изображения по умолчанию.

pygame.display.set_caption('GeeksforGeeks')


Icon = pygame.image.load('gfglogo.png')


pygame.display.set_icon(Icon)

Шаг 4: Держите это окно открытым, пока пользователь не нажмет кнопку выхода. Мы используем переменную, которая имеет значение true, пока пользователь не нажмет кнопку выхода. Чтобы игра продолжалась, мы используем цикл while и проверяем нашу переменную, истинна она или нет.

running  = True

while running:  
    for event in pygame.event.get():  
        if event.type == pygame.QUIT:  
           running = False

Пример:

# import pygame module
import pygame

# initializing imported module
pygame.init()

# Displaying a window of height
# 500 and width 400
pygame.display.set_mode((400, 500))

# Here we set name or title of our
# pygame window
pygame.display.set_caption('GeeksforGeeks')

# Here we load the image we want to
# use
Icon = pygame.image.load('gfglogo.png')

# We use set_icon to set new icon
pygame.display.set_icon(Icon)

# Creating a bool value which checks if
# game is running
running = True

# Keep game running till running is true
while running:
	
	# Check for event if user has pushed
	# any event in queue
	for event in pygame.event.get():
		
		# If event is of type quit then set
		# running bool to false
		if event.type == pygame.QUIT:
			running = False

Как настроить игровой цикл в PygGame?

В этой статье мы увидим, как настроить игровой цикл в PyGame. Игровой цикл — это цикл, который поддерживает работу игры. Он продолжает работать до тех пор, пока пользователь не захочет выйти. Пока игровой цикл работает, он в основном выполняет следующие задачи:

  1. Обновите наше игровое окно, чтобы показать визуальные изменения
  2. Обновляйте наши игровые состояния на основе пользовательского ввода
  3. Обработка различных типов событий
  4. Держите игровое окно открытым

Просто игровой цикл — это цикл while, имеющий только одно условие, чтобы проверить, верно ли наше логическое условие для продолжения игры.

Настройка игрового цикла

Шаг 1: Объявите логическую переменную в true, которая будет использоваться для проверки того, хочет ли наш игрок продолжать играть в нашу игру или нет.  

keepGameRunning=true

Шаг 2: Создайте цикл while и проверьте приведенную выше логическую переменную, истинна она или нет. Если это правда, продолжайте цикл, что предполагает, что наш игровой цикл будет работать. В этом цикле while проверяется наличие событий, и, если событие завершено, установите вышеуказанную переменную слишком ложной, чтобы выйти из нашего игрового цикла и закрыть наше окно pygame.

while keepGameRunning:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:  
           keepGameRunning = False

Ниже приведена полная реализация.

В приведенном ниже коде мы создаем простой игровой цикл, который создает окно pygame и проверяет, является ли тип события quit, и, если это правда, завершает игру.

# import pygame package
import pygame

# initializing imported module
pygame.init()

# displaying a window of height
# 500 and width 400
pygame.display.set_mode((400, 500))

# Setting name for window
pygame.display.set_caption('GeeksforGeeks')

# creating a bool value which checks
# if game is running
running = True

# Game loop
# keep game running till running is true
while running:

	# Check for event if user has pushed
	# any event in queue
	for event in pygame.event.get():
	
		# if event is of type quit then set
		# running bool to false
		if event.type == pygame.QUIT:
			running = False


В приведенном ниже коде мы добавили еще одну задачу в наш игровой цикл, а именно обновление нашего экрана в каждом цикле. Здесь мы меняем цвет фона для каждого цикла, обновляя наш экран в каждом цикле.

# import pygame package
import pygame

# initializing imported module
pygame.init()

# displaying a window of height
# 500 and width 400
window = pygame.display.set_mode((400, 500))

# создание значения bool, которое проверяет
# if game is running
running = True

# настройка переменной для сохранения цвета
color = "red"

# keep game running till running is true
while running:

	# Check for event if user has pushed
	# any event in queue
	for event in pygame.event.get():
		
		# if event is of type quit then set
		# running bool to false
		if event.type == pygame.QUIT:
			running = False
	
	# установите цвет фона для нашего окна
	window.fill(color)
	
	# Обновите наше окно
	pygame.display.flip()
	
	# если цвет красный, измените его на зеленый и
	# и наоборот
	if(color == "red"):
		color = "green"
		
	else:
		color = "red"

Как изменить значок PyGame?

При создании видеоигры вы хотите установить свое изображение или логотип компании в качестве значка для игры? Если да, то вы можете легко сделать это, используя функцию set_icon() после объявления изображения, которое вы хотите установить в качестве значка. Прочтите статью, приведенную ниже, чтобы узнать подробнее. 

Синтаксис:

pygame_icon = pygame.image.load('#Введите изображение')
pygame.display.set_icon(pygame_icon)

Подход:

Шаг 1: Сначала импортируйте библиотеку Pygame.

import pygame

Шаг 2: Теперь создайте игру с графическим интерфейсом.

pygame.init()

Шаг 3: Далее установите размеры вашей игры с графическим интерфейсом.

screen = pygame.display.set_mode([#width of game, #height of game])

Шаг 4: Затем возьмите изображение в качестве входных данных, которое мы хотим установить в качестве значка.

img = pygame.image.load('#Enter the image')

Шаг 5: Затем установите изображение в качестве значка. Набор значков появится в верхнем левом углу, когда игра запущена.

pygame.display.set_icon(img)

Шаг 6: Позже установите текущее значение для запуска игры.

running = True

Шаг 7: Установите, что вы хотите, чтобы ваша игра делала, когда она находится в рабочем состоянии.

while running:
   for event in pygame.event.get():
  • Шаг 7.1: Когда приложение находится в рабочем состоянии, закройте его, если пользователь хочет выйти.
       if event.type == pygame.QUIT:
           running = False
  • Шаг 7.2: Кроме того, установите цвет фона, который вы хотите видеть в своем приложении.
       screen.fill(# RGB Value of Color)
  • Шаг 7.3: Затем заставьте ваше приложение делать все, что вы хотите, пока оно находится в рабочем состоянии.
  • Шаг 7.4: Сделав все, что хотите, обновите сделанные изменения.
   pygame.display.update()

Шаг 8: Наконец, выйдите из игры с графическим интерфейсом.

pygame.quit()

Ниже приведена реализация.

# Python program to change
# the Pygame icon

# Import the library Pygame
import pygame

# Construct the GUI game
pygame.init()

# Установите размеры графического интерфейса игры
screen = pygame.display.set_mode([600, 400])

# Возьмите изображение в качестве входных данных
img = pygame.image.load('2359.jpg')

# Установить изображение в качестве значка
pygame.display.set_icon(img)

# Set running value
running = True

# Настройка того, что происходит, когда игра
# находится в запущенном состоянии
while running:
	for event in pygame.event.get():

		# Закрыть, если пользователь выходит из игры
		if event.type == pygame.QUIT:
			running = False

	# Установите цвет фона
	screen.fill((255, 255, 0))

	# Нарисуйте круг на экране
	pygame.draw.circle(screen, (0, 0, 0), (300, 200), 75)

	# Update the GUI game
	pygame.display.update()

# Quit the GUI game
pygame.quit()

Поверхность Surface

При использовании Pygame поверхности обычно используются для представления внешнего вида объекта и его положения на экране. Все объекты, текст, изображения, которые мы создаем в Pygame, создаются с использованием поверхностей.

Создание поверхности

Создание поверхностей в pygame довольно просто. Нам просто нужно передать высоту и ширину с помощью кортежа в метод pygame.Surface() . Мы можем использовать различные методы для форматирования нашей поверхности по своему усмотрению. Например, мы можем использовать pygame.draw() для рисования фигур, мы можем использовать метод surface.fill() для заполнения поверхности. Теперь о реализации этих функций. Давайте обсудим синтаксис и параметры.

Синтаксис : pygame.surface()

Он принимает 4 аргумента кортеж ширины и высоты, флаги, глубину, маску.

pygame.draw():

Используется для рисования предмета, формы.

Синтаксис: Surface.rect(поверхность, цвет, прямоугольник)

Код для рисования прямоугольника с помощью метода pygame.draw.rect() приведен ниже:

# Importing the library
import pygame
import time

# Initializing Pygame
pygame.init()

# Creating the surface
sample_surface = pygame.display.set_mode((400,300))

# Choosing red color for the rectangle
color = (255,255,0)

# Drawing Rectangle
pygame.draw.rect(sample_surface, color,
				pygame.Rect(30, 30, 60, 60))

# The pygame.display.flip() method is used
# to update content on the display screen
pygame.display.flip()

surface_name.fill():

pygame.Surface.fill: используется для заливки цветом поверхности.

Синтаксис: pygame.Surface. заливка (цвет, прямоугольник = нет, special_flags = 0)

Код для заливки цветом поверхности с использованием метода surface_name.fill():

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# Creating the surface
sample_surface = pygame.display.set_mode((400,300))

# Choosing yellow color to fill
color = (255,255,0)

# filling color to the surface
sample_surface.fill(color)

# updating the display
pygame.display.flip()

Загрузка изображения на поверхность

Хотя мы можем рисовать фигуры и заполнять цвета на поверхности, нам все равно нужно иметь изображение на поверхности. Мы можем легко создать такую ​​поверхность с помощью метода pygame.image.load(). Этот метод принимает относительный или абсолютный путь к изображению в качестве входных данных.

Синтаксис: pygame.image.load(img) 

# Importing the library
import pygame


# Initializing Pygame
pygame.init()

# creating the display surface
display_surface = pygame.display.set_mode((500, 500 ))

# Creating the image surface
image = pygame.image.load('gfg_logo.png')

# putting our image surface on display
# surface
display_surface.blit(image,(100,100))

# updating the display
pygame.display.flip()

Добавление блиттинга

Чтобы поверхность отображалась, она должна быть отображена на экране. Блиттинг можно рассматривать как копирование пикселей одной поверхности на другую. Мы можем выполнить блитирование, используя метод surface.blit() , который принимает поверхность, которую нужно блитить, в качестве первого аргумента и кортеж координат в качестве второй координаты.

Syntax: pygame.Surface.blit(source, dest, area=None, special_flags=0)

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# creating the display surface
display_surface = pygame.display.set_mode((500, 500 ))

# Creating the first image surface
image1 = pygame.image.load('gfg_logo.png')

# Creating the second image surface
image2 = pygame.image.load('gfg_logo.png')

# putting our first image surface on
# display surface
display_surface.blit(image1,(0,0))

# putting our second image surface on
# display surface
display_surface.blit(image1,(300,300))

# updating the display
pygame.display.flip()

Теперь, когда мы уже обсудили некоторые поверхностные функции, такие как .blit(), .fill() и т. д., давайте обсудим некоторые более важные функции экранов pygame.

  • pygame.Surface.convert: создает копию поверхности с измененным форматом пикселей. Новый формат пикселей может быть определен из существующей поверхности или глубины, флагов и аргументов маски.

Syntax: pygame.Surface.convert(Surface=None)

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# Creating the surface
sample_surface = pygame.display.set_mode((400,300))

# changing the pixel format of an image
pygame.Surface.convert(sample_surface)

# updating the display
pygame.display.flip()

pygame.Surface.convert_alpha: создает новую копию поверхности с желаемым форматом пикселей. Новая поверхность будет в формате, подходящем для быстрого преобразования в заданный формат с попиксельной альфой. Если поверхность не задана, новая поверхность будет оптимизирована для переноса на текущий дисплей.

Syntax: pygame.Surface.convert_alpha(Surface) 

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# Creating the surface
sample_surface = pygame.display.set_mode((400,300))

# changing the pixel format
# of an image including per pixel alphas
pygame.Surface.convert_alpha(sample_surface)

# updating the display
pygame.display.flip()
  • pygame.Surface.copy: создает новую копию поверхности. Дублированная поверхность будет иметь те же форматы пикселей, цветовые палитры, настройки прозрачности и класс, что и оригинал.

Syntax: pygame.Surface.copy()

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# Creating the surface
sample_surface = pygame.display.set_mode((400,300))

# creating a copy of sample_surface
# and naming it as copied_surface
copied_surface=pygame.Surface.copy(sample_surface)

# updating the display
pygame.display.flip()




pygame.Surface.set_colorkey: установить текущий цветовой ключ для поверхности. При переносе этой поверхности на место назначения любые пиксели того же цвета, что и цветовой ключ, будут прозрачными.

Syntax: set_colorkey(Color, flags=0)  

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# creating the display surface
display_surface = pygame.display.set_mode((500, 500 ))

# Creating the image surface
image = pygame.image.load('gfg_logo.png')

# putting our image surface on display surface
# making the white colored part
# of the surface as transparent
pygame.Surface.set_colorkey (image, [255,255,255])

display_surface.blit(image,(100,100))

# updating the display
pygame.display.flip()

Результатом приведенного выше кода будет логотип geeksforgeeks на черной поверхности с белым пикселем, измененным на прозрачный.
 

  • pygame.Surface.get_colorkey: возвращает текущее значение цветового ключа для поверхности. Если цветовой ключ не задан, возвращается None.

Syntax: get_colorkey()

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# creating the display surface
display_surface = pygame.display.set_mode((500, 500))

# Creating the image surface
image = pygame.image.load('gfg_logo.png')

# putting our image surface on display surface
# making the white colored part of the surface
# as transparent
pygame.Surface.set_colorkey(image, [255, 255, 255])

# printing the colorkey value for the surface
print(pygame.Surface.get_colorkey(image))

display_surface.blit(image, (100, 100))

# updating the display
pygame.display.flip()

Вывод приведенного выше кода будет окном, показывающим различные поверхности, как показано в примере с get_colorkey, а также будет напечатано значение colorkey.

  • pygame.Surface.set_alpha: Альфа-значение, установленное для полного изображения поверхности. Передайте 0 для невидимого и 255 для полностью непрозрачного.

Syntax: set_alpha(value, flags=0) or set_alpha(None)

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# creating the display surface
display_surface = pygame.display.set_mode((500, 500 ))

# Creating the image surface
image = pygame.image.load('gfg_logo.png')

# putting our image surface on display surface
# making the alpha value of surface as 100
pygame.Surface.set_alpha(image, 100)

display_surface.blit(image,(100,100))

# updating the display
pygame.display.flip()

Результатом приведенного выше кода будет логотип geeksforgeeks, который будет слегка прозрачным, поскольку мы изменили его альфа-значение на 100.

  • pygame.Surface.get_alpha: возвращает текущее альфа-значение поверхности.

Syntax: get_alpha()

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# creating the display surface
display_surface = pygame.display.set_mode((500, 500 ))

# Creating the image surface
image = pygame.image.load('gfg_logo.png')

# putting our image surface on display surface
# making alpha value of image surface to 100
pygame.Surface.set_alpha(image, 100)

# printing the alpha value of the surface
print(pygame.Surface.get_alpha(image))

display_surface.blit(image,(100,100))

# updating the display
pygame.display.flip()

Вывод приведенного выше кода будет окном, показывающим различные поверхности, как показано в примере set_alpha, а также будет напечатано значение альфа.

Время Time

При использовании pygame нам иногда нужно выполнять определенные операции, включающие использование времени. Например, узнать, сколько времени работает наша программа, приостановить программу на определенное время и т. д. Для операций такого рода нам нужно использовать методы времени pygame. В этой статье мы обсудим различные методы, которые можно использовать для выполнения этих операций.

Функции, которые мы обсудим:

  • pygame.time.wait
  • pygame.time.get_ticks
  • pygame.time.delay
  • pygame.time.Clock

pygame.time.wait

Эта функция используется для приостановки работы программы на несколько секунд. в качестве параметра требуется время в миллисекундах. Например, чтобы продемонстрировать эту функцию, мы напишем простую программу, чтобы логотип geeksforgeeks появлялся на экране только через 5 секунд. Код для этого будет:

# importing pygame module
import pygame

# importing sys module
import sys

# initialising pygame
pygame.init()

# creating display
display = pygame.display.set_mode((500, 500))

# Creating the image surface
image = pygame.image.load('gfg_logo.png')

# putting our image surface on display surface
display.blit(image,(100,100))

# making the script wait for 5000 seconds
pygame.time.wait(5000)

# creating a running loop
while True:

	# creating a loop to check events that are occurring
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			pygame.quit()
			sys.exit()
	# updating the display
	pygame.display.flip()

Результатом этого будет то, что скрипт будет ждать 5 секунд, а затем обновит дисплей, чтобы отобразить логотип geeksforgeeks. 

Он немного менее точен, чем pygame.time.delay, который мы обсудим позже в этой статье, потому что он использует спящий режим, а другой использует процессор.

pygame.time.get_ticks

Эта функция выдает время в миллисекундах. Например, если мы хотим написать простой код для демонстрации этого примера, это может быть:

# importing pygame module
import pygame

# initialising pygame
pygame.init()

# creating a variable
i=0
while i<5:
	
	# storing the time in ticks variable
	ticks=pygame.time.get_ticks()
	
	# printing the variable ticks
	print(ticks)
	
	# increasing the value of i by 1
	i=i+1
	
	# pausing the script for 1 second
	pygame.time.wait(1000)

Время печатается для каждой итерации, включая время, на которое мы приостанавливали скрипт в каждой итерации.

pygame.time.delay

Эта функция работает так же, как функция pygame.time.wait, разница в том, что эта функция будет использовать процессор (а не спать), чтобы сделать задержку более точной. Пример кода можно написать так же, как функцию pygame.time.wait, просто заменив имя:

# importing pygame module
import pygame

# importing sys module
import sys

# initialising pygame
pygame.init()

# creating display
display = pygame.display.set_mode((500, 500))

# Creating the image surface
image = pygame.image.load('gfg_logo.png')

# putting our image surface on display surface
display.blit(image,(100,100))

# making the script wait for 5000 seconds
pygame.time.delay(5000)

# creating a running loop
while True:

	# creating a loop to check events that are occurring
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			pygame.quit()
			sys.exit()
	# updating the display
	pygame.display.flip()

pygame.time.Clock

Эта функция используется для создания объекта часов, который можно использовать для отслеживания времени. Ниже приведены различные методы объекта часов:

tick() : этот метод следует вызывать один раз за кадр. Он подсчитает, сколько миллисекунд прошло с момента предыдущего вызова. Если вы передадите необязательный аргумент частоты кадров, функция сделает задержку, чтобы игра работала медленнее, чем заданное количество тактов в секунду. Например, если мы передадим 10 в качестве аргумента, программа никогда не будет работать со скоростью более 10 кадров в секунду.

get_time(): используется для получения количества миллисекунд между двумя тиками().

get_fps() : предоставляет информацию о частоте кадров часов. он возвращает вывод в значении с плавающей запятой.

Простая программа для демонстрации этой функции может быть:

# importing the pygame module
import pygame

# initialising the pygame
pygame.init()

# declaring a variable i with value 0
i=0

# creating a clock object
clock=pygame.time.Clock()

# создание цикла на 5 итераций
while i<5:
	
	# установка частоты кадров программы на максимум 1 в секунду
	clock.tick(1)
	
	# время печати, использованное в предыдущем тике
	print(clock.get_time())
	
	# печать вычисляет частоту тактовых кадров
	print(clock.get_fps())
	i=i+1

Поскольку мы передали 1 в методе tick, он устанавливает максимальный fps равным 1. В результате время между каждым кадром приближается к 1000 миллисекундам.

Идём далее:

Файл 1-1

#Подключение библиотеки PyGame

import pygame

#Инициализация PyGame

pygame.init()

#Окно игры: размер, позиция

gameScreen = pygame.display.set_mode((400, 300))

#Модуль os - позиция окна
import os
x = 100
y = 100
os.environ['Sp_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)

#Параметры окна
size = [500, 500]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Test drawings")
gameScreen.fill((0,0,255))
pygame.display.flip()

При запуске программы мы не сможем корректно закрыть программу. Добавим цикл для выхода из программы.

# Цикл игры
runGame = True # флаг выхода из цикла игры
while runGame:
    # Отслеживание события: "закрыть окно"
    for event in pygame.event.get():
        if event.type == pygame.QUIT: runGame = False
# Выход из игры: 
pygame.quit()

Полный код будет такой:

Файл 1-2

# Подключение библиотеки PyGame
import pygame
# Инициализация PyGame
pygame.init()
# Окно игры: размер, позиция
gameScreen = pygame.display.set_mode((400, 300))
# Модуль os - позиция окна
import os
x = 100
y = 100
os.environ['Sp_VIDEO_WINDOW_POS'] = "%d,%d" % (x,y)
# Параметры окна
size = [500, 500]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Test drawings")
gameScreen.fill((0,0,255))
pygame.display.flip()
# Цикл игры
runGame = True # флаг выхода из цикла игры
while runGame:
    # Отслеживание события: "закрыть окно"
    for event in pygame.event.get():
        if event.type == pygame.QUIT: runGame = False
# Выход из игры: 
pygame.quit()

Покажем новый код:

Файл 1-3

#Подключаем библиотеки
import pygame
import random

#Создаем константы
WIDTH = 360 # Ширина
HEIGHT = 480 # Высота
FPS = 30 # Частота обновлений

#Задаем цвета
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)

#Создаем игру и окно
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("My Game")
clock = pygame.time.Clock()

#Цикл игры
running = True
while running:
# Держим цикл на правильной скорости
   clock.tick(FPS)
   # Ввод процесса (события)
   for event in pygame.event.get():
      # проверьте, закрывается ли окно
      if event.type == pygame.QUIT:
         running = False

   # Обновление
   # Рендеринг
   screen.fill(BLACK)
   # После отрисовки всего, обновляем экран
   pygame.display.flip()

pygame.quit()

Создание шаблона Pygame

У вас есть рабочий шаблон Pygame. Сохраните его в файле с понятным названием, например, pygame_template.py, чтобы можно было использовать его каждый раз при создании нового проекта pygame.

Теперь разберём по частям:

В начале программы нужно импортировать необходимые библиотеки и задать базовые переменные настроек игры:

# Pygame шаблон – скелет для нового проекта Pygame

import pygame

import random

WIDTH = 360

HEIGHT = 480

FPS = 30

Задаём цвета :

Каждый из трех основных цветов может иметь значение от 0 (выключен) до 255 (включен на 100%), так что для каждого элемента есть 256 вариантов.

В каждую константу прописываем соответствующий цвет.

# Задаем цвета

WHITE = (255, 255, 255)

BLACK = (0, 0, 0)

RED = (255, 0, 0)

GREEN = (0, 255, 0)

BLUE = (0, 0, 255)

Дальше необходимо открыть окно игры:

# Создаем игру и окно

pygame.init()

pygame.mixer.init()

screen = pygame.display.set_mode((WIDTH, HEIGHT))

pygame.display.set_caption(“My Game”) clock = pygame.time.Clock()

pygame.init() — это команда, которая запускает и инициализирует все импортированные модули pygame

pygame.mixer – для работы со звуковыми эффектами;

pygame. screen — окно программы, которое создается, когда мы задаем его размер в настройках.

pygame.time.Clock()создаёт объект, чтобы помочь отслеживать время.

Игровой цикл

В сердце каждой игры лежит цикл, который принято называть «игровым циклом». Он запускается снова и снова, делая все, чтобы работала игра. Каждый цикл в игре называется кадром.

Теперь необходимо создать игровой цикл:

# Цикл игры

running = True

while running:

    # Держим цикл на правильной скорости

    clock.tick(FPS)

    # Ввод процесса (события)

    for event in pygame.event.get():

        # проверьте, закрывается ли окно

        if event.type == pygame.QUIT:

            running = False

Игровой цикл — это цикл while, контролируемый переменной running. Если нужно завершить игру, необходимо всего лишь поменять значение running на False.

В результате цикл завершится. Теперь можно заполнить каждый раздел базовым кодом.

pygame.QUIT — событие, которое стартует после нажатия крестика и передает значение False переменной running, в результате чего игровой цикл заканчивается.

Обновление, рендеринг

# Обновление

    # Рендеринг

    screen.fill(BLACK)

    # После отрисовки всего, обновляем экран

    pygame.display.flip()

pygame.quit()

screen.fill(BLACK) заполняем весь экран цветом выбранной константы.

pygame.display.flip() обновляем экрана.

Урок 2. Графические примитивы

Есть четыре основных шага для отображения изображений в pygameокне:

  • Создайте объект поверхности отображения, используя display.set_mode() метод pygame.
  • Полностью заполните объект поверхности белым цветом, используя fill() метод отображения объекта поверхности pygame.
  • Рисование различных фигур на поверхностном объекте с помощью Primitive Drawing Functionspygame.
  • Показать объект поверхности дисплея в окне pygame, используя display.update()метод pygame.

Ниже приведена реализация:

# import pygame module in this program
import pygame

# activate the pygame library .
# initiate pygame and give permission
# to use pygame's functionality.
pygame.init()

# define the RGB value
# for white, green,
# blue, black, red
# colour respectively.
white = (255, 255, 255)
green = (0, 255, 0)
blue = (0, 0, 128)
black = (0, 0, 0)
red = (255, 0, 0)

# assigning values to X and Y variable
X = 400
Y = 400

# create the display surface object
# of specific dimension..e(X,Y).
display_surface = pygame.display.set_mode((X, Y ))

# set the pygame window name
pygame.display.set_caption('Drawing')

# completely fill the surface object
# with white colour
display_surface.fill(white)

# draw a polygon using draw.polygon()
# method of pygame.
# pygame.draw.polygon(surface, color, pointlist, thickness)
# thickness of line parameter is optional.
pygame.draw.polygon(display_surface, blue,
					[(146, 0), (291, 106),
					(236, 277), (56, 277), (0, 106)])
					
# draw a line using draw.line()
# method of pygame.
# pygame.draw.line(surface, color,
# start point, end point, thickness)
pygame.draw.line(display_surface, green,
				(60, 300), (120, 300), 4)

# draw a circle using draw.circle()
# method of pygame.
# pygame.draw.circle(surface, color,
# center point, radius, thickness)
pygame.draw.circle(display_surface,
		green, (300, 50), 20, 0)

# draw a ellipse using draw.ellipse()
# method of pygame.
# pygame.draw.ellipse(surface, color,
# bounding rectangle, thickness)
pygame.draw.ellipse(display_surface, black,
					(300, 250, 40, 80), 1)

# draw a rectangle using draw.rect()
# method of pygame.
# pygame.draw.rect(surface, color,
# rectangle tuple, thickness)
# thickness of line parameter is optional.
pygame.draw.rect(display_surface, black,
					(150, 300, 100, 50))

# infinite loop
while True :
	
	# iterate over the list of Event objects
	# that was returned by pygame.event.get() method.
	for event in pygame.event.get() :

		# if event object type is QUIT
		# then quitting the pygame
		# and program both.
		if event.type == pygame.QUIT :

			# deactivates the pygame library
			pygame.quit()

			# quit the program.
			quit()

		# Draws the surface object to the screen.
		pygame.display.update()

Вывод:

Pygame — это библиотека Python, предназначенная для разработки видеоигр. Pygame добавляет функциональность поверх превосходной библиотеки SDL. Это позволяет создавать полнофункциональные игры и мультимедийные программы на языке Python.

Используемые функции:

  • pygame.display.set_mode(): эта функция используется для инициализации поверхности для отображения. Эта функция принимает размер дисплея в качестве параметра.
  • pygame.display.flip(): эта функция используется для обновления содержимого всей поверхности экрана.
  • pygame.draw.rect(): эта функция используется для рисования прямоугольника. Он принимает поверхность, цвет и объект Rect pygame в качестве входных параметров и рисует прямоугольник на поверхности.

Пример 1: В этом примере рисуется прямоугольник, залитый красным цветом.

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# Initializing surface
surface = pygame.display.set_mode((400,300))

# Initializing Color
color = (255,0,0)

# Drawing Rectangle
pygame.draw.rect(surface, color, pygame.Rect(30, 30, 60, 60))
pygame.display.flip()

Пример 2. В этом примере рисуется прямоугольник с красной рамкой без заливки цветом внутри.

# Importing the library
import pygame

# Initializing Pygame
pygame.init()

# Initializing surface
surface = pygame.display.set_mode((400,300))

# Initializing Color
color = (255,0,0)

# Drawing Rectangle
pygame.draw.rect(surface, color, pygame.Rect(30, 30, 60, 60), 2)
pygame.display.flip()

Идём далее

Создадим структуру файла.

Файл 2

import pygame

# инизилизация и параметры окна
pygame.init()


WIDTH = 480 # Ширина экрана
HEIGHT = 480 # Высота экрана
FPS = 30 # Частота обновления


WIN = pygame.display.set_mode((WIDTH, HEIGHT))# Не изменяемый размер
#WIN = pygame.display.set_mode((600, 400), pygame.RESIZABLE)# Изменяемый размер


pygame.display.set_caption("2 урок") # Название иконки
pygame.display.set_icon(pygame.image.load("pl_up.png")) # Картинка иконки

bg = pygame.image.load('bg.png') # Фон страницы (картинка)

# Цвета
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
SKYBLUE = (0, 255, 255)
BROUN = (102, 51, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)




clock = pygame.time.Clock()

#wall_1 = pygame.Rect((50, 40,), 20)

 
# функция отрисовки окна
def drawWindow():
    # рисуем фон 
    WIN.blit(bg, (0, 0)) # Фон экрана по картинке
    # WIN.fill(BLACK) # Фон экрана по цвету
    
    # рисуем тестовый квадратик
    pygame.draw.rect(WIN, RED, (60, 120, 90, 80))
    pygame.draw.rect(WIN, BLUE, (100, 10, 50, 100), 2)

    # рисуем тестовую линию
    pygame.draw.line(WIN, GREEN, (200, 20), (350, 50))

    # рисуем тестовую ломаную линию
    pygame.draw.lines(WIN, RED, True, [(200, 80), (250, 80), (300, 200)], 2)

    
    # рисуем тестовые линии
    pygame.draw.lines(WIN, RED, True, [(200, 80), (250, 80), (300, 200)], 2)
    pygame.draw.aalines(WIN, RED, True, [(300, 80), (350, 80), (400, 200)], 2)
    
    # рисуем тестовые полигоны
    pygame.draw.polygon(WIN, WHITE, [[150, 210], [180, 250], [90, 290], [30, 230]])
    pygame.draw.polygon(WIN, WHITE, [[150, 310], [180, 350], [90, 390], [30, 330]], 1)

    # рисуем тестовый круг
    pygame.draw.circle(WIN, BLUE, (300, 250), 40)

    # рисуем тестовый элипс
    pygame.draw.ellipse(WIN, BLUE, (300, 300, 100, 50), 1)

    # рисуем тестовую дугу
    pi = 3.14
    pygame.draw.arc(WIN, RED, (450, 30, 50, 150), pi, 2*pi, 5)


    

    # обновление экрана
   # pygame.display.flip()
    pygame.display.update()


# основная функция игры, тут проверяются все условия, и тут вся логика
run = True
while run:
    clock.tick(FPS)
    # выход из игры
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    


    drawWindow()
pygame.quit()

Разберем код:

Импорт библиотеки

import pygame

Инициализация окна

pygame.init()

Создание констант, для передачи значений размеров

WIDTH = 480 # Ширина экрана
HEIGHT = 480 # Высота экрана
FPS = 30 # Частота обновления

Варианты размера окна. Либо через константы WIDTH, HEIGHT

WIN = pygame.display.set_mode((WIDTH, HEIGHT))# Не изменяемый размер

Либо с первоначальым размером 600 на 400 и изменяемым размером.

WIN = pygame.display.set_mode((600, 400), pygame.RESIZABLE)# Изменяемый размер

Вводим значение текста в названии заголовка программы.

pygame.display.set_caption(“2 урок”) # Название иконки

Можем добавить иконку в заголовке игры. Картинка иконки должна быть с файлом.


pygame.display.set_icon(pygame.image.load(“pl_up.png”)) # Картинка иконки

Можно задать в качестве фона, выбранную картинку. Картинка должна быть нужного размера и находится в папке с файлом программы.

bg = pygame.image.load(‘bg.png’) # Фон страницы (картинка)

Создадим константы с настроенными цветами.

# Цвета

RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
SKYBLUE = (0, 255, 255)
BROUN = (102, 51, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

Создаем объект, чтобы помочь отслеживать время

clock = pygame.time.Clock()

Создаем функцию по отрисовки окна.

def drawWindow():
   # рисуем фон
   WIN.blit(bg, (0, 0)) # Фон экрана по картинке
   # WIN.fill(BLACK) # Фон экрана по цвету

   # рисуем тестовый квадратик
   pygame.draw.rect(WIN, RED, (60, 120, 90, 80))
   pygame.draw.rect(WIN, BLUE, (100, 10, 50, 100), 2)

   # рисуем тестовую линию
   pygame.draw.line(WIN, GREEN, (200, 20), (350, 50))

   # рисуем тестовую ломаную линию
   pygame.draw.lines(WIN, RED, True, [(200, 80), (250, 80), (300, 200)], 2)


   # рисуем тестовые линии
   pygame.draw.lines(WIN, RED, True, [(200, 80), (250, 80), (300, 200)], 2)
   pygame.draw.aalines(WIN, RED, True, [(300, 80), (350, 80), (400, 200)], 2)

   # рисуем тестовые полигоны
   pygame.draw.polygon(WIN, WHITE, [[150, 210], [180, 250], [90, 290], [30, 230]])
   pygame.draw.polygon(WIN, WHITE, [[150, 310], [180, 350], [90, 390], [30, 330]], 1)

   # рисуем тестовый круг
   pygame.draw.circle(WIN, BLUE, (300, 250), 40)

   # рисуем тестовый элипс
   pygame.draw.ellipse(WIN, BLUE, (300, 300, 100, 50), 1)

   # рисуем тестовую дугу
   pi = 3.14
   pygame.draw.arc(WIN, RED, (450, 30, 50, 150), pi, 2*pi, 5)

В созданной функции

Здесь либо принимаем за фон (через bg) картинку

WIN.blit(bg, (0, 0)) # Фон экрана по картинке

Либо используем в качестве фона константы с выбранными цветами (тогда надо закомментировать строку

bg = pygame.image.load(‘bg.png’) # Фон страницы (картинка)

WIN.fill(BLACK) # Фон экрана по цвету

Далее рассмотрим функции модуля pygame.draw для рисования графических примитивов:

  • pygame.draw.rect(surface, …) – прямоугольник;
  • pygame.draw.line(surface, …) – линия;
  • pygame.draw.aaline(surface, …) – сглаженная линия;
  • pygame.draw.lines(surface, …) – ломаная линия;
  • pygame.draw.aalines(surface, …) – ломаная сглаженная линия;
  • pygame.draw.polygon(surface, …) – полигон;
  • pygame.draw.circle(surface, …) – круг;
  • pygame.draw.ellipse(surface, …) – эллипс;
  • pygame.draw.arc(surface, …) – дуга.

Обратите внимание у всех этих функций первым параметром идет surface – поверхность, на которой выполняется рисование (в нашем примере поверхность имеет назвние WIN .

Забегая вперед отмечу, что таких поверхностей можно создавать множество, накладывая друг на друга. Но на этом занятии мы будем использовать базовую поверхность, представляющую клиентскую область окна приложения:

Ссылку на этот объект можно получить в момент создания окна:

WIN = pygame.display.set_mode((WIDTH, HEIGHT))

(здесь WIN – ссылка на базовый объект Surface). Давайте теперь нарисуем в окне прямоугольник с помощью функции rect:

pygame.draw.rect(WIN, (255,255,255), (10,10, 50, 100))

Мы здесь первым параметром указали главную поверхность, затем, цвет прямоугольника и его размеры.

Цвет определяется в формате (R, G, B). Причем, каждая цветовая компонента меняется в диапазоне от 0 до 255:

  • 0 – отсутствие цветовой составляющей;
  • 255 – полная насыщенность цветовой составляющей.

В данном случае мы включаем все три цветовые компоненты по максимуму и получаем белый цвет. Далее, размеры прямоугольника определяются по формату:

(x, y, width, height)

  • x, y – начальные координаты прямоугольника;
  • width, height – ширина и высота прямоугольника.

Обратите внимание, что координаты откладываются от верхнего левого угла и ось Oy направлена вниз (а не вверх, как мы привыкли по математике).

Итак, указание нарисовать прямоугольник даны. Но если сейчас выполнить программу, то мы ничего не увидим на экране. Почему? Это связано с тем, что базовый объект Surface использует механизм рисования, известный как буферизация вывода.

Ее принцип проще пояснить на таком рисунке. Представим, что объект Surface имеет две стороны A и B:

Изначально мы видим сторону B, но рисование выполняется на противоположной стороне – A. Затем, чтобы отобразить нарисованные объекты, мы должны перевернуть объект Surface другой стороной.

В PyGame это делается с помощью функции flip():

pygame.display.flip()

Теперь при запуске программы мы видим сторону A с нарисованным прямоугольником. В этом заключается принцип буферизации вывода графической информации. Но спрашивается: зачем все это нужно? Почему бы сразу не рисовать на видимой стороне объекта? В этом случае при большом числе объектов и сложной анимации пользователь будет замечать процесс отрисовки текущего кадра игры. И это негативно скажется на визуальном восприятии игрового процесса. Чтобы перерисовка кадров проходила незаметно для человеческого глаза, как раз и используется механизм буферизации.

Помимо метода flip() можно использовать похожий метод:

pygame.display.update(rectangle)

Здесь rectangle – это прямоугольная область, которую требуется перерисовать (по умолчанию, если ничего не указано, то перерисовывается вся клиентская область и метод update повторяет метод flip).

Так как метод update более гибкий, то в дальнейшем я буду использовать именно его.

Итак, мы с вами нарисовали закрашенный прямоугольник. Если нужно нарисовать не закрашенный, то следует указать следующий параметр – толщину линии:

pygame.draw.rect(sc, (0, 0, 255), (100, 10, 50, 100), 2)

Разумеется, все функции рисования должны следовать до метода update.

Наконец, последний важный штрих. Цвета заливки или линий обычно задаются вначале в виде констант, а затем, уже используются в функциях рисования:

WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
 
pygame.draw.rect(sc, WHITE, (10, 10, 50, 100))
pygame.draw.rect(sc, BLUE, (100, 10, 50, 100), 2)
pygame.display.update()

Так программа выглядит более читабельной. Давайте теперь посмотрим как рисуются остальные графические примитивы:

WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
pygame.draw.rect(sc, WHITE, (10, 10, 50, 100))
pygame.draw.rect(sc, BLUE, (100, 10, 50, 100), 2)
 
pygame.draw.line(sc, GREEN, (200, 20), (350, 50))
pygame.draw.aaline(sc, GREEN, (200, 40), (350, 70))
 
pygame.draw.lines(sc, RED, True, [(200, 80), (250, 80), (300, 200)], 2)
pygame.draw.aalines(sc, RED, True, [(300, 80), (350, 80), (400, 200)], 2)
 
pygame.draw.polygon(sc, WHITE, [[150, 210], [180, 250], [90, 290], [30, 230]])
pygame.draw.polygon(sc, WHITE, [[150, 310], [180, 350], [90, 390], [30, 330]], 1)
 
pygame.draw.circle(sc, BLUE, (300, 250), 40)
pygame.draw.ellipse(sc, BLUE, (300, 300, 100, 50), 1)
 
pi = 3.14
pygame.draw.arc(sc, RED, (450, 30, 50, 150), pi, 2*pi, 5)

Вот такие примитивы существуют в PyGame.

Основная функция игры, тут проверяются все условия, и тут вся логика. Здесь пока присутствует функция закрытия программы.

run = True
while run:
clock.tick(FPS)
# выход из игры
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False

Ну и последняя часть кода

   drawWindow()
pygame.quit()

Рисование базовых элементов
модуль pygame.draw

pygame.draw.rectнарисовать прямоугольную форму
pygame.draw.polygonфигуру с любым количеством сторон
pygame.draw.circleкруг вокруг точки
pygame.draw.ellipseнарисовать круглую форму внутри прямоугольника
pygame.draw.arcнарисовать секцию эллипса
pygame.draw.lineнарисовать сегмент прямой линии
pygame.draw.linesдля рисования нескольких смежных отрезков
pygame.draw.aalineрисовать тонкую линию
pygame.draw.aalinesнарисовать связанную последовательность сглаженных линий

МЕТОДЫ РАБОТЫ С RECT

pygame.Rect.copyВозвращает новый прямоугольник, имеющий ту же позицию и размер, что и оригинал.
pygame.Rect.moveВозвращает новый прямоугольник, перемещаемый данным смещением. Аргументы x и y могут быть любым целочисленным значением, положительным или отрицательным.
pygame.Rect.move_ipТо же, что и метод Rect.move (), но работает на месте.
pygame.Rect.inflateувеличивать или уменьшать размер прямоугольника, на месте
pygame.Rect.inflate_ipувеличивать или уменьшать размер прямоугольника, на месте
pygame.Rect.clampперемещает прямоугольник внутри другого
pygame.Rect.clamp_ipперемещает прямоугольник внутри другого, на месте
pygame.Rect.clipобрезает прямоугольник внутри другого
pygame.Rect.unionсоединяет два прямоугольника в один
pygame.Rect.union_ipсоединяет два прямоугольника в один, на месте
pygame.Rect.unionallобъединение многих прямоугольников
pygame.Rect.unionall_ipобъединение многих прямоугольников, на месте
pygame.Rect.fitизменить размер и переместить прямоугольник учмиывая соотношение сторон
pygame.Rect.normalizeкорректировать отрицательные размеры
pygame.Rect.containsпроверить, находится ли один прямоугольник внутри другого
pygame.Rect.collidepointпроверить, находится ли точка внутри прямоугольника
pygame.Rect.colliderectтест, пересекаются ли два прямоугольника
pygame.Rect.collidelistпроверить, пересекается ли хоть один прямоугольник в списке
pygame.Rect.collidelistallпересекаются ли все прямоугольники в списке
pygame.Rect.collidedictпроверить, если один прямоугольник в словаре пересекается
pygame.Rect.collidedictallпересекаются ли все прямоугольники в словаре

Урок 3. Как обрабатывать события от клавиатуры

Любая, даже самая простая игра предполагает взаимодействие с пользователем. Часто для этого используется клавиатура (или тачпад) или мышь. На этом занятии мы с вами увидим как происходит обработка событий от клавиатуры и какие нюансы здесь существуют.

Вообще, за обработку событий отвечает модуль

pygame.event

и ранее мы уже познакомились с методом

pygame.event.get()

который возвращал коллекцию событий, произошедших с момента его последнего вызова.

Причем, каждое конкретное событие – это объект, унаследованный от базового класса Event.

Этот базовый класс определяет свойство type, в котором сохраняется тип события. Остальные свойства объектов событий зависят от их типа (для клавиатуры одни, для мыши другие, для джойстика – третьи и т.д.). Причем, свойство type принимает несколько разных значений для нажатия клавиш, например:

  • event.type == pygame.KEYDOWN – клавиша нажата;
  • event.type == pygame.KEYUP – клавиша отпущена.

То есть, тип – это не только тип события, но и его конкретизация – какое именно событие произошло.

Давайте в качестве примера создадим программу, которая при нажатии на курсорные клавиши вправо-влево будет перемещать прямоугольник на экране:

Файл 3

import pygame

# инизилизация и параметры окна
pygame.init()


WIDTH = 480 # Ширина экрана
HEIGHT = 480 # Высота экрана
FPS = 30 # Частота обновления


WIN = pygame.display.set_mode((WIDTH, HEIGHT))# Не изменяемый размер
#WIN = pygame.display.set_mode((600, 400), pygame.RESIZABLE)# Изменяемый размер


pygame.display.set_caption("2 урок") # Название иконки
pygame.display.set_icon(pygame.image.load("pl_up.png")) # Картинка иконки

bg = pygame.image.load('bg.png') # Фон страницы (картинка)

# Цвета
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
SKYBLUE = (0, 255, 255)
BROUN = (102, 51, 0)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)


clock = pygame.time.Clock()

#wall_1 = pygame.Rect((50, 40,), 20)

 
# функция отрисовки окна
def drawWindow():
    # рисуем фон 
    WIN.blit(bg, (0, 0)) # Фон экрана по картинке
    # WIN.fill(BLACK) # Фон экрана по цвету

    

    # обновление экрана
   # pygame.display.flip()
    pygame.display.update()


# основная функция игры, тут проверяются все условия, и тут вся логика
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                print('Левая стрелка')
            elif event.key == pygame.K_RIGHT:
                print('Правая стрелка')
            elif event.key ==pygame.K_UP:
                print('Стрелка вверх')
            elif event.key ==pygame.K_DOWN:
                print('Стрелка вниз')

    


    drawWindow()
pygame.quit()

После запуска скрипта при нажатии стрелок на клавиатуре в стандартный вывод будут выводится строки с информацией о нажатой клавише.

Постоянной записи не происходит, как можно было ожидать. Все дело в том, что при нажатии клавиши в PyGame формируется только одно событие pygame.KEYDOWN.

После того, как мы его прочитали из очереди и обработали, повторного такого события там уже нет и, соответственно, условие event.type == pygame.KEYDOWN не срабатывает.

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                print('Левая стрелка')
            elif event.key == pygame.K_RIGHT:
                print('Правая стрелка')
            elif event.key ==pygame.K_UP:
                print('Стрелка вверх')
            elif event.key ==pygame.K_DOWN:
                print('Стрелка вниз')

pygame отслеживает все происходящие в игре события и позволяет нам их обрабатывать. При возникновении события создается экземпляр класса Event. Каждый экземпляр этого класса имеет определенный список свойств. Одно из этих свойств – это свойство type. Именно оно позволяет нам понять, какое событие произошло.

События клавиатуры имеют тип KEYDOWN.

Вважное свойство – это свойство key. Для нас оно представляет интерес, когда мы обнаружили событие с типом KEYDOWN. С помощью свойства key мы можем узнать, какая клавиша была нажата.

Объект event

Модуль pygame.event для обработки очереди событий

pygame.event.pumpЕсли вы не используете другие функции событий в своей игре, вы должны вызвать pygame.event.pump (), чтобы позволить pygame обрабатывать внутренние действия
pygame.event.getполучает события из очереди
pygame.event.pollполучить одно событие из очереди
pygame.event.waitждёт одиночного события из очереди
pygame.event.peekпроверить, ждут ли очереди события определённого типа
pygame.event.clearудалить все события из очереди
pygame.event.event_nameвозвращает имя для типа события. Строка находится в стиле WordCap
pygame.event.set_blockedпроверяет, какие события не разрешены в очереди
pygame.event.set_allowedпроверяет, какие события разрешены в очереди
pygame.event.get_blockedпроверить, заблокирован ли тип события из очереди
pygame.event.set_grabпроверяет совместное использование устройств ввода с другими приложениями
pygame.event.get_grabпроверить, работает ли программа на устройствах ввода данных
pygame.event.postпоместить новое событие в очередь
pygame.event.Eventсоздать новый объект события
pygame.event.EventTypeОбъект Python, представляющий событие SDL. Экземпляры пользовательских событий создаются с вызовом функции Event. Тип EventType не может быть напрямую вызван. Экземпляры EventType поддерживают назначение и удаление атрибутов.

Урок 4 Как обрабатывать события от мыши

На этом занятии мы с вами познакомимся с обработкой событий от мыши. Всего в PyGame существует четыре их типа (значение атрибута type объекта Event):

  • pygame.MOUSEBUTTONDOWN – нажатие кнопки мыши;
  • pygame.MOUSEBUTTONUP – отпускание кнопки мыши;
  • pygame.MOUSEMOTION – перемещение курсора мыши;
  • pygame.MOUSEWHEEL – кручение колесика мыши.

Давайте для начала рассмотрим пример обработки события pygame.MOUSEBUTTONDOWN:

Файл 4

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("События от мыши")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            print("Нажата кнопка: ", event.button)
 
    clock.tick(FPS)

Здесь при возникновении события pygame.MOUSEBUTTONDOWN в консоль выводится информация о номере нажатой кнопки, используя свойство button объекта event.

Причем, это свойство существует только в событиях от мыши. Поэтому, мы сначала должны проверить, что объект Event действительно соответствует одному из событий мыши и только потом обращаться к свойству button. Иначе, возникнет исключение, что такого атрибута не существует.

После запуска этой программы мы видим, что кнопкам мыши присвоены следующие значения:

  • 1 – левая кнопка;
  • 2 – центральная;
  • 3 – правая кнопка;
  • 4 – для колесика.

Если в этой программе добавить следующие две строчки:

       elif event.type == pygame.MOUSEMOTION:
            print("Позиция мыши: ", event.pos)

То в консоли мы увидим кортеж из координат положения мыши относительно клиентской области окна. То есть, свойство pos хранит координаты мыши и мы ими всегда можем воспользоваться.

Файл 4-1

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("События от мыши")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        elif event.type == pygame.MOUSEMOTION:
            print("Позиция мыши: ", event.pos)
 
    clock.tick(FPS)

Если вместо атрибута pos записать атрибут rel:

print("Смещение мыши: ", event.rel)

то увидим относительные смещения курсора мыши (относительно положения в предыдущем событии MOUSEMOTION). Причем, свойство rel существует только для события pygame.MOUSEMOTION.

Файл 4-2

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("События от мыши")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        elif event.type == pygame.MOUSEMOTION:
            print("Смещение мыши: ", event.rel)
 
    clock.tick(FPS)

Давайте теперь рассмотрим программу, которая позволяет рисовать в окне прямоугольник с помощью мыши. Она будет следующей:

Файл 4-3

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("События от мыши")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()

flStartDraw = False
sp = ep = None
 
sc.fill(WHITE)
pygame.display.update()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            flStartDraw = True
            sp = event.pos
        elif event.type == pygame.MOUSEMOTION:
            if flStartDraw:
                pos = event.pos
 
                width = pos[0] - sp[0]
                height = pos[1] - sp[1]
 
                sc.fill(WHITE)
                pygame.draw.rect(sc, RED, pygame.Rect(sp[0], sp[1], width, height))
                pygame.display.update()
        elif event.type == pygame.MOUSEBUTTONUP and event.button == 1:
            flStartDraw = False
 
    clock.tick(FPS)

Ее работа вполне очевидна. При нажатии на левую кнопку мыши мы устанавливаем флаг flStartDraw в значение True, т.е. включаем режим рисования при перемещении мыши. Соответственно, при событии MOUSEMOTION срабатывает условие и рисуется прямоугольник от начальной координаты sp до текущей позиции pos. При отпускании левой кнопки мыши, переменная flStartDraw становится равной False.

Однако, обратите внимание, события MOUSEBUTTONDOWN и MOUSEBUTTONUP срабатывают только один раз. То есть, если все время держать нажатой кнопку мыши, то произойдет только одно событие MOUSEBUTTONDOWN. А вот событие MOUSEMOTION происходит постоянно при каждом перемещении курсора мыши в клиентской области окна.

Если на каждой итерации главного цикла нужно определять: нажата ли какая-либо кнопка мыши, то следует использовать модуль

pygame.mouse

в котором, в частности, имеется функция:

pygame.mouse.get_pressed()

Она работает аналогично функции pygame.key.get_pressed() – определения нажатия клавиш, о которой мы говорили на прошлом занятии. Здесь все то же самое, только с кнопками мыши. На выходе pygame.mouse.get_pressed() выдает кортеж с тремя значениями:

Единица соответствует нажатой кнопке в соответствии с ее индексом:

  • 0 – левая кнопка;
  • 1 – центральная;
  • 2 – правая кнопка.

Перепишем предыдущую программу с использованием этой функции:

Файл 4-4

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("События от мыши")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()

flStartDraw = False
sp = ep = None
 
sp = None
 
sc.fill(WHITE)
pygame.display.update()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    pressed = pygame.mouse.get_pressed()
    if pressed[0]:
        pos = pygame.mouse.get_pos()
 
        if sp is None:
            sp = pos
 
        width = pos[0] - sp[0]
        height = pos[1] - sp[1]
 
        sc.fill(WHITE)
        pygame.draw.rect(sc, RED, pygame.Rect(sp[0], sp[1], width, height))
        pygame.display.update()
    else:
        sp = None
 
    clock.tick(FPS)

Смотрите, мы здесь вначале проверяем нажатие левой кнопки мыши (индекс 0) и если величина sp равна None, то начальной позиции для рисования прямоугольника еще нет и ее нужно приравнять текущей позиции курсора. Текущая позиция определяется с помощью функции get_pos(). Затем, удерживая нажатой левую кнопку и перемещая мышь, мы будем получать другие значения pos, но начальная позиция sp будет неизменной. В результате выполняется рисование прямоугольника. При отпускании левой кнопки, значение sp вновь становится равным None.

Наконец, можно скрыть курсор мыши с помощью функции:

pygame.mouse.set_visible(False)

И отобразить свой собственный, например, так:

Файл 4-5

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("События от мыши")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()

flStartDraw = False
sp = ep = None
 
sp = None
 
sc.fill(WHITE)
pygame.mouse.set_visible(False)
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    sc.fill(WHITE)
 
    pos = pygame.mouse.get_pos()
    if pygame.mouse.get_focused():
        pygame.draw.circle(sc, BLUE, pos, 7)
 
    pressed = pygame.mouse.get_pressed()
    if pressed[0]:
        if sp is None:
            sp = pos
 
        width = pos[0] - sp[0]
        height = pos[1] - sp[1]
        pygame.draw.rect(sc, RED, pygame.Rect(sp[0], sp[1], width, height))
    else:
        sp = None
 
    pygame.display.update()
 
    clock.tick(FPS)

Мы здесь в каждой позиции скрытого курсора рисуем синий кружок радиусом 7. При этом проверяем: находится ли курсор в области окна (иначе, его рисовать нет смысла).

Конечно, это не все функции модуля pygame.mouse, подробнее можно почитать на странице официальной документации:

Модуль pygame.mouse для работы с мышью

pygame.mouse.get_pressedполучить состояние кнопок мыши
pygame.mouse.get_posполучить позицию курсора мыши
pygame.mouse.get_relполучить количество движений мыши
pygame.mouse.set_posустановить позицию курсора мыши
pygame.mouse.set_visibleскрыть или показать курсор мыши
pygame.mouse.get_focusedпроверяет, принимает ли дисплей ввод мыши
pygame.mouse.set_cursorустановить изображение для курсора мыши
pygame.mouse.get_cursorполучить изображение для курсора мыши

Урок 5 Создание поверхностей

До сих пор мы с вами выполняли рисование в клиентской области окна, используя переменную sc (или другую):

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Surface")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)

Эта переменная ссылается на класс Surface, который связан с окном всего приложения. Однако, при необходимости, мы можем создать дополнительные поверхности рисования, используя конструктор класса Surface, например, так:

surf = pygame.Surface((200, 200))
surf.fill(RED)
sc.blit(surf, (50, 50))
pygame.display.update()

Файл 5-1

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Surface")
pygame.display.set_icon(pygame.image.load("pl_down.png"))


 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

surf = pygame.Surface((200, 200))
surf.fill(RED)
sc.blit(surf, (50, 50))
pygame.display.update()


 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)

В результате на поверхности sc будет отображена еще одна поверхность surf со всем своим содержимым:

Спрашивается: зачем создавать дополнительный объект surf, когда можно все рисовать непосредственно на основной поверхности sc? Это сделано главным образом для удобства: мы можем на дополнительной поверхности нарисовать сложную графическую информацию, а затем, переносить ее в область главного окна, просто, используя операцию:

sc.blit(surf, (x, y))

Здесь x, y – координаты верхнего левого угла, от которого позиционируется вторая поверхность surf. Затем, достаточно менять в цикле координаты x, y для создания простой анимации нашего графического образа. Перерисовывать каждый раз сложную графическую информацию уже не придется. В этом основное достоинство таких поверхностей.

Класс Surface имеет множество полезных методов. Подробно все их можно посмотреть на странице официальной документации:

Один из них мы уже использовали – это метод:

Surface.blit(source, pos, …)

который отображает содержимое поверхности source на поверхности Surface. Другой весьма полезный метод:

Surface.set_alpha(alpha)

задает степень прозрачности поверхности:

  • alpha = 0 – полностью прозрачная;
  • alpha = 255 – полностью непрозрачная;

Например, можно сделать так:

surf = pygame.Surface((200, 200))
surf.fill(RED)
pygame.draw.circle(surf, GREEN, (100, 100), 80)
 
surf_alpha = pygame.Surface((W, 100))
pygame.draw.rect(surf_alpha, BLUE, (0, 0, W, 100))
surf_alpha.set_alpha(128)
 
surf.blit(surf_alpha, (0, 50))
sc.blit(surf, (50, 50))
pygame.display.update()

Файл 5-2

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Surface")
pygame.display.set_icon(pygame.image.load("pl_down.png"))


 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

surf = pygame.Surface((200, 200))
surf.fill(RED)
pygame.draw.circle(surf, GREEN, (100, 100), 80)
 
surf_alpha = pygame.Surface((W, 100))
pygame.draw.rect(surf_alpha, BLUE, (0, 0, W, 100))
surf_alpha.set_alpha(128)
 
surf.blit(surf_alpha, (0, 50))
sc.blit(surf, (50, 50))
pygame.display.update()


 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)

Мы здесь определяем две дополнительные поверхности: surf и surf_alpha. Причем, surf_alpha полупрозрачная и располагается на surf. В итоге, имеем такую иерархию поверхностей:

И обратите внимание на такой эффект: поверхность surf_alpha по ширине больше, чем surf. Но, так как surf является родителем для surf_alpha, то все, что выходит за пределы surf – обрезается. В результате, мы видим следующее отображение:

Вот так можно создавать иерархию объектов Surface в PyGame. Причем, если поменять порядок следования слоев:

surf_alpha.blit(surf, (0, 0))
sc.blit(surf_alpha, (50, 50))

То поверхность surf также будет отображаться как полупрозрачная – она унаследует это свойство от родителя surf_alpha:

В заключение этого занятия я приведу небольшую программу простой анимации поверхностей (слоев):

Файл 5-3

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Surface")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
surf = pygame.Surface((W, 200))
bita = pygame.Surface((50, 10))
 
surf.fill(BLUE)
bita.fill(RED)
 
bx, by = 0, 150
x, y = 0, 0
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    surf.fill(BLUE)
    surf.blit(bita, (bx, by))
    if bx < W:
        bx += 5
    else:
        bx = 0
 
    if y < H:
        y += 1
    else:
        y = 0
 
    sc.fill(WHITE)
    sc.blit(surf, (x, y))
    pygame.display.update()
 
    clock.tick(FPS)

Урок 6 Класс Rect. Его роль, свойства и методы

При разработке игр часто требуется определять границы персонажей, окружающих предметов, определять моменты их столкновений. Во всех этих задачах в PyGame используется специальный объект:

Rect (сокращение от Rectangle – прямоугольник)

Обратите внимание, Rect – это не класс для рисования прямоугольников, это класс для операций с прямоугольными областями и к рисованию он не имеет прямого отношения.

Например, в PyGame каждая поверхность имеет метод:

Surface.get_rect()

который возвращает класс Rect с размерами этого слоя. И в качестве начального примера, рассмотрим вот такую простую программу:

Файл 6

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Rect")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
hero = pygame.Surface((40, 50))
hero.fill(BLUE)
rect = hero.get_rect()
print(rect)
 
sc.fill(WHITE)
sc.blit(hero, (100, 50))
pygame.display.update()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)

Смотрите, у нас здесь определена поверхность hero (герой), которая имеет размеры 40×50 пикселей. Затем, с помощью операции:

rect = hero.get_rect()

мы получаем ссылку на размеры этой области в виде экземпляра класса Rect. Причем, этот класс имеет следующие весьма полезные свойства:

Например, мы можем обратиться к атрибуту center и узнать координаты центра нашего героя:

print(rect.center)

Мало того, метод get_rect имеет ряд дополнительных, полезных именованных параметров. Например, для определения заданного начального положения координат верхнего левого угла, нужно указать такой параметр:

rect = hero.get_rect(topleft=(200, 50))

Или, чтобы определить координаты прямоугольника по центру клиентской области, можно записать следующую команду:

rect = hero.get_rect(center = (W//2, H//2))

или так:

rect = hero.get_rect(centerx = W//2, centery = H//2)

Теперь, мы можем расположить героя точно в центре окна:

sc.blit(hero, rect)

Обратите внимание, мы здесь передаем в метод blit объект Rect для позиционирования слоя hero, а не кортеж координат (x, y). Так тоже можно делать и blit автоматически возьмет из Rect координату верхнего левого угла, а остальные параметры проигнорирует.

Помимо свойств класс Rect содержит и несколько полезных методов. Например:

  • Rect.move(x, y) – возвращает новый прямоугольник со смещениями x, y;
  • Rect.move_ip(x, y) – меняет координаты текущего прямоугольника со смещениями x, y;
  • Rect.clip(Rect) – обрезает границы прямоугольника по указанным размерам переданного прямоугольника;
  • Rect.union(Rect) – возвращает новый прямоугольник с результатом объединения двух прямоугольников в один;
  • Rect.union_ip – объединяет два прямоугольника в один;
  • Rect.fit(Rect) – возвращает новый прямоугольник, смещенный и измененный по размеру переданного прямоугольника;
  • Rect.contains(Rect) – проверяет: содержится ли один прямоугольник внутри другого.

Это лишь некоторые методы класса Rect. Полный их список можно посмотреть на странице официальной документации:

И обратите внимание на суффикс _ip у одноименных методов. Он указывает, что изменения следует выполнять для текущего экземпляра класса, не создавая нового. Если же этот суффикс отсутствует, то метод создает новый объект класса Rect с соответствующими изменениями его свойств.

Например, давайте создадим в программе два объекта Rect:

rect1 = pygame.Rect((0, 0, 30, 30))
rect2 = pygame.Rect((30, 30, 30, 30))

И выполним с ними следующие операции:

rect2.move_ip(20, 20)
print(rect2)
rect3 = rect2.union(rect1)
print(rect3)

Код. Файл 6-1

import pygame
 
pygame.init()
 
W = 600
H = 400
 
sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Rect")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
 
FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()
 
hero = pygame.Surface((40, 50))
hero.fill(BLUE)

rect1 = pygame.Rect((0, 0, 30, 30))
rect2 = pygame.Rect((30, 30, 30, 30))

rect2.move_ip(20, 20)
print(rect2)
rect3 = rect2.union(rect1)
print(rect3)
 
sc.fill(WHITE)
sc.blit(hero, (100, 50))
pygame.display.update()
 
while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)

Результат работы показан на рисунке ниже:

По аналогии работают и другие методы класса Rect.

Давайте для примера, используя класс Rect, напишем программу подпрыгивания нашего героя при нажатии на кнопку пробел (lesson 6.hero_jump.py: https://github.com/selfedu-rus/pygame):

Файл 6-2

import pygame

pygame.init()

W = 600
H = 400

sc = pygame.display.set_mode((W, H))
pygame.display.set_caption("Класс Rect")
pygame.display.set_icon(pygame.image.load("pl_down.png"))

WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)

FPS = 60        # число кадров в секунду
clock = pygame.time.Clock()

ground = H-70           # высота земли
jump_force = 20         # сила прыжка
move = jump_force+1     # текущая вертикальная скорость

hero = pygame.Surface((40, 50))
hero.fill(BLUE)
rect = hero.get_rect(centerx=W//2)

print(rect)
rect.bottom = ground
print(rect)

rect_update = pygame.Rect(rect.x, 0, rect.width, ground)
sc.fill(WHITE)
pygame.display.update()

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE and ground == rect.bottom:
                move = -jump_force

    if move <= jump_force:
        if rect.bottom + move < ground:
            rect.bottom += move
            if move < jump_force:
                move += 1
        else:
            rect.bottom = ground
            move = jump_force+1

    sc.fill(WHITE)
    sc.blit(hero, rect)
    pygame.display.update(rect_update)

    clock.tick(FPS)

Здесь мы определили вспомогательные переменные:

  • ground – высота земли;
  • jump_force – сила прыжка;
  • move – текущая вертикальная скорость.

Затем, ставим героя по центру горизонтали и на уровень земли, используя свойство rect.bottom. Обратите внимание, меняя это свойство, автоматически изменятся и свойства x, y – координаты верхнего левого угла. То есть, мы фактически смещаем прямоугольник вниз до уровня земли. Далее, нажимая на пробел, устанавливается значение move = -jump_force – герой прыгает вверх с начальной скоростью jump_force. В главном цикле идет проверка: если скорость move меньше или равна jump_force, то мы смещаем героя на эту величину и уменьшаем скорость на единицу (move += 1). И делаем эти операции, пока герой снова не окажется на уровне земли. Тогда его скорость искусственно устанавливается равной move = jump_force+1, чтобы условие прыжка не срабатывало и он остановился.

Этот пример показывает как можно использовать класс Rect для реализации простой анимации. Мало того, мы можем указать в методе pygame.display.update() перерисовывать не всю область окна, а только ту часть, где происходит подпрыгивание героя:

rect_update = pygame.Rect(rect.x, 0, rect.width, ground)

и, затем:

pygame.display.update(rect_update)

Смотрите, теперь кажется, что герой как бы пытается выпрыгнуть из ямы. Я специально показал этот эффект для лучшего понимания работы метода update. Конечно, в нашем случае нужно до главного цикла полностью прорисовать окно:

sc.fill(WHITE)
pygame.display.update()

а уже потом ограничивать область рисования.

Урок 7 Как рисовать текст различными шрифтами

На этом занятии мы с вами разберемся как в Pygame происходит отображение текста разными шрифтами. И начнем со шрифтов. Для работы с ними имеется встроенный модуль:

pygame.font

в котором определены следующие полезные классы и функции:

  • SysFont(fontname, size) – класс для выбора предустановленного шрифта (по имени fontname) с размером size (в пикселях);
  • Font(path, size) – класс для загрузки шрифта по указанному пути path с размером size (в пикселях);
  • get_fonts() – функция, возвращающая имена предустановленных в системе шрифтов;
  • match_font(fontname) – функция возвращающая путь к предустановленному шрифту по его имени.

Например, вот так можно получить список всех шрифтов, установленных на устройстве:

import pygame
pygame.init()
print( pygame.font.get_fonts() )

И выберем первый из них:

f_sys = pygame.font.SysFont('arial', 12)

На выходе получим экземпляр класса Font, на который ссылается переменная f_sys. Далее, уже используя эту переменную, мы можем работать с выбранным шрифтом.

Аналогично используется и второй класс:

f = pygame.font.Font('fonts/YandexSDLight.ttf', 24)

только здесь мы указываем полный путь к шрифту (обычно, это какой-либо нестандартный шрифт, который мы хотим использовать в нашей программе). Давайте нарисуем с его помощью текст. Программа будет выглядеть так:

Файл 7

import pygame
pygame.init()
 
W, H = 600, 400
 
sc = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Шрифты")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
clock = pygame.time.Clock()
FPS = 60
 
WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (239, 228, 176)
 
f = pygame.font.Font('fonts/YandexSDLight.ttf', 24)
sc_text = f.render('Привет мир!', 1, RED, YELLOW)
pos = sc_text.get_rect(center=(W//2, H//2))
 
sc.fill(WHITE)
sc.blit(sc_text, pos)
pygame.display.update()
 
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)
}

Смотрите, сначала вызывается метод render чтобы сформировать слой Surface, на котором будет написан текст «Привет мир!» выбранным шрифтом. Параметр 1 говорит, что нужно выполнять сглаживание границ букв (0 – без сглаживания), затем идет цвет текст и цвет фона. После этого мы получаем координаты прямоугольной области поверхности sc_text, расположенной по центру клиентской области окна приложения. И далее, с помощью уже известного метода blit отображаем текст в окне. Результат работы программы выглядит так:

Вот такие действия нужно выполнить для отображения текста в Pygame. Однако, если мы хотим использовать шрифт по умолчанию, используемый в этой библиотеке, то вместо имени шрифта, в приведенных выше классах, следует указывать значение None, например:

f = pygame.font.Font(None, 24)

В заключение этого занятия я приведу пример простой программы по перемещению изображения текста с помощью мышки (lesson 7.text_move.py: https://github.com/selfedu-rus/pygame):

Файл 7-1

import pygame
pygame.init()
 
W, H = 600, 400
 
sc = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Шрифты")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
clock = pygame.time.Clock()
FPS = 60
 
WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (239, 228, 176)
 
print( pygame.font.get_fonts() )
 
f = pygame.font.Font('fonts/YandexSDLight.ttf', 24)
sc_text = f.render('Привет мир!', 1, RED, YELLOW)
pos = sc_text.get_rect(center=(W//2, H//2))
 
def draw_text():
    sc.fill(WHITE)
    sc.blit(sc_text, pos)
    pygame.display.update()
 
draw_text()
 
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            pygame.mouse.get_rel()   # обнуляем первое смещение (при повторном вызове ниже)
 
    if pygame.mouse.get_focused() and pos.collidepoint(pygame.mouse.get_pos()):
        btns = pygame.mouse.get_pressed()
        if btns[0]:     # нажата левая кнопка мыши
            rel = pygame.mouse.get_rel()    # получаем смещение
            pos.move_ip(rel)
            draw_text()
 
    clock.tick(FPS)

Смотрите, в главном цикле мы проверяем: находится ли курсор мыши в области окна приложения и располагается ли над текстом. Если это так, то далее проверяем: нажата ли левая кнопка мыши и при истинности проверки получаем смещение курсора мыши. Причем, первое смещение будет нулевым, т.к. выше при проверке события MOUSEBUTTONDOWN мы вызываем эту же функцию get_rel(), поэтому при ее повторном вызове она возвратит нулевые смещения. Далее, смещая курсор мыши переменная rel будет ссылаться на кортеж из значений смещения по координатам X и Y. Мы используем этот кортеж, чтобы изменить положение прямоугольника pos и отобразить текст с этими новыми координатами с помощью функции draw_text().

Вот так довольно просто выполняется работа с текстом в Pygame.

Урок 8 Как работать с изображениями. Модули image и transform

Ссылка на проект занятия (lesson 8.car_move.zip): https://github.com/selfedu-rus/pygame

На этом занятии мы с вами узнаем как использовать изображения в библиотеке Pygame. Здесь сразу следует знать одну вещь: родной формат графических данных для Pygame – это

bmp (от англ. Bitmap Picture)

то есть, не сжатые наборы пикселей изображения. Такие графические файлы занимают много места по сравнению с другими распространенными форматами:

  • PNG (расширение png) – используется сжатие без потерь с использованием алгоритмов ДИКМ и LZW;
  • JPEG (расширение jpg) – используется сжатие с потерями (алгоритм ДКП – аналог Фурье-преобразования с косинусными гармониками).

Существуют и другие форматы представления изображений, но они применяются гораздо реже, чем PNG или JPEG.

Как же нам понять: какой формат данных выбирать? В действительности, все просто. Во-первых, нужно узнать: поддерживает ли Pygame на текущем устройстве какие-либо форматы, кроме BMP. Для этого следует выполнить функцию:

pygame.image.get_extended()

и если она вернет значение True (то есть 1), то в программе можно использовать PNG, JPEG, GIF и другие известные форматы. А, иначе, только BMP. Далее, при выборе между PNG и JPEG руководствуются следующим правилом:

Для фотореалистичных изображений лучше всего использовать JPEG, т.к. незначительные потери практически не скажутся на визуальном восприятии, но изображение будет хорошо сжато.

Для искусственных изображений с большим наличием однотонных областей (например, клип-арт) где четкость границ и однотонность заливки имеет первостепенное значение, лучше выбирать формат PNG. Кроме того, этот формат хранит альфа-канал для прозрачного фона (в JPEG такой возможности нет).

Программа ниже инициализирует Pygame и выводит в консоль значение функции get_extended():

Файл 8

import pygame
pygame.init()
 
W, H = 600, 400
 
sc = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Изображения")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
clock = pygame.time.Clock()
FPS = 60
 
WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (239, 228, 176)
 
print( pygame.image.get_extended() )
 
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)
}

Как видите, в данном случае Pygame возвращает 1, значит, можно использовать форматы PNG и JPEG.

Теперь загрузим в программе изображение машинки:

car_surf = pygame.image.load("images/car.bmp")

Здесь используется функция load(), в которой указывается путь к изображению (относительно исполняемого файла на Питоне) и на выходе она формирует поверхность с изображением машинки. Далее, мы можем отобразить содержимое этой поверхности уже знакомым нам способом:

car_rect = car_surf.get_rect(center=(W//2, H//2))
 
sc.blit(car_surf, car_rect)
pygame.display.update()






в папке lesson 8.car_move. Файл 8-1

import pygame
pygame.init()
 
W, H = 600, 400
 
sc = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Изображения")
pygame.display.set_icon(pygame.image.load("pl_down.png"))
 
clock = pygame.time.Clock()
FPS = 60
 
WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (239, 228, 176)
 
print( pygame.image.get_extended() )

car_surf = pygame.image.load("images/car.bmp")

car_rect = car_surf.get_rect(center=(W//2, H//2))
pygame.display.update()


 
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()




    sc.blit(car_surf, car_rect)

    pygame.display.update()
 
    clock.tick(FPS)

Следующий пример.

Папка lesson 8.car_move. Файл 8-2

import pygame
pygame.init()

W, H = 600, 400

sc = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Изображения")
pygame.display.set_icon(pygame.image.load("pl_down.png"))

clock = pygame.time.Clock()
FPS = 60

WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (239, 228, 176)

print( pygame.image.get_extended() )
car_surf = pygame.image.load("images/car.bmp").convert()
car_surf.set_colorkey((255, 255, 255))
car_rect = car_surf.get_rect(center=(W//2, H//2))

finish_surf = pygame.image.load("images/finish.png").convert_alpha()

bg_surf = pygame.image.load("images/sand.jpg").convert()

bg_surf = pygame.transform.scale(bg_surf, (bg_surf.get_width()//3, bg_surf.get_height()//3))

car_up = car_surf
car_down = pygame.transform.flip(car_surf, 0, 1)
car_left = pygame.transform.rotate(car_surf, 90)
car_right = pygame.transform.rotate(car_surf, -90)

car = car_up
speed = 5

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()



    sc.blit(bg_surf, (0, 0))
    sc.blit(finish_surf, (0, 0))
    sc.blit(car, car_rect)

    pygame.display.update()

    clock.tick(FPS)


Не забываем про наличие и вложенные картинки в папках с программой

Добавим фон в виде изображения песка:

bg_surf = pygame.image.load("images/sand.jpg")
sc.blit(bg_surf, (0, 0))

Стало лучше, но белый фон у машинки явно выделяется на фоне песка. Давайте укажем Pygame, что белый цвет следует воспринимать как прозрачный:

car_surf.set_colorkey((255, 255, 255))

Теперь намного лучше. Однако, если имеется файл с альфа-каналом (прозрачным фоном), то оно будет сразу отображаться нужным образом:

finish_surf = pygame.image.load("images/finish.png")
sc.blit(finish_surf, (0, 0))

Следующий важный момент, особенно при разработке динамических игр, перевод пикселей загруженных изображений в формат пикселей главной поверхности:

car_surf = pygame.image.load("images/car.bmp").convert()
finish_surf = pygame.image.load("images/finish.png").convert_alpha()
bg_surf = pygame.image.load("images/sand.jpg").convert()

В этом случае, перерисовка поверхностей будет выполняться быстрее. Причем, обратите внимание, изображение в формате PNG с альфа-каналом преобразуется методом convert_alpha(), а не convert().

Вообще, эти строчки равносильны следующей операции:

car_surf = pygame.image.load("images/car.bmp")
car_surf = car_surf.convert()

То есть, методы convert() и convert_alpha() – это методы класса Surface, которые возвращают новую поверхность с измененным представлением пикселей. При этом прежняя поверхность остается без изменений. Например, если переписать последнюю строчку вот так:

car_surf2 = car_surf.convert()

то пиксели car_surf2 будут приведены к формату главной поверхности, а пиксели car_surf останутся прежними – без изменений.

После выполнения программы увидим в центре окна изображение машины:

Трансформация поверхностей

Предположим, что мы теперь хотели бы уменьшить масштаб изображения фона, чтобы песок был более мелкий. Это можно сделать с помощью модуля

pygame.transform

содержащий различные функции трансформации поверхностей. Подробное их описание можно посмотреть на странице официальной документации:

Итак, мы воспользуемся функцией:

pygame.transform.scale(Surface, (width, height), DestSurface = None) -> Surface

Здесь первый параметр – преобразуемая поверхность; (width, height) – ее новые значения ширины и высоты. В нашей программе вызовем эту функцию так:

bg_surf = pygame.transform.scale(bg_surf, (bg_surf.get_width()//3, bg_surf.get_height()//3))

Мы здесь уменьшаем размеры bg_surf в три раза по обеим координатам. Теперь, при отображении песок выглядит более мелким.

Давайте теперь сделаем так, чтобы машинка перемещалась при нажатии на курсорные клавиши. Для начала мы сформируем изображения машинки при движении вверх, влево, вправо и вниз:

car_up = car_surf
car_down = pygame.transform.flip(car_surf, 0, 1)
car_left = pygame.transform.rotate(car_surf, 90)
car_right = pygame.transform.rotate(car_surf, -90)

Далее, определим переменные для хранения текущего вида машинки и ее скорости:

car = car_up
speed = 5

А внутри главного цикла будем выполнять перерисовку главного окна с текущим видом и положением машинки:

Смотри Папка lesson 8.car_move. Файл lesson 8.car_move

import pygame
pygame.init()

W, H = 600, 400

sc = pygame.display.set_mode((600, 400))
pygame.display.set_caption("Изображения")
pygame.display.set_icon(pygame.image.load("pl_down.png"))

clock = pygame.time.Clock()
FPS = 60

WHITE = (255, 255, 255)
RED = (255, 0, 0)
YELLOW = (239, 228, 176)

print( pygame.image.get_extended() )
car_surf = pygame.image.load("images/car.bmp").convert()
car_surf.set_colorkey((255, 255, 255))
car_rect = car_surf.get_rect(center=(W//2, H//2))

finish_surf = pygame.image.load("images/finish.png").convert_alpha()
bg_surf = pygame.image.load("images/sand.jpg").convert()

bg_surf = pygame.transform.scale(bg_surf, (bg_surf.get_width()//3, bg_surf.get_height()//3))

car_up = car_surf
car_down = pygame.transform.flip(car_surf, 0, 1)
car_left = pygame.transform.rotate(car_surf, 90)
car_right = pygame.transform.rotate(car_surf, -90)

car = car_up
speed = 5

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()

    bt = pygame.key.get_pressed()
    if bt[pygame.K_LEFT]:
        car = car_left
        car_rect.x -= speed
        if car_rect.x < 0:
            car_rect.x = 0
    elif bt[pygame.K_RIGHT]:
        car = car_right
        car_rect.x += speed
        if car_rect.x > W-car_rect.height:
            car_rect.x = W-car_rect.height
    elif bt[pygame.K_UP]:
        car = car_up
        car_rect.y -= speed
        if car_rect.y < 0:
            car_rect.y = 0
    elif bt[pygame.K_DOWN]:
        car = car_down
        car_rect.y += speed
        if car_rect.y > H-car_rect.height:
            car_rect.y = H-car_rect.height

    sc.blit(bg_surf, (0, 0))
    sc.blit(finish_surf, (0, 0))
    sc.blit(car, car_rect)

    pygame.display.update()

    clock.tick(FPS)

Урок 9 Что такое спрайты и как с ними работать

Спрайт — это элемент компьютерной графики, представляющий объект на экране, который может двигаться. В двухмерной игре все, что вы видите на экране, является спрайтами. Спрайты можно анимировать, заставлять их взаимодействовать между собой или передавать управление ими игроку.

Для загрузки и отрисовки спрайтов в случай этой игры их нужно добавить в разделы “Обновление” и “Визуализация” игрового цикла. Несложно представить, что если в игре много спрайтов, то цикл довольно быстро станет большим и запутанным.

В Pygame для этого есть решение: группировка спрайтов.

Набор спрайтов — это коллекция спрайтов, которые могут отображаться одновременно. Вот как нужно создавать группу спрайтов в игре:

clock = pygame.time.Clock()
all_sprites = pygame.sprite.Group() 

Теперь этой возможностью можно воспользоваться, добавив группу целиком в цикл:

    # Обновление
    all_sprites.update()

<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; padding-left: 0px; color: rgb(243, 228, 203);" class="token comment"># Отрисовка</span>
screen<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(255, 255, 238);" class="token punctuation">.</span>fill<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(255, 255, 238);" class="token punctuation">(</span>BLACK<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(255, 255, 238);" class="token punctuation">)</span>
all_sprites<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(255, 255, 238);" class="token punctuation">.</span>draw<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(255, 255, 238);" class="token punctuation">(</span>screen<span style="box-sizing: border-box; font-weight: inherit !important; font-size: inherit; color: rgb(255, 255, 238);" class="token punctuation">)</span>

Теперь при создании каждого спрайта, главное убедиться, что он добавлен в группу all_sprites. Такой спрайт будет автоматически отрисован на экране и обновляться в цикле.

Ссылка на проект занятия (lesson 9.flowballs.zip): https://github.com/selfedu-rus/pygame

Представьте, что мы делаем игру, в которой множество подвижных объектов, с которым взаимодействует пользователь. Как в этом случае правильно спроектировать программу на Pygame, чтобы эффективно обрабатывать движения и взаимодействия? Для этого была специально создана ветка:

pygame.sprite

для работы со спрайтами. Вообще в игровом процессе спрайт – это любой подвижный объект. И когда таких объектов много, то класс:

pygame.sprite.Sprite

значительно облегчает их обработку. И мы сейчас посмотрим, как это делается.

Для начала создадим базовый каркас приложения. Он вам уже знаком и выглядит следующим образом:

import pygame
 
pygame.init()
 
BLACK = (0, 0, 0)
W, H = 1000, 570
 
sc = pygame.display.set_mode((W, H))
 
clock = pygame.time.Clock()
FPS = 60
 
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
 
    clock.tick(FPS)

Давайте теперь добавим сюда подвижный объект в виде падающего сверху шарика. Для этого мы воспользуемся классом Sprite и на его основе создадим новый класс Ball для обработки падающих шариков. Этот класс мы объявим в отдельном файле ball.py, чтобы сохранить модульность нашей программы:

import pygame
 
class Ball(pygame.sprite.Sprite):
    def __init__(self, x, filename):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(filename).convert_alpha()
        self.rect = self.image.get_rect(center=(x, 0))

Значит, здесь мы определяем наш собственный класс Ball, наследуя его от базового класса Sprite. В результате, мы расширяем функциональность этого базового класса, определяя в конструкторе два обязательных свойства:

  • image – графическое представление спрайта (ссылка на Surface);
  • rect – положение и размер спрайта.

Затем, эти свойства будут автоматически использоваться для обработки групп спрайтов. Поэтому они необходимы и должны называться именно так.

Отлично, это мы сделали. Теперь в основном модуле подключим этот файл и создадим шар через класс Ball:

from ball import Ball
...
speed = 1
b1 = Ball(W//2, 'images/ball_bear.png')

После этого в главном цикле реализуем движение шара b1:

    sc.fill(BLACK)
    sc.blit(b1.image, b1.rect)
    pygame.display.update()
 
    clock.tick(FPS)
 
    if b1.rect.y < H-20:
        b1.rect.y += speed
    else:
        b1.rect.y = 0

И при запуске программы увидим как шар в виде медведя падает вниз. Давайте для красоты добавим еще фон. Сначала загрузим его:

bg = pygame.image.load('images/back1.jpg').convert()

а, затем, в главном цикле будем перерисовывать вместо вызова fill(BLACK):

sc.blit(bg, (0, 0))

Получим такой вид игрового процесса:

Полезная ссылка

Полезная ссылка

Полезная ссылка

Ну очень интересная ссылка

PyGame — шпаргалка для использования

Тоже не плохая информация

Канал egoroff_channel