Игры на python: Пишем игру на Python — Журнал «Код»: программирование без снобизма
Содержание
Пишем игру на Python — Журнал «Код»: программирование без снобизма
Прежде чем мы начнём программировать что-то полезное на Python, давайте закодим что-нибудь интересное. Например, свою игру, где нужно не дать шарику упасть, типа Арканоида. Вы, скорее всего, играли в детстве во что-то подобное, поэтому освоиться будет просто.
Логика игры
Есть игровое поле — простой прямоугольник с твёрдыми границами. Когда шарик касается стенки или потолка, он отскакивает в другую сторону. Если он упадёт на пол — вы проиграли. Чтобы этого не случилось, внизу вдоль пола летает платформа, а вы ей управляете с помощью стрелок. Ваша задача — подставлять платформу под шарик как можно дольше. За каждое удачное спасение шарика вы получаете одно очко.
Алгоритм
Чтобы реализовать такую логику игры, нужно предусмотреть такие сценарии поведения:
- игра начинается;
- шарик начинает двигаться;
- если нажаты стрелки влево или вправо — двигаем платформу;
- если шарик коснулся стенок, потолка или платформы — делаем отскок;
- если шарик коснулся платформы — увеличиваем счёт на единицу;
- если шарик упал на пол — выводим сообщение и заканчиваем игру.
Хитрость в том, что всё это происходит параллельно и независимо друг от друга. То есть пока шарик летает, мы вполне можем двигать платформу, а можем и оставить её на месте. И когда шарик отскакивает от стен, это тоже не мешает другим объектам двигаться и взаимодействовать между собой.
Получается, что нам нужно определить три класса — платформу, сам шарик и счёт, и определить, как они реагируют на действия друг друга. Поле нам самим определять не нужно — для этого есть уже готовая библиотека. А потом в этих классах мы пропишем методы — они как раз и будут отвечать за поведение наших объектов.
Весь кайф в том, что мы всё это задаём один раз, а потом объекты сами разбираются, как им реагировать друг на друга и что делать в разных ситуациях. Мы не прописываем жёстко весь алгоритм, а задаём правила игры — а для этого классы подходят просто идеально.
По коням, пишем на Python
Для этого проекта вам потребуется установить и запустить среду Python. Как это сделать — читайте в нашей статье.
Начало программы
Чтобы у нас появилась графика в игре, используем библиотеку Tkinter. Она входит в набор стандартных библиотек Python и позволяет рисовать простейшие объекты — линии, прямоугольники, круги и красить их в разные цвета. Такой простой Paint, только для Python.
Чтобы создать окно, где будет видна графика, используют класс Tk(). Он просто делает окно, но без содержимого. Чтобы появилось содержимое, создают холст — видимую часть окна. Именно на нём мы будем рисовать нашу игру. За холст отвечает класс Canvas(), поэтому нам нужно будет создать свой объект из этого класса и дальше уже работать с этим объектом.
Если мы принудительно не ограничим скорость платформы, то она будет перемещаться мгновенно, ведь компьютер считает очень быстро и моментально передвинет её к другому краю. Поэтому мы будем искусственно ограничивать время движения, а для этого нам понадобится модуль Time — он тоже стандартный.
Последнее, что нам глобально нужно, — задавать случайным образом начальное положение шарика и платформы, чтобы было интереснее играть. За это отвечает модуль Random — он помогает генерировать случайные числа и перемешивать данные.
Запишем всё это в виде кода на Python:
# подключаем графическую библиотеку
from tkinter import *
# подключаем модули, которые отвечают за время и случайные числа
import time
import random
# создаём новый объект — окно с игровым полем. В нашем случае переменная окна называется tk, и мы его сделали из класса Tk() — он есть в графической библиотеке
tk = Tk()
# делаем заголовок окна — Games с помощью свойства объекта title
tk.title('Game')
# запрещаем менять размеры окна, для этого используем свойство resizable
tk.resizable(0, 0)
# помещаем наше игровое окно выше остальных окон на компьютере, чтобы другие окна не могли его заслонить
tk.wm_attributes('-topmost', 1)
# создаём новый холст — 400 на 500 пикселей, где и будем рисовать игру
canvas = Canvas(tk, width=500, height=400, highlightthickness=0)
# говорим холсту, что у каждого видимого элемента будут свои отдельные координаты
canvas.pack()
# обновляем окно с холстом
tk.update()
Мы подключили все нужные библиотеки, сделали и настроили игровое поле. Теперь займёмся классами.
Шарик
Сначала проговорим словами, что нам нужно от шарика. Он должен уметь:
- задавать своё начальное положение и направление движение;
- понимать, когда он коснулся платформы;
- рисовать сам себя и понимать, когда нужно отрисовать себя в новом положении (например, после отскока от стены).
Этого достаточно, чтобы шарик жил своей жизнью и умел взаимодействовать с окружающей средой. При этом нужно не забыть о том, что каждый класс должен содержать конструктор — код, который отвечает за создание нового объекта. Без этого сделать шарик не получится. Запишем это на Python:
# Описываем класс Ball, который будет отвечать за шарик
class Ball:
# конструктор — он вызывается в момент создания нового объекта на основе этого класса
def __init__(self, canvas, paddle, score, color):
# задаём параметры объекта, которые нам передают в скобках в момент создания
self.canvas = canvas
self.paddle = paddle
self.score = score
# цвет нужен был для того, чтобы мы им закрасили весь шарик
# здесь появляется новое свойство id, в котором хранится внутреннее название шарика
# а ещё командой create_oval мы создаём круг радиусом 15 пикселей и закрашиваем нужным цветом
self.id = canvas.create_oval(10,10, 25, 25, fill=color)
# помещаем шарик в точку с координатами 245,100
self.canvas.move(self.id, 245, 100)
# задаём список возможных направлений для старта
starts = [-2, -1, 1, 2]
# перемешиваем его
random.shuffle(starts)
# выбираем первый из перемешанного — это будет вектор движения шарика
self.x = starts[0]
# в самом начале он всегда падает вниз, поэтому уменьшаем значение по оси y
self.y = -2
# шарик узнаёт свою высоту и ширину
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()
# свойство, которое отвечает за то, достиг шарик дна или нет. Пока не достиг, значение будет False
self.hit_bottom = False
# обрабатываем касание платформы, для этого получаем 4 координаты шарика в переменной pos (левая верхняя и правая нижняя точки)
def hit_paddle(self, pos):
# получаем кординаты платформы через объект paddle (платформа)
paddle_pos = self.canvas.coords(self.paddle.id)
# если координаты касания совпадают с координатами платформы
if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
# увеличиваем счёт (обработчик этого события будет описан ниже)
self.score.hit()
# возвращаем метку о том, что мы успешно коснулись
return True
# возвращаем False — касания не было
return False
# обрабатываем отрисовку шарика
def draw(self):
# передвигаем шарик на заданные координаты x и y
self.canvas.move(self.id, self.x, self.y)
# запоминаем новые координаты шарика
pos = self.canvas.coords(self.id)
# если шарик падает сверху
if pos[1] <= 0:
# задаём падение на следующем шаге = 2
self.y = 2
# если шарик правым нижним углом коснулся дна
if pos[3] >= self.canvas_height:
# помечаем это в отдельной переменной
self.hit_bottom = True
# выводим сообщение и количество очков
canvas.create_text(250, 120, text='Вы проиграли', font=('Courier', 30), fill='red')
# если было касание платформы
if self.hit_paddle(pos) == True:
# отправляем шарик наверх
self.y = -2
# если коснулись левой стенки
if pos[0] <= 0:
# движемся вправо
self.x = 2
# если коснулись правой стенки
if pos[2] >= self.canvas_width:
# движемся влево
self.x = -2
Платформа
Сделаем то же самое для платформы — сначала опишем её поведение словами, а потом переведём в код. Итак, вот что должна уметь платформа:
- двигаться влево или вправо в зависимости от нажатой стрелки;
- понимать, когда игра началась и можно двигаться.
А вот как это будет в виде кода:
# Описываем класс Paddle, который отвечает за платформы
class Paddle:
# конструктор
def __init__(self, canvas, color):
# canvas означает, что платформа будет нарисована на нашем изначальном холсте
self.canvas = canvas
# создаём прямоугольную платформу 10 на 100 пикселей, закрашиваем выбранным цветом и получаем её внутреннее имя
self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
# задаём список возможных стартовых положений платформы
start_1 = [40, 60, 90, 120, 150, 180, 200]
# перемешиваем их
random.shuffle(start_1)
# выбираем первое из перемешанных
self.starting_point_x = start_1[0]
# перемещаем платформу в стартовое положение
self.canvas.move(self.id, self.starting_point_x, 300)
# пока платформа никуда не движется, поэтому изменений по оси х нет
self.x = 0
# платформа узнаёт свою ширину
self.canvas_width = self.canvas.winfo_width()
# задаём обработчик нажатий
# если нажата стрелка вправо — выполняется метод turn_right()
self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
# если стрелка влево — turn_left()
self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
# пока игра не началась, поэтому ждём
self.started = False
# как только игрок нажмёт Enter — всё стартует
self.canvas.bind_all('<KeyPress-Return>', self.start_game)
# движемся вправо
def turn_right(self, event):
# будем смещаться правее на 2 пикселя по оси х
self.x = 2
# движемся влево
def turn_left(self, event):
# будем смещаться левее на 2 пикселя по оси х
self.x = -2
# игра начинается
def start_game(self, event):
# меняем значение переменной, которая отвечает за старт
self.started = True
# метод, который отвечает за движение платформы
def draw(self):
# сдвигаем нашу платформу на заданное количество пикселей
self.canvas.move(self.id, self.x, 0)
# получаем координаты холста
pos = self.canvas.coords(self.id)
# если мы упёрлись в левую границу
if pos[0] <= 0:
# останавливаемся
self.x = 0
# если упёрлись в правую границу
elif pos[2] >= self.canvas_width:
# останавливаемся
self.x = 0
Счёт
Можно было не выделять счёт в отдельный класс и каждый раз обрабатывать вручную. Но здесь реально проще сделать класс, задать нужные методы, чтобы они сами потом разобрались, что и когда делать.
От счёта нам нужно только одно (кроме конструктора) — чтобы он правильно реагировал на касание платформы, увеличивал число очков и выводил их на экран:
# Описываем класс Score, который отвечает за отображение счетов
class Score:
# конструктор
def __init__(self, canvas, color):
# в самом начале счёт равен нулю
self.score = 0
# будем использовать наш холст
self.canvas = canvas
# создаём надпись, которая показывает текущий счёт, делаем его нужно цвета и запоминаем внутреннее имя этой надписи
self.id = canvas.create_text(450, 10, text=self.score, font=('Courier', 15), fill=color)
# обрабатываем касание платформы
def hit(self):
# увеличиваем счёт на единицу
self.score += 1
# пишем новое значение счёта
self.canvas.itemconfig(self.id, text=self.score)
Игра
У нас всё готово для того, чтобы написать саму игру. Мы уже провели необходимую подготовку всех элементов, и нам остаётся только создать конкретные объекты шарика, платформы и счёта и сказать им, в каком порядке мы будем что делать.
Смысл игры в том, чтобы не уронить шарик. Пока этого не произошло — всё движется, но как только шарик упал — нужно показать сообщение о конце игры и остановить программу.
Посмотрите, как лаконично выглядит код непосредственно самой игры:
# создаём объект — зелёный счёт
score = Score(canvas, 'green')
# создаём объект — белую платформу
paddle = Paddle(canvas, 'White')
# создаём объект — красный шарик
ball = Ball(canvas, paddle, score, 'red')
# пока шарик не коснулся дна
while not ball.hit_bottom:
# если игра началась и платформа может двигаться
if paddle.started == True:
# двигаем шарик
ball.draw()
# двигаем платформу
paddle.draw()
# обновляем наше игровое поле, чтобы всё, что нужно, закончило рисоваться
tk.update_idletasks()
# обновляем игровое поле, и смотрим за тем, чтобы всё, что должно было быть сделано — было сделано
tk.update()
# замираем на одну сотую секунды, чтобы движение элементов выглядело плавно
time.sleep(0.01)
# если программа дошла досюда, значит, шарик коснулся дна. Ждём 3 секунды, пока игрок прочитает финальную надпись, и завершаем игру
time.sleep(3)
# подключаем графическую библиотеку
from tkinter import *
# подключаем модули, которые отвечают за время и случайные числа
import time
import random
# создаём новый объект — окно с игровым полем. В нашем случае переменная окна называется tk, и мы его сделали из класса Tk() — он есть в графической библиотеке
tk = Tk()
# делаем заголовок окна — Games с помощью свойства объекта title
tk.title('Game')
# запрещаем менять размеры окна, для этого используем свойство resizable
tk.resizable(0, 0)
# помещаем наше игровое окно выше остальных окон на компьютере, чтобы другие окна не могли его заслонить. Попробуйте :)
tk.wm_attributes('-topmost', 1)
# создаём новый холст — 400 на 500 пикселей, где и будем рисовать игру
canvas = Canvas(tk, width=500, height=400, highlightthickness=0)
# говорим холсту, что у каждого видимого элемента будут свои отдельные координаты
canvas.pack()
# обновляем окно с холстом
tk.update()
# Описываем класс Ball, который будет отвечать за шарик
class Ball:
# конструктор — он вызывается в момент создания нового объекта на основе этого класса
def __init__(self, canvas, paddle, score, color):
# задаём параметры объекта, которые нам передают в скобках в момент создания
self.canvas = canvas
self.paddle = paddle
self.score = score
# цвет нужен был для того, чтобы мы им закрасили весь шарик
# здесь появляется новое свойство id, в котором хранится внутреннее название шарика
# а ещё командой create_oval мы создаём круг радиусом 15 пикселей и закрашиваем нужным цветом
self.id = canvas.create_oval(10,10, 25, 25, fill=color)
# помещаем шарик в точку с координатами 245,100
self.canvas.move(self.id, 245, 100)
# задаём список возможных направлений для старта
starts = [-2, -1, 1, 2]
# перемешиваем его
random.shuffle(starts)
# выбираем первый из перемешанного — это будет вектор движения шарика
self.x = starts[0]
# в самом начале он всегда падает вниз, поэтому уменьшаем значение по оси y
self.y = -2
# шарик узнаёт свою высоту и ширину
self.canvas_height = self.canvas.winfo_height()
self.canvas_width = self.canvas.winfo_width()
# свойство, которое отвечает за то, достиг шарик дна или нет. Пока не достиг, значение будет False
self.hit_bottom = False
# обрабатываем касание платформы, для этого получаем 4 координаты шарика в переменной pos (левая верхняя и правая нижняя точки)
def hit_paddle(self, pos):
# получаем кординаты платформы через объект paddle (платформа)
paddle_pos = self.canvas.coords(self.paddle.id)
# если координаты касания совпадают с координатами платформы
if pos[2] >= paddle_pos[0] and pos[0] <= paddle_pos[2]:
if pos[3] >= paddle_pos[1] and pos[3] <= paddle_pos[3]:
# увеличиваем счёт (обработчик этого события будет описан ниже)
self.score.hit()
# возвращаем метку о том, что мы успешно коснулись
return True
# возвращаем False — касания не было
return False
# метод, который отвечает за движение шарика
def draw(self):
# передвигаем шарик на заданный вектор x и y
self.canvas.move(self.id, self.x, self.y)
# запоминаем новые координаты шарика
pos = self.canvas.coords(self.id)
# если шарик падает сверху
if pos[1] <= 0:
# задаём падение на следующем шаге = 2
self.y = 2
# если шарик правым нижним углом коснулся дна
if pos[3] >= self.canvas_height:
# помечаем это в отдельной переменной
self.hit_bottom = True
# выводим сообщение и количество очков
canvas.create_text(250, 120, text='Вы проиграли', font=('Courier', 30), fill='red')
# если было касание платформы
if self.hit_paddle(pos) == True:
# отправляем шарик наверх
self.y = -2
# если коснулись левой стенки
if pos[0] <= 0:
# движемся вправо
self.x = 2
# если коснулись правой стенки
if pos[2] >= self.canvas_width:
# движемся влево
self.x = -2
# Описываем класс Paddle, который отвечает за платформы
class Paddle:
# конструктор
def __init__(self, canvas, color):
# canvas означает, что платформа будет нарисована на нашем изначальном холсте
self.canvas = canvas
# создаём прямоугольную платформу 10 на 100 пикселей, закрашиваем выбранным цветом и получаем её внутреннее имя
self.id = canvas.create_rectangle(0, 0, 100, 10, fill=color)
# задаём список возможных стартовых положений платформы
start_1 = [40, 60, 90, 120, 150, 180, 200]
# перемешиваем их
random.shuffle(start_1)
# выбираем первое из перемешанных
self.starting_point_x = start_1[0]
# перемещаем платформу в стартовое положение
self.canvas.move(self.id, self.starting_point_x, 300)
# пока платформа никуда не движется, поэтому изменений по оси х нет
self.x = 0
# платформа узнаёт свою ширину
self.canvas_width = self.canvas.winfo_width()
# задаём обработчик нажатий
# если нажата стрелка вправо — выполняется метод turn_right()
self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
# если стрелка влево — turn_left()
self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
# пока платформа не двигается, поэтому ждём
self.started = False
# как только игрок нажмёт Enter — всё стартует
self.canvas.bind_all('<KeyPress-Return>', self.start_game)
# движемся вправо
def turn_right(self, event):
# будем смещаться правее на 2 пикселя по оси х
self.x = 2
# движемся влево
def turn_left(self, event):
# будем смещаться левее на 2 пикселя по оси х
self.x = -2
# игра начинается
def start_game(self, event):
# меняем значение переменной, которая отвечает за старт движения платформы
self.started = True
# метод, который отвечает за движение платформы
def draw(self):
# сдвигаем нашу платформу на заданное количество пикселей
self.canvas.move(self.id, self.x, 0)
# получаем координаты холста
pos = self.canvas.coords(self.id)
# если мы упёрлись в левую границу
if pos[0] <= 0:
# останавливаемся
self.x = 0
# если упёрлись в правую границу
elif pos[2] >= self.canvas_width:
# останавливаемся
self.x = 0
# Описываем класс Score, который отвечает за отображение счетов
class Score:
# конструктор
def __init__(self, canvas, color):
# в самом начале счёт равен нулю
self.score = 0
# будем использовать наш холст
self.canvas = canvas
# создаём надпись, которая показывает текущий счёт, делаем его нужно цвета и запоминаем внутреннее имя этой надписи
self.id = canvas.create_text(450, 10, text=self.score, font=('Courier', 15), fill=color)
# обрабатываем касание платформы
def hit(self):
# увеличиваем счёт на единицу
self.score += 1
# пишем новое значение счёта
self.canvas.itemconfig(self.id, text=self.score)
# создаём объект — зелёный счёт
score = Score(canvas, 'green')
# создаём объект — белую платформу
paddle = Paddle(canvas, 'White')
# создаём объект — красный шарик
ball = Ball(canvas, paddle, score, 'red')
# пока шарик не коснулся дна
while not ball.hit_bottom:
# если игра началась и платформа может двигаться
if paddle.started == True:
# двигаем шарик
ball.draw()
# двигаем платформу
paddle.draw()
# обновляем наше игровое поле, чтобы всё, что нужно, закончило рисоваться
tk.update_idletasks()
# обновляем игровое поле и смотрим за тем, чтобы всё, что должно было быть сделано — было сделано
tk.update()
# замираем на одну сотую секунды, чтобы движение элементов выглядело плавно
time.sleep(0.01)
# если программа дошла досюда, значит, шарик коснулся дна. Ждём 3 секунды, пока игрок прочитает финальную надпись, и завершаем игру
time.sleep(3)
Что дальше
На основе этого кода вы можете сделать свою модификацию игры:
- добавить второй шарик;
- раскрасить элементы в другой цвет;
- поменять размеры шарика; поменять скорость платформы;
- сделать всё это сразу;
- поменять логику программы на свою.
Игры, в которых использовался Python
Сегодня вашему вниманию представляется статья и небольшая инфографика, которая покажет вам на конкретных примерах, что Python столь же эффективен в разработке игр, как и в других областях.
Вот некоторые из самых известныx игр, в которых был в той или иной мере использован Python:
Battlefield
(2005 / Digital Illusions CE (DICE) / Стокгольм)
Все серии Python используется в игре для различных нужд, от серверных элементов управления до внутренней логики игры. Battlefield — это одна из самых популярных игр в жанре симулятора войны, которая хорошо известна на весь мир.
EVE Online
(2003 / CCP Games / Исландия)
Это многопользовательская онлайн ролевая игра (MMORPG), действие которой разворачивается в антураже научно-фантастического пространства. Пользовательская база насчитывает более 500 000 игроков. EVE Online полностью написана на StacklessPython, что делает ее одной из крупнейших игр, использующих Python для своих нужд.
Mount & Blade
(2008 / Tale Worlds / Турция)
Ролевая игра, действие которой происходит в средние века. Игра была разработана всего лишь двумя людьми, мужем и женой, они использовали скрипты на языке Python для обеспечения модульности игры. Особенности игры — это огромный игровой мир и эпические сражения в реальном времени.
Sims 4
(2014 / Е.А. Maxis Sims Studio / США)
По праву является самой известной игрой в жанре симуляции жизни. Sims 4 — первая компьютерная игра, которая занимала лидирующие позиции на всевозможных игровых чартах на протяжении двух лет, и продалась в объеме 408,150 экземпляров по всему миру в течение первых четырех дней. На сегодняшний день продано более 1.1 миллиона копий по всему миру, что делает Sims 4 одной из самых продаваемых игр, которые использует Python — для обеспечения внутриигрового моддинга, открывающего пользователям огромные возможности по изменению параметров игры.
Civilization IV
(2005 / Firaxis Games / США)
Это компьютерная игра в жанре пошаговой стратегии. Цель игрока — подчинить себе весь мир путем дипломатических переговоров или кровожадной войны. Большая часть игры написана на Python, и Boost Python, что дает возможность пользователям собственноручно создавать модификации для игры.
Frets On Fire (FoF)
(2006 / Unreal Voodoo / Финляндия)
Музыкальная игра с открытым и свободным исходным кодом, которая сама по себе имитирует коммерческую игру Guitar Hero. Игра полностью написана на Python с использованием библиотеки Pygame. Благодаря открытости и простоте кода, игра представляется как хорошая площадка для изучения и практики программирования.
Спасибо CheckiO за интересную статью.
20 бесплатных онлайн-игр для программистов: лёгкое изучение
Эта подборка включает бесплатные онлайн-игры для программистов, которые позволят в увлекательной форме освоить JavaScript, Java, Python, PHP, C# и другие языки.
А для тех, кто всегда в дороге, мы собрали лучшие мобильные приложения по программированию.
Примечание Вы читаете улучшенную версию некогда выпущенной нами статьи.
1
CodinGame
На CodinGame с помощью написания кода и создания собственного «искусственного интеллекта» вам предстоит решить самые разнообразные и весёлые проблемы. Сайт поддерживает все языки программирования.
2
CodeCombat
CodeCombat — это не просто игра по программированию, а настоящая платформа для учащихся, позволяющая легко осваивать компьютерные науки.
Красочная анимация и интересный сюжет, кланы, взаимодействие с тысячами других игроков по всему миру. Поддерживаются такие языки, как Java, JavaScript, Python, Lua, CoffeeScript. Есть русская локализация.
3
Ruby Warrior
Если вы хотите изучить Ruby, то Ruby Warrior — то, что вам нужно: отличная игра для начинающих программистов. Есть два уровня сложности, соответствующих вашим навыкам. Для сохранения своего прогресса придётся залогиниться через Facebook.
4
Check iO
Check iO — это браузерная игра в жанре «Приключение», которая научит вас программированию на Python.
5
Code Hunt
В онлайн-игре для программистов Code Hunt вы, охотник за кодом, исправляете код, чтобы он возвращал нужный результат. Для прохождения доступны 14 уровней, в каждом из которых есть по несколько заданий. Игра подойдёт тем, кто хочет изучить Java или C#.
6
Vim Adventures
Давно хотели собраться с силами и выучить Vim полностью? Игра Vim Adventures поможет сделать это в наиболее весёлой и интерактивной форме.
7
Robocode
Любите битвы роботов? Тогда игра Robocode для вас. Вы научитесь программировать путём создания боевых роботов-танков на Java или .NET. Когда вы создадите робота, на экране в реальном времени начнётся битва.
8
Cyber DoJo
Cyber Dojo — это пространство, где разработчики могут собираться вместе и изучать такие языки программирования, как JavaScript, Java, Python, PHP, Ruby и многие другие.
Репозиторий проекта на GitHub.
9
Code Monkey
В игре для программистов Code Monkey вы научитесь кодить онлайн, хватая бананы. На западе учителя часто используют Code Monkey для преподавания программирования на CoffeScript и Python.
10
Elevator Saga
В Elevator Saga вам предстоит управлять настоящим лифтом с помощью JavaScript, разгадывая различные задачки. Например, первое задание — доставить лифтом 15 человек меньше чем за 60 секунд.
Также есть открытый репозиторий.
11
Codewars
Улучшайте свои навыки программирования совместно с другими людьми через решение реальных IT-проблем и задач на Codewars. Поддерживает JavaScript, C#, Java, Python и другие языки.
12
Git Game
Git Game — консольная онлайн-игра для программистов, пройдя которую вы овладеете системой контроля версий Git. Суть заключается в использовании различных команд, чтобы найти подсказки для решения разных загадок.
13
Hacker
На Hacker.org вы найдете набор пазлов, тестов, викторин и других игр по программированию, которые прокачают ваши хакерские навыки. К концу игры вы научитесь взламывать настоящие шифры.
14
Hex Invaders
В этой версии классической аркады на мир нападают три инопланетянина разных цветов. Чтобы спасти человечество, игрок должен быстро переводить шестнадцатеричное значение цвета на человеческий язык и сбивать пришельцев.
15
Flexbox Froggy
Flexbox Froggy — это логическая онлайн-игра для программистов, в которой вы должны помочь лягушкам добраться до их кувшинок. Делается это с помощью CSS Flexbox, что очень поможет развить навыки вёрстки.
Также у нас есть статья, из которой вы узнаете, как работает CSS Flexbox.
16
Pixactly
Pixactly — это простая по виду, но не по содержанию игра для начинающих программистов. Вам даётся местоположение двух пикселей, а вы должны нарисовать по этим координатам прямоугольник.
17
CSS Diner
Отличная игра для знакомства с CSS-селекторами. Игроку даётся стол с посудой, заданный анимированной HTML-формой, и конкретный предмет или предметы, которые нужно взять со стола. Изучено будет всё, от основ до ~
и :first-child
.
18
Flexbox Defense
Классический Tower Defense с привкусом CSS — все башни и ловушки нужно размещать при помощи гибкой вёрстки. Игра состоит из 12 уровней, которые потребуют от вас вспомнить все тонкости системы Flexbox.
19
Untrusted
Untrusted — это мета-JavaScript-адвенчура, в которой вы играете за персонажа по имени Dr. Eval — символ @, который может изменять окружающий мир, модифицируя его исходный код (ух, прям Матрица ? ). Игроку предоставляются функции, инициализирующие каждый уровень, и API, с помощью которого нужно прокладывать путь к выходу из уровня.
20
Dungeons & Developers
Одна из самых увлекательных игр для программистов онлайн. Дерево магических навыков, но магия эта — не льда и пламени, а веб-разработки. Отмечайте свои знания CSS, HTML и JavaScript и следите за продвижением к званию Мастера.
По материалам Hackernoon
Курс «Программирование игр на Python» – школа программирования Coddy в Москве
GameDev – не просто модный тег, созданный для описания прикладной сферы использования языков программирования. Разработка игр – это глубокий и насыщенный мир, в котором одинаково комфортно чувствуют себя как подростки, только начинающие изучать кодинг и создающие свои первые игры, так и титаны индустрии, зарабатывающие миллионные состоянии на деле, приносящем не только доход, но и эстетическое удовольствие. Истоки многих крупных игровых стартапов находятся именно в любительском программировании игр и графики.
Одним из наиболее удобных и популярных языков разработки является Python. Скорость и простота создания программ на нем заработали ему надежную репутацию в самых разных областях. На Python работают служба совместного использования видеоматериалов YouTube и клиентское и серверное ПО хранилища Dropbox, Intel, Hewlett-Packard и IBM используют Python для аппаратного тестирования, Industrial Light & Magic, Pixar и другие компании используют Python в производстве анимационных фильмов. Высока роль Python в инфраструктурах ПО Netflix и Yelp, NASA используют Python для решения задач научного программирования, а для шифрования и анализа разведывательной информации язык Python использует даже Агентство национальной безопасности США.
Стандартная реализация языка Python написана на языке Си, компилируется и запускается практически на любой применяемой в настоящее время платформе: от компьютеров и игровых приставок до цифровых ассистентов и крупнейших суперкомпьютеров, что делает Python одним из самых актуальных кроссплатформенных языков программирования.
Программирование игр и создание мультимедиа-содержимого – одни из «коньков» Python. Помимо множества проектов от независимых разработчиков, на Python писались и культовые игры. Так, грандиозный космический симулятор EVE Online от исландской компании CCP Games, представляющий собой массовую многопользовательскую ролевую онлайн-игру, широко применяет Python. В не менее легендарной Civilization IV настраиваемые сценарные события написаны целиком на Python.
Подростковый возраст от 10 до 14 лет – самое подходящее время для начала программирования на Python. Разработка игр, как инструмент обучения, является наиболее удобным форматом освоения языка. На занятиях слушатели курса:
— изучат основы востребованного языка Python;
— научатся рисовать и анимировать нарисованное с помощью кода;
— напишут собственные игры.
Системные требования к компьютеру
Просьба убедиться, что Ваш компьютер подходит для курса. Рекомендации по ссылке
Инструкция по установке программ для курса «Программирование игр на Python».
Скачать по ссылке
Открыть инструкцию по установке VSCode для работы с Python здесь.
По завершении курса каждый ученик получает именной сертификат от CODDY.
Игра Тетрис на PyQt5 | Python 3 для начинающих и чайников
Игра Тетрис – одна из самых популярных компьютерных игр. Оригинальная игра была разработана и запрограммирована русским программистом Алексеем Пажитновым в 1985 году. С тех пор Тетрис доступен на почти каждой компьютерной платформе в множестве вариаций.
Создание простой компьютерной игры на PyQt5 – отличный способ повышения навыков программирования.
Тетрисом называется игра-головоломка с падающими блоками. В этой игре, мы имеем 7 разных фигур, называемых так: S-фигура, Z-фигура, T-фигура, L-фигура, фигура-линия, фигура «Г», и квадрат. Каждая из этих фигур формируется с помощью четырёх квадратиков. Фигуры падают вниз на доску. Цель игры Тетрис – перемещать и вращать фигуры так, чтобы их приземлилось как можно больше. Если мы сумеем сформировать ряд, ряд разрушается и мы получаем очки. Мы играем в Тетрис до тех пор, пока не достигнем верха.
Разработка
У нас нет изображений для нашего Тетриса, мы рисуем тетрамино, используя доступное в программном инструментарии PyQt5 инструменты рисования. У каждой компьютерной игры имеется математическая модель. Также и в Тетрисе.
Некоторые идеи, применяющиеся в игре:
- Мы используем QtCore.QBasicTimer(), чтобы создать игровой цикл.
- Тетрамино рисуются.
- Фигуры перемещаются по принципу «кубик за кубиком» (не «пиксель за пикселем»).
- Математически, доска – это просто список чисел.
Код содержит четыре класса: Tetris, Board, Tetrominoe и Shape. Класс Tetris организовывает игру. Board – это то, где пишется игровая логика. Класс Tetrominoe содержит имена всех частей тетриса и класс Shape содержит код для частей тетриса.
Код игры Тетрис:
#!/usr/bin/python3 # -*- coding: utf-8 -*- import sys, random from PyQt5.QtWidgets import QMainWindow, QFrame, QDesktopWidget, QApplication from PyQt5.QtCore import Qt, QBasicTimer, pyqtSignal from PyQt5.QtGui import QPainter, QColor class Tetris(QMainWindow): def __init__(self): super().__init__() self.initUI() def initUI(self): self.tboard = Board(self) self.setCentralWidget(self.tboard) self.statusbar = self.statusBar() self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage) self.tboard.start() self.resize(180, 380) self.center() self.setWindowTitle('Tetris') self.show() def center(self): screen = QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2) class Board(QFrame): msg2Statusbar = pyqtSignal(str) BoardWidth = 10 BoardHeight = 22 Speed = 300 def __init__(self, parent): super().__init__(parent) self.initBoard() def initBoard(self): self.timer = QBasicTimer() self.isWaitingAfterLine = False self.curX = 0 self.curY = 0 self.numLinesRemoved = 0 self.board = [] self.setFocusPolicy(Qt.StrongFocus) self.isStarted = False self.isPaused = False self.clearBoard() def shapeAt(self, x, y): return self.board[(y * Board.BoardWidth) + x] def setShapeAt(self, x, y, shape): self.board[(y * Board.BoardWidth) + x] = shape def squareWidth(self): return self.contentsRect().width() // Board.BoardWidth def squareHeight(self): return self.contentsRect().height() // Board.BoardHeight def start(self): if self.isPaused: return self.isStarted = True self.isWaitingAfterLine = False self.numLinesRemoved = 0 self.clearBoard() self.msg2Statusbar.emit(str(self.numLinesRemoved)) self.newPiece() self.timer.start(Board.Speed, self) def pause(self): if not self.isStarted: return self.isPaused = not self.isPaused if self.isPaused: self.timer.stop() self.msg2Statusbar.emit("paused") else: self.timer.start(Board.Speed, self) self.msg2Statusbar.emit(str(self.numLinesRemoved)) self.update() def paintEvent(self, event): painter = QPainter(self) rect = self.contentsRect() boardTop = rect.bottom() - Board.BoardHeight * self.squareHeight() for i in range(Board.BoardHeight): for j in range(Board.BoardWidth): shape = self.shapeAt(j, Board.BoardHeight - i - 1) if shape != Tetrominoe.NoShape: self.drawSquare(painter, rect.left() + j * self.squareWidth(), boardTop + i * self.squareHeight(), shape) if self.curPiece.shape() != Tetrominoe.NoShape: for i in range(4): x = self.curX + self.curPiece.x(i) y = self.curY - self.curPiece.y(i) self.drawSquare(painter, rect.left() + x * self.squareWidth(), boardTop + (Board.BoardHeight - y - 1) * self.squareHeight(), self.curPiece.shape()) def keyPressEvent(self, event): if not self.isStarted or self.curPiece.shape() == Tetrominoe.NoShape: super(Board, self).keyPressEvent(event) return key = event.key() if key == Qt.Key_P: self.pause() return if self.isPaused: return elif key == Qt.Key_Left: self.tryMove(self.curPiece, self.curX - 1, self.curY) elif key == Qt.Key_Right: self.tryMove(self.curPiece, self.curX + 1, self.curY) elif key == Qt.Key_Down: self.tryMove(self.curPiece.rotateRight(), self.curX, self.curY) elif key == Qt.Key_Up: self.tryMove(self.curPiece.rotateLeft(), self.curX, self.curY) elif key == Qt.Key_Space: self.dropDown() elif key == Qt.Key_D: self.oneLineDown() else: super(Board, self).keyPressEvent(event) def timerEvent(self, event): if event.timerId() == self.timer.timerId(): if self.isWaitingAfterLine: self.isWaitingAfterLine = False self.newPiece() else: self.oneLineDown() else: super(Board, self).timerEvent(event) def clearBoard(self): for i in range(Board.BoardHeight * Board.BoardWidth): self.board.append(Tetrominoe.NoShape) def dropDown(self): newY = self.curY while newY > 0: if not self.tryMove(self.curPiece, self.curX, newY - 1): break newY -= 1 self.pieceDropped() def oneLineDown(self): if not self.tryMove(self.curPiece, self.curX, self.curY - 1): self.pieceDropped() def pieceDropped(self): for i in range(4): x = self.curX + self.curPiece.x(i) y = self.curY - self.curPiece.y(i) self.setShapeAt(x, y, self.curPiece.shape()) self.removeFullLines() if not self.isWaitingAfterLine: self.newPiece() def removeFullLines(self): numFullLines = 0 rowsToRemove = [] for i in range(Board.BoardHeight): n = 0 for j in range(Board.BoardWidth): if not self.shapeAt(j, i) == Tetrominoe.NoShape: n = n + 1 if n == 10: rowsToRemove.append(i) rowsToRemove.reverse() for m in rowsToRemove: for k in range(m, Board.BoardHeight): for l in range(Board.BoardWidth): self.setShapeAt(l, k, self.shapeAt(l, k + 1)) numFullLines = numFullLines + len(rowsToRemove) if numFullLines > 0: self.numLinesRemoved = self.numLinesRemoved + numFullLines self.msg2Statusbar.emit(str(self.numLinesRemoved)) self.isWaitingAfterLine = True self.curPiece.setShape(Tetrominoe.NoShape) self.update() def newPiece(self): self.curPiece = Shape() self.curPiece.setRandomShape() self.curX = Board.BoardWidth // 2 + 1 self.curY = Board.BoardHeight - 1 + self.curPiece.minY() if not self.tryMove(self.curPiece, self.curX, self.curY): self.curPiece.setShape(Tetrominoe.NoShape) self.timer.stop() self.isStarted = False self.msg2Statusbar.emit("Game over") def tryMove(self, newPiece, newX, newY): for i in range(4): x = newX + newPiece.x(i) y = newY - newPiece.y(i) if x < 0 or x >= Board.BoardWidth or y < 0 or y >= Board.BoardHeight: return False if self.shapeAt(x, y) != Tetrominoe.NoShape: return False self.curPiece = newPiece self.curX = newX self.curY = newY self.update() return True def drawSquare(self, painter, x, y, shape): colorTable = [0x000000, 0xCC6666, 0x66CC66, 0x6666CC, 0xCCCC66, 0xCC66CC, 0x66CCCC, 0xDAAA00] color = QColor(colorTable[shape]) painter.fillRect(x + 1, y + 1, self.squareWidth() - 2, self.squareHeight() - 2, color) painter.setPen(color.lighter()) painter.drawLine(x, y + self.squareHeight() - 1, x, y) painter.drawLine(x, y, x + self.squareWidth() - 1, y) painter.setPen(color.darker()) painter.drawLine(x + 1, y + self.squareHeight() - 1, x + self.squareWidth() - 1, y + self.squareHeight() - 1) painter.drawLine(x + self.squareWidth() - 1, y + self.squareHeight() - 1, x + self.squareWidth() - 1, y + 1) class Tetrominoe(object): NoShape = 0 ZShape = 1 SShape = 2 LineShape = 3 TShape = 4 SquareShape = 5 LShape = 6 MirroredLShape = 7 class Shape(object): coordsTable = ( ((0, 0), (0, 0), (0, 0), (0, 0)), ((0, -1), (0, 0), (-1, 0), (-1, 1)), ((0, -1), (0, 0), (1, 0), (1, 1)), ((0, -1), (0, 0), (0, 1), (0, 2)), ((-1, 0), (0, 0), (1, 0), (0, 1)), ((0, 0), (1, 0), (0, 1), (1, 1)), ((-1, -1), (0, -1), (0, 0), (0, 1)), ((1, -1), (0, -1), (0, 0), (0, 1)) ) def __init__(self): self.coords = [[0,0] for i in range(4)] self.pieceShape = Tetrominoe.NoShape self.setShape(Tetrominoe.NoShape) def shape(self): return self.pieceShape def setShape(self, shape): table = Shape.coordsTable[shape] for i in range(4): for j in range(2): self.coords[i][j] = table[i][j] self.pieceShape = shape def setRandomShape(self): self.setShape(random.randint(1, 7)) def x(self, index): return self.coords[index][0] def y(self, index): return self.coords[index][1] def setX(self, index, x): self.coords[index][0] = x def setY(self, index, y): self.coords[index][1] = y def minX(self): m = self.coords[0][0] for i in range(4): m = min(m, self.coords[i][0]) return m def maxX(self): m = self.coords[0][0] for i in range(4): m = max(m, self.coords[i][0]) return m def minY(self): m = self.coords[0][1] for i in range(4): m = min(m, self.coords[i][1]) return m def maxY(self): m = self.coords[0][1] for i in range(4): m = max(m, self.coords[i][1]) return m def rotateLeft(self): if self.pieceShape == Tetrominoe.SquareShape: return self result = Shape() result.pieceShape = self.pieceShape for i in range(4): result.setX(i, self.y(i)) result.setY(i, -self.x(i)) return result def rotateRight(self): if self.pieceShape == Tetrominoe.SquareShape: return self result = Shape() result.pieceShape = self.pieceShape for i in range(4): result.setX(i, -self.y(i)) result.setY(i, self.x(i)) return result if __name__ == '__main__': app = QApplication([]) tetris = Tetris() sys.exit(app.exec_())
Игра немного упрощена для более легкого понимания. Игра начинается сразу же после её запуска. Мы можем приостановить игру, нажав клавишу p. Клавиша Space будет немедленно бросать блок тетриса вниз. Игра идёт на постоянной скорости, ускорение не реализуется. Очки – это число линий, который мы удалили.
self.tboard = Board(self) self.setCentralWidget(self.tboard)
Экземпляр класса Board создаётся и устанавливается центральным виджетом приложения.
self.statusbar = self.statusBar() self.tboard.msg2Statusbar[str].connect(self.statusbar.showMessage)
Мы создаём строку состояния, где мы будем отображать сообщения. Мы будем отображать три возможных сообщения: количество уже удалённых линий, сообщение паузы, или сообщение «Игра окончена». msgStatusbar – это пользовательский сигнал, который реализуется в классе Board. showMessage() – это встроенный метод, который отображает сообщение в строке состояния.
self.tboard.start()
Эта строка инициирует игру.
class Board(QFrame): msg2Statusbar = pyqtSignal(str) ...
Создаётся пользовательский сигнал. msgStatusbar – это сигнал, который срабатывает, когда мы хотим написать сообщение или количество очков в строку состояния.
BoardWidth = 10 BoardHeight = 22 Speed = 300
Это переменные класса Board. BoardWidth и BoardHeight определяют размер доски в блоках. Speed определяет скорость игры. Каждые 300 мс будет начинаться цикл новой игры.
... self.curX = 0 self.curY = 0 self.numLinesRemoved = 0 self.board = [] ...
В методе initBoard() мы инициализируем несколько важных переменных. Переменная self.board – это список чисел от 0 до 7. Она представляет местоположение различных фигур и оставляет фигуры на доске.
def shapeAt(self, x, y): return self.board[(y * Board.BoardWidth) + x]
Метод shapeAt() определяет тип фигуры в данном блоке.
def squareWidth(self): return self.contentsRect().width() // Board.BoardWidth
Доска может динамически менять размер (например, при изменении размера окна). Как следствие, размер блока может меняться. squareWidth() вычисляет ширину простого квадратика в пикселях и возвращает её. Board.BoardWidth – это размер доски в блоках.
for i in range(Board.BoardHeight): for j in range(Board.BoardWidth): shape = self.shapeAt(j, Board.BoardHeight - i - 1) if shape != Tetrominoe.NoShape: self.drawSquare(painter, rect.left() + j * self.squareWidth(), boardTop + i * self.squareHeight(), shape)
Рисование игры разделяется на два шага. Первым шагом, мы рисуем все фигуры, или оставляем фигуры, которые были сброшены вниз доски. Все квадратики запоминаются в списке переменных self.board. Доступ к переменной получают, используя метод shapeAt().
if self.curPiece.shape() != Tetrominoe.NoShape: for i in range(4): x = self.curX + self.curPiece.x(i) y = self.curY - self.curPiece.y(i) self.drawSquare(painter, rect.left() + x * self.squareWidth(), boardTop + (Board.BoardHeight - y - 1) * self.squareHeight(), self.curPiece.shape())
Следующий шаг – это рисование упавших вниз частей.
elif key == Qt.Key_Right: self.tryMove(self.curPiece, self.curX + 1, self.curY)
В методе keyPressEvent(), мы проверяем нажатые клавиши. Если мы нажали клавишу правой стрелки, мы пробуем передвинуть часть вправо. Мы говорим «пробуем», поскольку часть может быть на правом крае.
elif key == Qt.Key_Up: self.tryMove(self.curPiece.rotateLeft(), self.curX, self.curY)
Клавиша стрелки вверх будет поворачивать падающую часть влево.
elif key == Qt.Key_Space: self.dropDown()
Клавиша «Пробел» будет немедленно бросать падающую часть.
elif key == Qt.Key_D: self.oneLineDown()
Нажимая клавишу «d», часть спустится вниз на один блок. Это может быть использовано, чтобы слегка ускорить падение части.
def tryMove(self, newPiece, newX, newY): for i in range(4): x = newX + newPiece.x(i) y = newY - newPiece.y(i) if x < 0 or x >= Board.BoardWidth or y < 0 or y >= Board.BoardHeight: return False if self.shapeAt(x, y) != Tetrominoe.NoShape: return False self.curPiece = newPiece self.curX = newX self.curY = newY self.update() return True
В методе tryMove(), мы пробуем переместить наши фигуры. Если фигура находится на краю доски или примыкает к некоторой другой части, мы возвращаем значение «Ложь». В противном случае, мы перемещаем текущую падающую часть в новую позицию.
def timerEvent(self, event): if event.timerId() == self.timer.timerId(): if self.isWaitingAfterLine: self.isWaitingAfterLine = False self.newPiece() else: self.oneLineDown() else: super(Board, self).timerEvent(event)
В timerEvent (событии таймера), мы либо создаём новую фигуру после предыдущей, которая упала, либо мы передвигаем падающую часть на одну линию вниз.
def clearBoard(self): for i in range(Board.BoardHeight * Board.BoardWidth): self.board.append(Tetrominoe.NoShape)
Метод clearBoard() очищает доску путём установки Tetrominoe.Noshape на каждый блок доски.
def removeFullLines(self): numFullLines = 0 rowsToRemove = [] for i in range(Board.BoardHeight): n = 0 for j in range(Board.BoardWidth): if not self.shapeAt(j, i) == Tetrominoe.NoShape: n = n + 1 if n == 10: rowsToRemove.append(i) rowsToRemove.reverse() for m in rowsToRemove: for k in range(m, Board.BoardHeight): for l in range(Board.BoardWidth): self.setShapeAt(l, k, self.shapeAt(l, k + 1)) numFullLines = numFullLines + len(rowsToRemove) ...
Когда фигура падает, мы вызываем метод removeFullLines(). Мы обнаруживаем все полные линии и удаляем их. Обратите внимание, что мы развернули порядок удаляемых линий. В противном случае, это не будет работать правильно. В нашем случае, мы используем «никакую» гравитацию. Это означает, что части могут парить над пустыми промежутками.
def newPiece(self): self.curPiece = Shape() self.curPiece.setRandomShape() self.curX = Board.BoardWidth // 2 + 1 self.curY = Board.BoardHeight - 1 + self.curPiece.minY() if not self.tryMove(self.curPiece, self.curX, self.curY): self.curPiece.setShape(Tetrominoe.NoShape) self.timer.stop() self.isStarted = False self.msg2Statusbar.emit("Game over")
Метод newPiece() случайным образом создаёт новую часть тетриса. Если часть не может прийти в свою начальную позицию, игра заканчивается.
class Tetrominoe(object): NoShape = 0 ZShape = 1 SShape = 2 LineShape = 3 TShape = 4 SquareShape = 5 LShape = 6 MirroredLShape = 7
Класс Tetrominoe содержит в себе имена всех возможных фигур. Мы также имеем NoShape для пустого пространства.
class Shape(object): coordsTable = ( ((0, 0), (0, 0), (0, 0), (0, 0)), ((0, -1), (0, 0), (-1, 0), (-1, 1)), ... ) ...
Класс Shape хранит информацию о частях тетриса.
Набор coordsTable содержит в себе всевозможные значения координат наших частей тетриса. Это шаблон, из которого все части берут свои значения координат.
self.coords = [[0,0] for i in range(4)]
После создания, мы создаём пустой список координат. Список будет хранить координаты частей тетриса.
Изображение выше поможет понять значения координат. Для примера, набор (0, -1), (0, 0), (-1, 0), (-1, -1) представляет S-фигуру. Схема иллюстрирует фигуру.
def rotateLeft(self): if self.pieceShape == Tetrominoe.SquareShape: return self result = Shape() result.pieceShape = self.pieceShape for i in range(4): result.setX(i, self.y(i)) result.setY(i, -self.x(i)) return result
Метод rotateLeft() поворачивает часть влево. Квадрат не должен поворачиваться. Вот почему мы просто возвращаем ссылку на текущий объект. Новая часть создаётся и её координаты устанавливаются в одну из повернутых частей.
Это была игра Тетрис в PyQt5 (а также перевод последней части туториала от zetcode).
Создание игр на Python 3 и Pygame: Часть 1 / Хабр
Многие разработчики приходят в разработку ПО, потому что хотят создавать игры. Не все могут стать профессиональными разработчиками игр, но любой может создавать собственные игры из интереса (а может быть, и с выгодой). В этом туториале, состоящем из пяти частей, я расскажу вам, как создавать двухмерные однопользовательские игры с помощью Python 3 и замечательного фреймворка PyGame.
(Остальные части туториала: вторая, третья, четвёртая, пятая.)
Мы создадим версию классической игры Breakout. Освоив этот туториал, вы будете чётко понимать, что необходимо для создания игры, познакомитесь с возможностями Pygame и напишете собственный пример игры.
Мы реализуем следующие функции и возможности:
- простые стандартные GameObject и TextObject
- простой стандартный Game object
- простая стандартная кнопка
- файл конфигурации
- обработка событий клавиатуры и мыши
- кирпичи, ракетка и мяч
- управление движением ракетки
- обработка коллизий мяча с объектами игры
- фоновое изображение
- звуковые эффекты
- расширяемая система спецэффектов
Не стоит ожидать
, что игра будет очень красива графически. Я программист, а не художник, меня больше интересует эстетика кода. Созданный мной дизайн может неприятно удивить. С другой стороны, у вас будут почти неограниченные возможности по улучшению графики этой версии Breakout. Если вы отважитесь повторять за мной, посмотрите на скриншот:
Готовый исходный код выложен
здесь
.
Краткое введение в программирование игр
Главное в играх — перемещение пикселей на экране и издаваемый шум. Почти во всех видеоиграх есть эти элементы. В этой статье мы не будем рассматривать клиент-серверные и многопользовательские игры, для которых требуется много сетевого программирования.
Основной цикл
Основной цикл (main loop) игры выполняется и обновляет экран через фиксированные интервалы времени. Они называются частотой кадров и определяют плавность перемещения. Обычно игры обновляют экран 30-60 раз в секунду. Если частота будет меньше, то покажется, что объекты на экране дёргаются.
Внутри основного цикла есть три основных операции: обработка событий, обновление состояния игры и отрисовка текущего состояния на экране.
Обработка событий
События в игре состоят из всего, что происходит за пределами управления кода игры, но относится к выполнению игры. Например, если в Breakout игрок нажимает клавишу «стрелка влево», то игре нужно переместить ракетку влево. Стандартными событиями являются нажатия (и отжатия) клавиш, движение мыши, нажатия кнопок мыши (особенно в меню) и события таймера (например, действие спецэффекта может длиться 10 секунд).
Обновление состояния
Сердце любой игры — это её состояние: всё то, что она отслеживает и отрисовывает на экране. В случае Breakout к состоянию относятся положение всех кирпичей, позиция и скорость мяча, положение ракетки, а также жизни и очки.
Существует также вспомогательное состояние, позволяющее управлять игрой:
- Отображается ли сейчас меню?
- Закончена ли игра?
- Победил ли игрок?
Отрисовка
Игре нужно отображать своё состояние на экране, в том числе отрисовывать геометрические фигуры, изображения и текст.
Игровая физика
В большинстве игр симулируется физическое окружение. В Breakout мяч отскакивает от объектов и имеет
очень
приблизительную систему физики твёрдого тела (если это можно так назвать).
В более сложных играх могут использоваться более изощрённые и реалистичные физические системы (особенно в 3D-играх). Стоит также отметить, что в некоторых играх, например, в карточных, физики почти нет, и это совершенно нормально.
ИИ (искусственный интеллект)
Во многих играх мы сражаемся с компьютерными противниками, или в них есть враги, пытающиеся нас убить. Часто они ведут себя в игровом мире так, как будто обладают разумом.
Например, враги преследуют игрока и знают о его местоположении. В Breakout нет никакого ИИ. Игрок сражается с холодными и твёрдыми кирпичами. Однако ИИ в играх часто очень прост и всего лишь следует простым (или сложным) правилам, обеспечивающим псевдоразумные результаты.
Воспроизведение звука
Воспроизведение звука — ещё один важный аспект игр. В общем случае существует два типа звука: фоновая музыка и звуковые эффекты. В Breakout я реализую только звуковые эффекты, которые воспроизводятся при различных событиях.
Фоновая музыка — это просто музыка, постоянно играющая на фоне. В некоторых играх она не используется, а в некоторых меняется на каждом уровне.
Жизни, очки и уровни
В большинстве игр игрок имеет определённое количество жизней, и когда они заканчиваются, игра завершается. Также в играх часто присутствуют очки, позволяющие понять, насколько хорошо мы играем, и дающие мотивацию к самосовершенствованию или просто хвастаться друзьям своими рекордами. Во многих играх есть уровни, которые или совершенно отличаются, или постепенно увеличивают сложность.
Знакомство с Pygame
Прежде чем приступить к реализации игры, давайте немного узнаем о Pygame, который возьмёт на себя большую часть работы.
Что такое Pygame?
Pygame — это фреймворк языка Python для программирования игр. Он создан поверх
SDL
и обладает всем необходимым:
- зрелостью
- хорошим сообществом
- открытым исходным кодом
- кроссплатформенностью
- качественной документацией
- множеством примеров игр
- простотой изучения
Установка Pygame
Введите
pip install pygame
, чтобы установить фреймворк. Если вам нужно что-то ещё, то следуйте инструкциям из раздела
Getting Started
в Wiki проекта. Если у вас, как и у меня, macOS Sierra, то могут возникнуть проблемы. Мне удалось установить Pygame без сложностей, и код работает отлично, но окно игры никогда не появляется.
Это станет серьёзным препятствием при запуске игры. В конце концов мне пришлось запускать её в Windows внутри VirtualBox VM. Надеюсь, ко времени прочтения этой статьи проблема будет решена.
Архитектура игры
Играм нужно управлять кучей информации и выполнять почти одинаковые операции со множеством объектов. Breakout — это небольшая игра, однако попытка управлять всем в одном файле может оказаться слишком утомительной. Поэтому я решил создать файловую структуру и архитектуру, которая подойдёт и для гораздо более крупных игр.
Структура папок и файлов
├── Pipfile ├── Pipfile.lock ├── README.md ├── ball.py ├── breakout.py ├── brick.py ├── button.py ├── colors.py ├── config.py ├── game.py ├── game_object.py ├── images │ └── background.jpg ├── paddle.py ├── sound_effects │ ├── brick_hit.wav │ ├── effect_done.wav │ ├── level_complete.wav │ └── paddle_hit.wav └── text_object.py
Pipfile и Pipfile.lock — это современный способ управления зависимостями в Python. Папка images содержит изображения, используемые игрой (в нашей версии будет только фоновое изображение), а в папке sound_effects directory лежат короткие звуковые клипы, используемые (как можно догадаться) в качестве звуковых эффектов.
Файлы ball.py, paddle.py и brick.py содержат код, относящийся к каждому из этих объектов Breakout. Подробнее я рассмотрю их в следующих частях туториала. Файл text_object.py содержит код отображения текста на экране, а в файле background.py содержится игровая логика Breakout.
Однако существует несколько модулей, создающих произвольный «скелет» общего назначения. Определённые в них классы можно будет использовать в других играх на основе Pygame.
Класс GameObject
GameObject представляет собой визуальный объект, знающий о том, как себя рендерить, сохранять свои границы и перемещаться. В Pygame есть и класс Sprite, исполняющий похожую роль, но в этом туториале я хочу показать вам, как всё работает на низком уровне, а не полагаться слишком активно на готовую магию. Вот как выглядит класс GameObject:
from pygame.rect import Rect
class GameObject:
def __init__(self, x, y, w, h, speed=(0,0)):
self.bounds = Rect(x, y, w, h)
self.speed = speed
@property
def left(self):
return self.bounds.left
@property
def right(self):
return self.bounds.right
@property
def top(self):
return self.bounds.top
@property
def bottom(self):
return self.bounds.bottom
@property
def width(self):
return self.bounds.width
@property
def height(self):
return self.bounds.height
@property
def center(self):
return self.bounds.center
@property
def centerx(self):
return self.bounds.centerx
@property
def centery(self):
return self.bounds.centery
def draw(self, surface):
pass
def move(self, dx, dy):
self.bounds = self.bounds.move(dx, dy)
def update(self):
if self.speed == [0, 0]:
return
self.move(*self.speed)
GameObject предназначен для того, чтобы быть базовым классом для других объектов. Он непосредственно раскрывает множество свойств его прямоугольника self.bounds, а в своём методе
update()
он перемещает объект в соответствии с его текущей скоростью. Он ничего не делает в своём методе
draw()
, который должен быть переопределён подклассами.
Класс Game
Класс Game — это ядро игры. Он выполняется в основном цикле. В нём есть множество полезных возможностей. Давайте разберём его метод за методом.
Метод __init__()
инициализирует сам Pygame, систему шрифтов и звуковой микшер. Три разных вызова нужны, так как не во всякой игре на Pygame используются все компоненты, поэтому можно контролировать подсистемы, которые мы используем, и инициализировать только нужные с соответствующими параметрами. Метод создаёт фоновое изображение, основную поверхность (на которой всё отрисовывается) и игровой таймер с правильной частотой кадров.
Элемент self.objects хранит все игровые объекты, которые должны рендериться и обновляться. Различные обработчики управляют списками функций-обработчиков, которые должны выполняться при определённых событиях.
import pygame
import sys
from collections import defaultdict
class Game:
def __init__(self,
caption,
width,
height,
back_image_filename,
frame_rate):
self.background_image = \
pygame.image.load(back_image_filename)
self.frame_rate = frame_rate
self.game_over = False
self.objects = []
pygame.mixer.pre_init(44100, 16, 2, 4096)
pygame.init()
pygame.font.init()
self.surface = pygame.display.set_mode((width, height))
pygame.display.set_caption(caption)
self.clock = pygame.time.Clock()
self.keydown_handlers = defaultdict(list)
self.keyup_handlers = defaultdict(list)
self.mouse_handlers = []
Методы
update()
и
draw()
очень просты. Они обходят все управляемые игровые объекты и вызывают соответствующие им методы. Если два объекта накладываются друг на друга на экране, то порядок списка объектов определяет, какой из них будет рендериться первым, а остальные будут частично или полностью его перекрывать.
def update(self):
for o in self.objects:
o.update()
def draw(self):
for o in self.objects:
o.draw(self.surface)
Метод
handle_events()
слушает события, генерируемые Pygame, такие как события клавиш и мыши. Для каждого события он вызывает все функции-обработчики, которые должны обрабатывать события соответствующих типов.
def handle_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
elif event.type == pygame.KEYDOWN:
for handler in self.keydown_handlers[event.key]:
handler(event.key)
elif event.type == pygame.KEYUP:
for handler in self.keydown_handlers[event.key]:
handler(event.key)
elif event.type in (pygame.MOUSEBUTTONDOWN,
pygame.MOUSEBUTTONUP,
pygame.MOUSEMOTION):
for handler in self.mouse_handlers:
handler(event.type, event.pos)
Наконец, метод
run()
выполняет основной цикл. Он выполняется до тех пор, пока элемент
game_over
не принимает значение True. В каждой итерации он рендерит фоновое изображение и вызывает по порядку методы
handle_events()
,
update()
и
draw()
.
Затем он обновляет экран, то есть записывает на физический дисплей всё содержимое, которое было отрендерено на текущей итерации. И последнее, но не менее важное — он вызывает метод clock.tick()
для управления тем, когда будет вызвана следующая итерация.
def run(self):
while not self.game_over:
self.surface.blit(self.background_image, (0, 0))
self.handle_events()
self.update()
self.draw()
pygame.display.update()
self.clock.tick(self.frame_rate)
Заключение
В этой части мы изучили основы программирования игр и все компоненты, участвующие в создании игр. Также мы рассмотрели сам Pygame и узнали, как его установить. Наконец, мы погрузились в архитектуру игры и изучили структуру папок, классы
GameObject
и Game.
Во второй части мы рассмотрим класс TextObject
, используемый для рендеринга текста на экране. Мы создадим основное окно, в том числе и фоновое изображение, а затем узнаем, как отрисовывать объекты (мяч и ракетку).
Создаем 2D игру на Python с библиотекой Arcade | by Andrew Prog
Python — выдающийся язык для начинающих изучать программирование. Он также идеально подходит тем, кто хочет “просто взять и сделать”, а не тратить кучу времени на шаблонный код. Arcade — библиотека Python для создания 2D игр, с низким порогом вхождения, но очень функциональная в опытных руках. В этом статье я объясню, как начать использовать Python и Arcade для программирования игр.
Я начал разрабатывать на Arcade после преподавания азов библиотеки PyGame студентам. Я очно преподавал PyGames в течение почти 10 лет, а также разработал ProgramArcadeGames.com для обучения онлайн. PyGames отличная, но в какой-то момент я понял, что устал тратить время на оправдание багов, которые никогда не фиксятся.
Меня беспокоило преподавание таких вещей, как событийный цикл, которым уже почти не пользовались. И был целый раздел, в котором я объяснял, почему y-координаты повернуты в противоположном направлении. PyGames обновлялась редко и базировалась на старой библиотеке SDL 1, а не чем-то более современном вроде OpenGL. На светлое будущее я не рассчитывал.
В моих мечтах была простая и мощная библиотека, которая бы использовала новые фичи Python 3, например, декораторы и тайп-хинтинг. Ей оказалась Arcade. Посмотрим, как начать ее использовать.
Arcade, как и многие другие пакеты, доступна на PyPi, а значит, можно установить Arcade при помощи команды pip (или pipenv). Если Python уже установлен, скорее всего можно просто открыть терминал и написать:
pip install arcade
Для более детализированной инструкции по установке, почитайте документацию по установке Arcade.
Вы можете открыть окно и нарисовать простой рисунок всего несколькими строчками кода. В качестве примера, нарисуем смайлик, как на картинке ниже:
Скрипт ниже показывает, как это сделать, используя команды рисования Arcade. Заметьте, что вам не обязательно знать, как использовать классы или определять функции. Программирование с быстрым визуальным фидбеком — хороший старт для тех, кто только учится.
Конечно, писать код в глобальном контексте — не лучший способ. К счастью, использование функций поможет улучшить ваш код. Ниже приведен пример того, как нарисовать елку в заданных координатах (x, y), используя функцию:
Для полного примера, посмотрите рисунок с функциями.
Более опытные программисты знают, что современные программы сначала загружают графическую информацию на видеокарту, а затем просят ее отрисовать batch-файлом. Arcade это поддерживает. Индивидуальная отрисовка 10000 прямоугольников занимает 0.8 секунды. Отрисовка того же количества батником займет менее 0.001 секунды.
Большие программы обычно базируются на классе Window или используют декораторы. Это позволяет программисту писать код, контролирующий отрисовку, обновление и обработку входных данных пользователя. Ниже приведен шаблон для программы с Window-основой.
В классе Window есть несколько методов, которые ваши программы могут переопределять для обеспечения функциональности. Вот список тех, что используются чаще всего:
- on_draw: Весь код для отрисовки экрана находится здесь.
- update: Весь код для перемещения объектов и отработки игровой логики находится здесь. Вызывается примерно 60 раз в секунду.
- on_key_press: Обрабатывает события при нажатии кнопки, например, движение персонажа.
- on_key_release: Обрабатывает события при отпускании кнопки, например, остановка персонажа.
- on_mouse_motion: Вызывается каждый раз при движении мышки.
- on_mouse_press: Вызывается при нажатии кнопки мыши.
- set_viewport: Эта функция используется в скроллерах, когда мир значительно больше, чем то что видно на одном экране. Вызов set_viewport позволяет программисту задать ту часть экрана, которая будет видна.
Спрайты — простой способ создания 2D bitmap объектов в Arcade. В нем есть методы, позволяющие с легкостью рисовать, перемещать и анимировать спрайты. Также можно использовать спрайты для отслеживания коллизий между объектами.
Создать инстанс Sprite класса Arcade очень легко. Программисту необходимо только название файла изображения, на котором будет основываться спрайт, и, опционально, число раз для увеличения или уменьшения изображения. Например:
Этот код создает спрайт, используя изображение coin_01.png. Картинка уменьшится до 20% от исходной.
Спрайты обычно организуются в списки. Они помогают упростить их управление. Спрайты в списке будут использовать OpenGl для групповой batch-отрисовки. Нижеприведенный код настраивает игру, где есть игрок и множество монет, которые игрок должен собрать. Мы используем два списка — один для игрока и один для монеток.
Мы с легкостью можем отрисовать все монетки в списке монеток:
Функция check_for_collision_with_list позволяет увидеть, если спрайт наталкивается на другой спрайт из списка. Используем ее, чтобы увидеть все монетки, с которыми пересекается спрайт игрока. Применив простой for- цикл, можно избавиться от монетки в игре и увеличить счет.
С полным примером можно ознакомиться в collect_coins.py.
Во многих играх есть физика в том или ином виде. Самые простое, например, что top-down игры не позволяют игроку проходить сквозь стены. Платформеры добавляют сложности с гравитацией и движущимися платформами. Некоторые игры используют полноценные физические 2D движки с массами, трением, пружинами и тд.
Для простых игр с видом сверху программе на Arcade необходим список стен (или чего-то подобного), через которые игрок не сможет проходить. Обычно я называю это wall_list. Затем создается физический движок в установочном коде класса Window:
player_sprite получает вектор движения с двумя атрибутами change_x и change_y. Просто пример использования — перемещение игрока с помощью клавиатуры.
Несмотря на то что этот код задает скорость игрока, он его не перемещает. Метод update в классе Window вызывает physics_engine.update(), что заставит игрока двигаться, но не через стены.
Пример полностью можно посмотреть в sprite_move_walls.py.
Переход к платформеру с видом сбоку достаточно прост. Программисту необходимо переключить физический движок на PhysicsEnginePlatformer и добавить гравитационную константу.
Для добавления тайлов и блоков, из которых будет состоять уровень, можно использовать программу вроде Tiled.
Пример доступен в sprite_tiled_map.py.
Учиться на примере — один из лучших методов. В библиотеке Arcade есть большой список образцов программ, на которые можно ориентироваться при создании игры.
Запускать демки при установленной Arcade совсем не сложно. В начале программы каждого примера есть комментарий с командой, которую нужно ввести в командную строку для запуска этого примера. Например:
python -m arcade.examples.sprite_moving_platforms
Первоисточник: https://realpython.com/python-async-features/
Перевел: MaxRokatansky
Написание игр для изучения Python и JavaScript
Какие языки программирования доступны?
В настоящее время мы поддерживаем Python и JavaScript.
Почему следует выбрать Python?
Python удобен для начинающих и в настоящее время используется крупными корпорациями (такими как Google). Если у вас есть ученики помоложе или впервые, мы настоятельно рекомендуем Python.
Почему вы должны выбрать JavaScript?
JavaScript — это язык Интернета, который используется почти на каждом веб-сайте.Вы можете предпочесть JavaScript, если планируете также изучать веб-разработку. Мы также упростили для студентов переход от Python к веб-разработке на основе JavaScript.
Синтаксис JavaScript немного сложнее для новичков, чем Python, поэтому, если вы не можете выбрать между ними, мы рекомендуем Python.
С чего начать?
- Создайте учетную запись учителя
- Создайте класс
- Добавьте учеников
- Устройтесь поудобнее и наблюдайте, как ваши ученики с удовольствием учатся кодировать
Могу ли я использовать CodeCombat или Ozaria в качестве основной учебной программы?
Совершенно верно! Мы потратили время на консультации со специалистами в области образования, чтобы разработать учебную программу и материалы специально для учителей, которые используют CodeCombat или Ozaria, но сами не имеют опыта работы в информатике.Многие школы внедряют CodeCombat и / или Ozaria в качестве основной учебной программы по информатике.
Поддерживают ли CodeCombat и Ozaria умный мгновенный вход?
Да! Посетите наш __clever__, чтобы узнать больше о том, как начать.
А как насчет Google Classroom?
Ага! Обязательно используйте режим единого входа Google (SSO), чтобы создать учетную запись учителя. Если у вас уже есть учетная запись, использующая вашу электронную почту Google, используйте модальное окно единого входа Google для входа в следующий раз.В модальном окне «Создать класс» вы увидите опцию «Связать Google Classroom». В настоящее время мы поддерживаем регистрацию только через Google Classroom.
Примечание: вы должны использовать систему единого входа Google для регистрации или входа в систему хотя бы один раз, чтобы увидеть возможность интеграции с Google Classroom.
Сколько стоит доступ ко всем доступным курсам и ресурсам?
Мы настраиваем решения для школ и округов и работаем с вами, чтобы понять ваш вариант использования, контекст и бюджет. __contact__ для уточнения деталей!
Есть ли рекомендуемый браузер и операционная система?
CodeCombat и Ozaria лучше всего работают на компьютерах с объемом оперативной памяти не менее 4 ГБ и в современном браузере, таком как Chrome, Safari, Firefox или Edge.Chromebook с 2 ГБ ОЗУ может иметь незначительные проблемы с графикой на более поздних курсах. На одного учащегося требуется минимум 200 Кбит / с, хотя рекомендуется 1+ Мбит / с.
Если у Вас есть другие вопросы, __свяжитесь с нами.
Учебник по программированию игр на Python — Real Python
Когда я начал изучать компьютерное программирование в конце прошлого тысячелетия, это было движимо моим желанием писать компьютерные игры. Я пытался понять, как писать игры на всех языках и на всех платформах, которые я изучил, включая Python.Так я обнаружил pygame
и научился использовать его для написания игр и других графических программ. В то время мне очень хотелось праймер по pygame
.
К концу этой статьи вы сможете:
- Рисуйте элементы на экране
- Воспроизведение звуковых эффектов и музыки
- Обработка пользовательского ввода
- Реализовать циклы событий
- Опишите, чем игровое программирование отличается от стандартного процедурного программирования на Python.
Этот учебник предполагает, что у вас есть базовые знания о написании программ Python, включая определяемые пользователем функции, импорт, циклы и условные выражения.Вы также должны знать, как открывать файлы на своей платформе. Также полезно базовое понимание объектно-ориентированного Python. pygame
работает с большинством версий Python, но Python 3.6 рекомендуется и используется в этой статье.
Вы можете получить весь код из этой статьи, чтобы следить за ним:
Фон и настройка
pygame
— это оболочка Python для библиотеки SDL, что означает Simple DirectMedia Layer .SDL обеспечивает кроссплатформенный доступ к основным мультимедийным аппаратным компонентам вашей системы, таким как звук, видео, мышь, клавиатура и джойстик. pygame
начал свою жизнь как замена застрявшему проекту PySDL. Кроссплатформенность SDL и pygame
означает, что вы можете писать игры и мультимедийные программы Python для любой платформы, которая их поддерживает!
Чтобы установить pygame
на вашу платформу, используйте соответствующую команду pip
:
Вы можете проверить установку, загрузив один из примеров, поставляемых с библиотекой:
$ python3 -m pygame.examples.aliens
Если появляется игровое окно, значит, pygame
установлен правильно! Если у вас возникнут проблемы, то в руководстве по началу работы описаны некоторые известные проблемы и предостережения для всех платформ.
Базовая программа PyGame
Прежде чем переходить к деталям, давайте взглянем на базовую программу pygame
. Эта программа создает окно, заполняет фон белым цветом и рисует в центре синий круг:
1 # Простая программа pygame
2
3 # Импортировать и инициализировать библиотеку pygame
4импорт pygame
5pygame.в этом()
6
7 # Настроить окно рисования
8screen = pygame.display.set_mode ([500, 500])
9
10 # Запускаем, пока пользователь не попросит выйти
11running = True
12 во время работы:
13
14 # Пользователь нажал кнопку закрытия окна?
15 для события в pygame.event.get ():
16, если event.type == pygame.QUIT:
17 running = False
18
19 # Залейте фон белым
20 screen.fill ((255, 255, 255))
21 год
22 # Нарисуйте сплошной синий круг в центре
23 pygame.draw.circle (экран, (0, 0, 255), (250, 250), 75)
24
25 # Переверните дисплей
26 pygame.display.flip ()
27
28 # Готово! Пора все бросить.
29pygame.quit ()
Когда вы запустите эту программу, вы увидите окно, которое выглядит так:
Давайте разберем этот код, раздел за разделом:
Строки 4 и 5 импортируют и инициализируют библиотеку
pygame
. Без этих строк не существуетpygame
.Строка 8 устанавливает окно отображения вашей программы. Вы предоставляете либо список, либо кортеж, определяющий ширину и высоту создаваемого окна.Эта программа использует список для создания квадратного окна с 500 пикселями с каждой стороны.
Строки 11 и 12 устанавливают игровой цикл для управления, когда программа заканчивается. Позже в этом уроке вы расскажете о игровых циклах.
Строки с 15 по 17 просматривают и обрабатывают событий в игровом цикле. Вы тоже попадете на мероприятия чуть позже. В этом случае обрабатывается только событие
pygame.QUIT
, которое происходит, когда пользователь нажимает кнопку закрытия окна.Строка 20 заполняет окно сплошным цветом.
screen.fill ()
принимает либо список, либо кортеж, определяющий значения RGB для цвета. Поскольку было предоставлено(255, 255, 255)
, окно заполняется белым цветом.Строка 23 рисует в окне круг со следующими параметрами:
-
экран
: окно для рисования -
(0, 0, 255)
: кортеж, содержащий значения цвета RGB -
(250, 250)
: кортеж, определяющий координаты центра круга -
75
: радиус нарисованного круга в пикселях
-
Строка 26 обновляет содержимое дисплея на экране.Без этого вызова в окне ничего не появляется!
Строка 29 выходит из
pygame
. Это происходит только после завершения цикла.
Это pygame
версия «Hello, World». Теперь давайте углубимся в концепции, лежащие в основе этого кода.
Концепции PyGame
Поскольку pygame
и библиотека SDL переносимы на разные платформы и устройства, они оба должны определять абстракции и работать с ними для различных аппаратных реалий.Понимание этих концепций и абстракций поможет вам проектировать и разрабатывать свои собственные игры.
Инициализация и модули
Библиотека pygame
состоит из ряда конструкций Python, которые включают несколько различных модулей . Эти модули обеспечивают абстрактный доступ к определенному оборудованию в вашей системе, а также унифицированные методы работы с этим оборудованием. Например, display
обеспечивает единообразный доступ к вашему видео дисплею, а джойстик
позволяет абстрактное управление вашим джойстиком.
После импорта библиотеки pygame
в приведенном выше примере первое, что вы сделали, это инициализировали PyGame с помощью pygame.init ()
. Эта функция вызывает отдельные функции init ()
всех включенных модулей pygame
. Поскольку эти модули являются абстракциями для определенного оборудования, этот шаг инициализации необходим, чтобы вы могли работать с одним и тем же кодом в Linux, Windows и Mac.
Дисплеи и поверхности
Помимо модулей, pygame
также включает несколько классов Python , которые инкапсулируют концепции, не зависящие от оборудования.Одним из них является поверхность Surface
, которая, по сути, определяет прямоугольную область, на которой вы можете рисовать. Поверхность
объекты используются во многих контекстах в pygame
. Позже вы увидите, как загрузить изображение в Surface
и отобразить его на экране.
В pygame
все отображается на одном созданном пользователем дисплее
, который может быть окном или полноэкранным. Отображение создается с помощью .set_mode ()
, которая возвращает Surface
, представляющую видимую часть окна.Именно эту поверхность Surface
вы передаете в функции рисования, такие как pygame.draw.circle ()
, и содержимое этой поверхности Surface
выводится на дисплей при вызове pygame.display.flip ()
.
Изображения и прямоугольники
Ваша базовая программа pygame
нарисовала фигуру прямо на Surface
дисплея, но вы также можете работать с изображениями на диске. Модуль image
позволяет загружать и сохранять изображения в различных популярных форматах.Изображения загружаются в объекты Surface
, которыми затем можно манипулировать и отображать различными способами.
Как упоминалось выше, объекты Surface
представлены прямоугольниками, как и многие другие объекты в pygame
, такие как изображения и окна. Прямоугольники настолько широко используются, что для их обработки существует специальный класс Rect
. Вы будете использовать Rect
объектов и изображений в своей игре, чтобы рисовать игроков и врагов и управлять столкновениями между ними.
Ладно, хватит теории. Давайте спроектируем и напишем игру!
Базовый игровой дизайн
Прежде чем вы начнете писать какой-либо код, всегда полезно иметь какой-нибудь дизайн. Поскольку это обучающая игра, давайте также разработаем для нее базовый игровой процесс:
- Цель игры — избегать входящих препятствий:
- Игрок начинает с левой стороны экрана.
- Препятствия случайно входят справа и движутся влево по прямой.
- Игрок может двигаться влево, вправо, вверх или вниз, чтобы избежать препятствий.
- Игрок не может покинуть экран.
- Игра заканчивается, когда игрок сталкивается с препятствием или когда пользователь закрывает окно.
Когда он описывал программные проекты, мой бывший коллега говорил: «Ты не знаешь, что делаешь, пока не знаешь, чего не делаешь». Имея это в виду, вот некоторые вещи, которые не будут рассмотрены в этом руководстве:
- Нет нескольких жизней
- Без учета
- Нет возможности атаковать игрока
- Без повышения уровней
- Нет боссов
Вы можете попробовать свои силы в добавлении этих и других функций в свою программу.
Приступим!
Импорт и инициализация PyGame
После импорта pygame
вам также потребуется его инициализировать. Это позволяет pygame
подключать свои абстракции к вашему конкретному оборудованию:
1 # Импортировать модуль pygame
2импорт pygame
3
4 # Импортируйте pygame.locals для облегчения доступа к ключевым координатам
5 # Обновлено в соответствии со стандартами flake8 и black
6 из импорта pygame.locals (
7 К_УП,
8 K_DOWN,
9 К_ЛЕФТ,
10 К_ПРАВО,
11 K_ESCAPE,
12 КЛЮЧ,
13 ВЫЙТИ,
14)
15
16 # Инициализировать pygame
17pygame.в этом()
Библиотека pygame
определяет многие вещи помимо модулей и классов. Он также определяет некоторые локальные константы для таких вещей, как нажатия клавиш, движения мыши и атрибуты отображения. Вы ссылаетесь на эти константы, используя синтаксис pygame.
. Импортируя определенные константы из pygame.locals
, вы можете вместо этого использовать синтаксис
. Это сэкономит вам несколько нажатий клавиш и улучшит читаемость в целом.
Настройка дисплея
Теперь тебе нужно на чем рисовать! Создайте экран, который будет общим холстом:
1 # Импортировать модуль pygame
2импорт pygame
3
4 # Импортировать pygame.местные жители для более удобного доступа к ключевым координатам
5 # Обновлено в соответствии со стандартами flake8 и black
6 из импорта pygame.locals (
7 К_УП,
8 K_DOWN,
9 К_ЛЕФТ,
10 К_ПРАВО,
11 K_ESCAPE,
12 КЛЮЧ,
13 ВЫЙТИ,
14)
15
16 # Инициализировать pygame
17pygame.init ()
18
19 # Определить константы для ширины и высоты экрана
20SCREEN_WIDTH = 800
21SCREEN_HEIGHT = 600
22
23 # Создаем экранный объект
24 # Размер определяется константами SCREEN_WIDTH и SCREEN_HEIGHT
25screen = pygame.display.set_mode ((SCREEN_WIDTH; SCREEN_HEIGHT))
Вы создаете экран для использования, вызывая pygame.display.set_mode ()
и передавая кортеж или список с желаемой шириной и высотой. В этом случае размер окна 800×600, как определено константами SCREEN_WIDTH
и SCREEN_HEIGHT
в строках 20 и 21. Это возвращает поверхность Surface
, которая представляет внутренние размеры окна. Это часть окна, которой вы можете управлять, в то время как ОС контролирует границы окна и строку заголовка.
Если вы запустите эту программу сейчас, вы увидите всплывающее окно, которое сразу же исчезнет при выходе из программы. Не моргайте, иначе можете пропустить! В следующем разделе вы сосредоточитесь на основном игровом цикле, чтобы гарантировать, что ваша программа завершится только при правильном вводе.
Настройка игрового цикла
Каждая игра от Pong до Fortnite использует игровой цикл для управления игровым процессом. Игровой цикл выполняет четыре очень важных задачи:
- Обрабатывает ввод данных пользователем
- Обновляет состояние всех игровых объектов
- Обновляет дисплей и аудиовыход
- Поддерживает скорость игры
Каждый цикл игрового цикла называется кадром , и чем быстрее вы сможете выполнять действия в каждом цикле, тем быстрее будет работать ваша игра.Кадры продолжают появляться до тех пор, пока не будет выполнено какое-либо условие для выхода из игры. В вашем дизайне есть два условия, которые могут завершить игровой цикл:
- Игрок сталкивается с препятствием. (Об обнаружении столкновений поговорим позже.)
- Плеер закрывает окно.
Первое, что делает игровой цикл, — это обрабатывает вводимые пользователем данные, позволяя игроку перемещаться по экрану. Следовательно, вам нужен способ захвата и обработки различных входных данных. Вы делаете это с помощью системы событий pygame
.
Обработка событий
Нажатие клавиш, движения мыши и даже движения джойстика — вот некоторые из способов, которыми пользователь может вводить данные. Все действия пользователя приводят к созданию события. События могут происходить в любое время и часто (но не всегда) происходят вне программы. Все события в pygame
помещаются в очередь событий, к которой затем можно получить доступ и управлять ими. Обработка событий называется обработкой событий , а код для этого называется обработчиком событий .
С каждым событием в pygame
связано событие типа . В вашей игре вы сосредоточите внимание на типах событий: нажатие клавиш и закрытие окна. События нажатия клавиш имеют тип события KEYDOWN
, а событие закрытия окна имеет тип QUIT
. С разными типами событий могут быть связаны и другие данные. Например, тип события KEYDOWN
также имеет переменную под названием key
, чтобы указать, какая клавиша была нажата.
Вы получаете доступ к списку всех активных событий в очереди, вызывая pygame.event.get ()
. Затем вы просматриваете этот список, проверяете каждый тип события и отвечаете соответствующим образом:
27 # Переменная для поддержания работы основного цикла
28running = True
29
30 # Основной цикл
31 во время работы:
32 # Посмотрите на каждое событие в очереди
33 для события в pygame.event.get ():
34 # Пользователь нажал клавишу?
35, если event.type == KEYDOWN:
36 # Это была клавиша Escape? Если да, остановите цикл.37, если event.key == K_ESCAPE:
38 бег = Ложь
39
40 # Пользователь нажал кнопку закрытия окна? Если да, остановите цикл.
41 elif event.type == ВЫЙТИ:
42 бега = Ложь
Давайте подробнее рассмотрим этот игровой цикл:
Строка 28 устанавливает управляющую переменную для игрового цикла. Чтобы выйти из цикла и игры, вы устанавливаете
running = False
. Цикл игры начинается со строки 29.Строка 31 запускает обработчик событий, просматривая все события, находящиеся в данный момент в очереди событий.Если событий нет, то список пуст, и обработчик ничего делать не будет.
Строки с 35 по 38 проверяют, является ли текущее событие
тип
событиемKEYDOWN
. Если это так, программа проверяет, какая клавиша была нажата, по атрибутуevent.key
. Если ключом является ключ Esc , обозначенныйK_ESCAPE
, то он выходит из игрового цикла, установивrunning = False
.Строки 41 и 42 выполняют аналогичную проверку для типа события под названием
QUIT
.Это событие происходит только тогда, когда пользователь нажимает кнопку закрытия окна. Пользователь также может использовать любое другое действие операционной системы, чтобы закрыть окно.
Когда вы добавляете эти строки в предыдущий код и запускаете его, вы увидите окно с пустым или черным экраном:
Окно не исчезнет, пока вы не нажмете клавишу Esc или иным образом не вызовете событие QUIT
, закрыв окно.
Рисование на экране
В примере программы вы рисовали на экране с помощью двух команд:
-
экран.fill ()
для заливки фона -
pygame.draw.circle ()
, чтобы нарисовать круг
Теперь вы узнаете о третьем способе рисования на экране: с помощью Surface
.
Напомним, что Surface
— это прямоугольный объект, на котором можно рисовать, как на чистом листе бумаги. Объект screen
— это Surface
, и вы можете создавать свои собственные объекты Surface
отдельно от экрана дисплея.Посмотрим, как это работает:
44 # Залить экран белым цветом
45screen.fill ((255, 255, 255))
46
47 # Создаем поверхность и передаем кортеж, содержащий ее длину и ширину
48surf = pygame.Surface ((50, 50))
49
50 # Придайте поверхности цвет, чтобы отделить ее от фона
51surf.fill ((0, 0, 0))
52rect = surf.get_rect ()
После заливки экрана белым цветом в строке 45, новая поверхность Surface
создается в строке 48. Эта поверхность Surface
имеет ширину 50 пикселей, высоту 50 пикселей и назначается для surf
.На этом этапе вы относитесь к нему так же, как к экрану
. Итак, в строке 51 вы заполняете ее черным цветом. Вы также можете получить доступ к его базовому Rect
, используя .get_rect ()
. Он сохраняется как rect
для дальнейшего использования.
Использование
.blit ()
и .flip ()
Просто создать новый Surface
недостаточно, чтобы увидеть его на экране. Для этого вам нужно перенести Surface
на другую Surface
. Термин blit
означает Block Transfer, и .blit ()
— это то, как вы копируете содержимое одной поверхности Surface
в другую. Вы можете использовать только .blit ()
с одной поверхности Surface
на другую, но поскольку экран — это просто еще одна поверхность Surface
, это не проблема. Вот как нарисовать surf
на экране:
54 # В этой строке написано "Нарисуйте прибой на экране в центре"
55screen.blit (серфинг, (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2))
56pygame.display.flip ()
Вызов .blit ()
в строке 55 принимает два аргумента:
- Поверхность
- Местоположение источника
Поверхность
Координаты (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)
говорят вашей программе разместить surf
точно в центре экрана, но это не совсем так:
Причина, по которой изображение выглядит не по центру, в том, что .blit ()
помещает в верхний левый угол surf
в указанное место. Если вы хотите, чтобы surf
располагались по центру, вам нужно будет выполнить некоторые вычисления, чтобы сместить его вверх и влево. Вы можете сделать это, вычтя ширину и высоту surf
из ширины и высоты экрана, разделив каждую на 2, чтобы найти центр, а затем передав эти числа в качестве аргументов в screen.blit ()
:
54 # Поместите центр прибоя в центр дисплея
55surf_center = (
56 (SCREEN_WIDTH-surf.get_width ()) / 2,
57 (SCREEN_HEIGHT-surf.get_height ()) / 2
58)
59
60 # Рисуем прибой в новых координатах
61screen.blit (серфинг, surf_center)
62pygame.display.flip ()
Обратите внимание на вызов pygame.display.flip ()
после вызова blit ()
. Это обновляет весь экран со всем, что было нарисовано с момента последнего переворота. Без вызова .flip ()
ничего не отображается.
Спрайты
В вашем игровом дизайне игрок начинает слева, а препятствия появляются справа.Вы можете представить все препятствия с помощью объектов Surface
, чтобы все было проще рисовать, но как узнать, где их рисовать? Как узнать, что с игроком столкнулось препятствие? Что происходит, когда препятствие улетает за пределы экрана? Что, если вы хотите нарисовать фоновые изображения, которые также движутся? Что делать, если вы хотите, чтобы ваши изображения были анимированными? Вы можете справиться со всеми этими и другими ситуациями с помощью спрайтов.
С точки зрения программирования, спрайт — это двухмерное представление чего-либо на экране.По сути, это картинка. pygame
предоставляет класс Sprite
, который предназначен для хранения одного или нескольких графических представлений любого игрового объекта, который вы хотите отобразить на экране. Чтобы использовать его, вы создаете новый класс, расширяющий Sprite
. Это позволяет использовать его встроенные методы.
Игроки
Вот как вы используете объекты Sprite
в текущей игре для определения игрока. Вставьте этот код после строки 18:
20 # Определите объект Player, расширив pygame.спрайт. спрайт
21 # Поверхность, нарисованная на экране, теперь является атрибутом 'player'
Игрок 22 класса (pygame.sprite.Sprite):
23 def __init __ (сам):
24 super (Игрок, сам) .__ init __ ()
25 self.surf = pygame.Surface ((75, 25))
26 self.surf.fill ((255, 255, 255))
27 self.rect = self.surf.get_rect ()
Сначала вы определяете Player
, расширяя pygame.sprite.Sprite
в строке 22. Затем .__ init __ ()
использует .super ()
для вызова .__init __ ()
метод Sprite
. Для получения дополнительной информации о том, почему это необходимо, вы можете прочитать Supercharge Your Classes With Python super ().
Затем вы определяете и инициализируете .surf
для хранения изображения для отображения, которое в настоящее время представляет собой белое поле. Вы также определяете и инициализируете .rect
, который вы будете использовать для рисования проигрывателя позже. Чтобы использовать этот новый класс, вам необходимо создать новый объект и также изменить код рисования. Разверните блок кода ниже, чтобы увидеть все вместе:
1 # Импортировать модуль pygame
2импорт pygame
3
4 # Импортировать pygame.местные жители для более удобного доступа к ключевым координатам
5 # Обновлено в соответствии со стандартами flake8 и black
6 из импорта pygame.locals (
7 К_УП,
8 K_DOWN,
9 К_ЛЕФТ,
10 К_ПРАВО,
11 K_ESCAPE,
12 КЛЮЧ,
13 ВЫЙТИ,
14)
15
16 # Определить константы для ширины и высоты экрана
17SCREEN_WIDTH = 800
18SCREEN_HEIGHT = 600
19
20 # Определите объект игрока, расширив pygame.sprite.Sprite
21 # Поверхность, нарисованная на экране, теперь является атрибутом 'player'
Игрок 22 класса (pygame.sprite.Sprite):
23 def __init __ (сам):
24 супер (Игрок, я).__в этом__()
25 self.surf = pygame.Surface ((75, 25))
26 self.surf.fill ((255, 255, 255))
27 self.rect = self.surf.get_rect ()
28 год
29 # Инициализировать pygame
30pygame.init ()
31 год
32 # Создаем экранный объект
33 # Размер определяется константами SCREEN_WIDTH и SCREEN_HEIGHT
34screen = pygame.display.set_mode ((SCREEN_WIDTH, SCREEN_HEIGHT))
35 год
36 # Создание экземпляра игрока. Сейчас это просто прямоугольник.
37player = Игрок ()
38
39 # Переменная для поддержания работы основного цикла
40running = True
41 год
42 # Основной цикл
43 во время работы:
44 # для цикла по очереди событий
45 для события в pygame.event.get ():
46 # Проверить событие KEYDOWN
47, если event.type == KEYDOWN:
48 # Если нажата клавиша Esc, то выходим из основного цикла
49, если event.key == K_ESCAPE:
50 бега = Ложь
51 # Проверить событие выхода. Если ВЫЙТИ, то установите для бега значение false.
52 elif event.type == ВЫЙТИ:
53 бег = Ложь
54
55 # Залить экран черным
56 screen.fill ((0, 0, 0))
57 год
58 # Рисуем игрока на экране
59 screen.blit (player.surf, (SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2))
60
61 # Обновить дисплей
62 pygame.display.flip ()
Запустите этот код. Примерно в центре экрана вы увидите белый прямоугольник:
.
Как вы думаете, что произойдет, если вы измените строку 59 на screen.blit (player.surf, player.rect)
? Попробуйте и увидите:
55 # Залить экран черным цветом
56screen.fill ((0, 0, 0))
57 год
58 # Рисуем игрока на экране
59screen.blit (player.surf, player.rect)
60
61 # Обновить дисплей
62pygame.display.flip ()
Когда вы передаете Rect
на .blit ()
, он использует координаты верхнего левого угла для рисования поверхности. Вы будете использовать это позже, чтобы ваш игрок двигался!
Пользовательский ввод
Итак, вы узнали, как настроить pygame
и рисовать объекты на экране. Теперь начинается самое интересное! Вы сделаете проигрывателем управляемым с клавиатуры.
Ранее вы видели, что pygame.event.get ()
возвращает список событий в очереди событий, которые вы просматриваете на предмет типов событий KEYDOWN
.Что ж, это не единственный способ читать нажатия клавиш. pygame
также предоставляет pygame.event.get_pressed ()
, который возвращает словарь, содержащий все текущие события KEYDOWN
в очереди.
Поместите это в игровой цикл сразу после цикла обработки событий. Это возвращает словарь, содержащий клавиши, нажатые в начале каждого кадра:
54 # Нажать набор клавиш и проверить ввод пользователя
55pressed_keys = pygame.key.get_pressed ()
Затем вы пишете метод в Player
для приема этого словаря.Это определит поведение спрайта на основе нажатых клавиш. Вот как это может выглядеть:
29 # Перемещение спрайта на основе нажатия клавиш пользователя
Обновление 30def (собственное, нажатые_keys):
31 если нажата_keys [K_UP]:
32 self.rect.move_ip (0, -5)
33 если нажата_keys [K_DOWN]:
34 self.rect.move_ip (0, 5)
35, если нажата_keys [K_LEFT]:
36 self.rect.move_ip (-5, 0)
37 если нажата_keys [K_RIGHT]:
38 self.rect.move_ip (5, 0)
K_UP
, K_DOWN
, K_LEFT
и K_RIGHT
соответствуют клавишам со стрелками на клавиатуре.Если словарная запись для этого ключа — True
, то этот ключ нажат, и вы перемещаете игрока .rect
в правильном направлении. Здесь вы используете .move_ip ()
, что означает перемещение на место , чтобы переместить текущий Rect
.
Затем вы можете вызывать .update ()
каждый кадр, чтобы перемещать спрайт игрока в ответ на нажатия клавиш. Добавьте этот вызов сразу после вызова в .get_pressed ()
:
52 # Главный цикл
53 во время работы:
54 # для цикла по очереди событий
55 для события в pygame.event.get ():
56 # Проверить событие KEYDOWN
57, если event.type == KEYDOWN:
58 # Если нажата клавиша Esc, то выходим из основного цикла
59, если event.key == K_ESCAPE:
60 бег = Ложь
61 # Проверить наличие события QUIT. Если ВЫЙТИ, то установите для бега значение false.
62 elif event.type == ВЫЙТИ:
63 бега = Ложь
64
65 # Получить все нажатые в данный момент клавиши
66 Press_keys = pygame.key.get_pressed ()
67
68 # Обновить спрайт игрока на основе нажатий клавиш пользователя
69 игроков.обновление (нажатые_keys)
70
71 # Залить экран черным
72 screen.fill ((0, 0, 0))
Теперь вы можете перемещать прямоугольник вашего плеера по экрану с помощью клавиш со стрелками:
Вы можете заметить две небольшие проблемы:
- Прямоугольник игрока может перемещаться очень быстро, если удерживать клавишу. Вы поработаете над этим позже.
- Прямоугольник игрока может перемещаться за пределы экрана. Давайте сейчас решим эту проблему.
Чтобы игрок оставался на экране, вам нужно добавить некоторую логику для определения того, собирается ли прямоугольник
уйти с экрана.Для этого вы проверяете, переместились ли координаты rect
за границу экрана. Если да, то вы даете программе указание переместить его обратно на край:
25 # Перемещение спрайта на основе нажатия клавиш пользователя
26def update (self, press_keys):
27, если нажата_keys [K_UP]:
28 self.rect.move_ip (0, -5)
29 если нажата_keys [K_DOWN]:
30 self.rect.move_ip (0, 5)
31 если нажата_keys [K_LEFT]:
32 self.rect.move_ip (-5, 0)
33 если нажата_keys [K_RIGHT]:
34 сам.rect.move_ip (5, 0)
35 год
36 # Держите игрока на экране
37, если самовращение слева <0:
38 self.rect.left = 0
39, если self.rect.right> SCREEN_WIDTH:
40 self.rect.right = SCREEN_WIDTH
41, если self.rect.top <= 0:
42 self.rect.top = 0
43, если self.rect.bottom> = SCREEN_HEIGHT:
44 self.rect.bottom = SCREEN_HEIGHT
Здесь вместо использования .move ()
вы просто меняете соответствующие координаты .top
, .bottom
, .слева
или . справа
напрямую. Проверьте это, и вы обнаружите, что прямоугольник плеера больше не может отодвигаться от экрана.
А теперь добавим врагов!
Враги
Что за игра без врагов? Вы воспользуетесь уже изученными приемами, чтобы создать базовый класс врагов, а затем создадите множество из них, чтобы ваш игрок избегал их. Сначала импортируйте случайную библиотеку
:
4 # Импортировать случайные числа для случайных чисел
5импорт случайный
Затем создайте новый класс спрайтов с именем Enemy
, следуя тому же шаблону, который вы использовали для Player
:
55 # Определите объект врага, расширив pygame.спрайт. спрайт
56 # Поверхность, которую вы рисуете на экране, теперь является атрибутом 'врага'.
Враг 57 класса (pygame.sprite.Sprite):
58 def __init __ (сам):
59 super (Враг, я) .__ init __ ()
60 self.surf = pygame.Surface ((20, 10))
61 self.surf.fill ((255, 255, 255))
62 self.rect = self.surf.get_rect (
63 центр = (
64 random.randint (SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
65 random.randint (0, SCREEN_HEIGHT),
66)
67)
68 сам.скорость = random.randint (5, 20)
69
70 # Перемещение спрайта в зависимости от скорости
71 # Удаляем спрайт, когда он проходит левый край экрана
Обновление 72 def (самостоятельно):
73 self.rect.move_ip (-self.speed, 0)
74, если self.rect.right <0:
75 самоубийств ()
Есть четыре заметных различия между Enemy
и Player
:
В строках с 62 по 67 вы обновляете
прямоугольник
, чтобы он стал случайным местом вдоль правого края экрана.Центр прямоугольника находится за пределами экрана. Он расположен на расстоянии от 20 до 100 пикселей от правого края и где-то между верхним и нижним краями.В строке 68 вы определяете
.speed
как случайное число от 5 до 20. Это определяет, насколько быстро этот враг движется к игроку.В строках с 73 по 76 вы определяете
.update ()
. Это не требует аргументов, поскольку враги перемещаются автоматически.Вместо этого.update ()
перемещает врага в левую часть экрана со скоростью.speed
, определенной при его создании.В строке 74 вы проверяете, ушел ли противник за пределы экрана. Чтобы убедиться, что
Enemy
полностью скрыт с экрана и не исчезнет просто так, пока он все еще виден, вы убедитесь, что правая сторона.rect
прошла за левую часть экрана. Как только противник окажется за кадром, вы звоните по номеру.kill ()
, чтобы предотвратить его дальнейшую обработку.
Итак, что делает .kill ()
? Чтобы понять это, вы должны знать о Sprite Groups .
Группы спрайтов
Еще один очень полезный класс, который предоставляет pygame
, - это Sprite Group
. Это объект, который содержит группу из Sprite
объектов. Так зачем это использовать? Разве вы не можете вместо этого просто отслеживать свои объекты Sprite
в списке? Что ж, вы можете, но преимущество использования Group
заключается в методах, которые он предоставляет.Эти методы помогают определить, столкнулся ли какой-либо Enemy
с Player
, что значительно упрощает обновление.
Давайте посмотрим, как создавать группы спрайтов. Вы создадите два разных объекта Group
:
- Первая группа
Sprite
в игре. - Вторая группа
Group
будет содержать толькоEnemy
объектов.
Вот как это выглядит в коде:
82 # Создайте 'player'
83player = Игрок ()
84
85 # Создавайте группы для хранения вражеских спрайтов и всех спрайтов
86 # - враги используются для обнаружения столкновений и обновления позиции
87 # - all_sprites используется для рендеринга
88enemies = pygame.sprite.Group ()
89all_sprites = pygame.sprite.Group ()
90all_sprites.add (игрок)
91
92 # Переменная для поддержания работы основного цикла
93running = True
Когда вы вызываете .kill ()
, Sprite
удаляется из каждой Group
, к которой он принадлежит. Это также удаляет ссылки на Sprite
, что позволяет сборщику мусора Python при необходимости освобождать память.
Теперь, когда у вас есть группа all_sprites
, вы можете изменить способ рисования объектов.Вместо того, чтобы вызывать .blit ()
только для Player
, вы можете перебирать все в all_sprites
:
117 # Залить экран черным
118screen.fill ((0, 0, 0))
119
120 # Рисуем все спрайты
121 для сущности в all_sprites:
122 screen.blit (entity.surf, entity.rect)
123
124 # Перевернуть все на дисплей
125pygame.display.flip ()
Теперь все, что помещено в all_sprites
, будет отрисовываться с каждым кадром, будь то враг или игрок.
Есть только одна проблема ... У тебя нет врагов! Вы можете создать кучу врагов в начале игры, но игра быстро наскучит, когда через несколько секунд все они покинут экран. Вместо этого давайте рассмотрим, как поддерживать постоянный приток врагов по ходу игры.
Пользовательские события
Дизайн призывает врагов появляться через равные промежутки времени. Это означает, что через установленные промежутки времени вам нужно сделать две вещи:
- Создать нового врага
- Добавьте его к
all_sprites
ипротивникам
.
У вас уже есть код, обрабатывающий случайные события. Цикл событий предназначен для поиска случайных событий, происходящих в каждом кадре, и обработки их соответствующим образом. К счастью, pygame
не ограничивает вас использованием только тех типов событий, которые он определил. Вы можете определить свои собственные события для обработки по своему усмотрению.
Давайте посмотрим, как создать настраиваемое событие, которое генерируется каждые несколько секунд. Вы можете создать собственное событие, присвоив ему имя:
.
78 # Создать экранный объект
79 # Размер определяется константами SCREEN_WIDTH и SCREEN_HEIGHT
80screen = pygame.display.set_mode ((SCREEN_WIDTH; SCREEN_HEIGHT))
81 год
82 # Создайте собственное событие для добавления нового врага
83ADDENEMY = pygame.USEREVENT + 1
84pygame.time.set_timer (ДОБАВЛЕНИЕ, 250)
85
86 # Создание экземпляра игрока. Сейчас это просто прямоугольник.
87player = Игрок ()
pygame
определяет события внутри как целые числа, поэтому вам нужно определить новое событие с уникальным целым числом. Последнее событие pygame
резервирует называется USEREVENT
, поэтому определение ADDENEMY = pygame.USEREVENT + 1
в строке 83 гарантирует его уникальность.
Затем вам нужно вставить это новое событие в очередь событий через равные промежутки времени на протяжении всей игры. Вот тут и появляется модуль time
. Строка 84 запускает новое событие ADDENEMY
каждые 250 миллисекунд или четыре раза в секунду. Вы вызываете .set_timer ()
вне игрового цикла, поскольку вам нужен только один таймер, но он будет срабатывать на протяжении всей игры.
Добавьте код для обработки нового события:
100 # Главный цикл
101 во время работы:
102 # Посмотрите на каждое событие в очереди
103 для события в pygame.event.get ():
104 # Пользователь нажал клавишу?
105, если event.type == KEYDOWN:
106 # Это была клавиша Escape? Если да, остановите цикл.
107, если event.key == K_ESCAPE:
108 бег = Ложь
109
110 # Пользователь нажал кнопку закрытия окна? Если да, остановите цикл.
111 elif event.type == ВЫЙТИ:
112 работает = Ложь
113
114 # Добавить нового врага?
115 elif event.type == ДОБАВЛЕНИЕ:
116 # Создайте нового врага и добавьте его в группы спрайтов
117 new_enemy = Враг ()
118 врагов.добавить (new_enemy)
119 all_sprites.add (новый_враг)
120
121 # Нажать набор клавиш и проверить ввод пользователя
122 нажатых_keys = pygame.key.get_pressed ()
123 player.update (нажатые_keys)
124
125 # Обновить позицию врага
126 врагов.update ()
Каждый раз, когда обработчик событий видит новое событие ADDENEMY
в строке 115, он создает Enemy
и добавляет его к противникам
и all_sprites
. Поскольку Enemy
находится в all_sprites
, он будет отрисовываться каждый кадр.Вам также необходимо вызвать врагов.update ()
в строке 126, который обновит все в врагов
, чтобы убедиться, что они перемещаются правильно:
Однако это не единственная причина, по которой существует группа всего из врагов
.
Обнаружение столкновений
Ваш игровой дизайн требует, чтобы игра завершалась всякий раз, когда враг сталкивается с игроком. Проверка на столкновения - это базовая техника программирования игр, которая обычно требует некоторой нетривиальной математики, чтобы определить, будут ли два спрайта перекрывать друг друга.
Вот здесь и пригодится фреймворк вроде pygame
! Написание кода обнаружения столкновений утомительно, но в pygame
есть МНОГО методов обнаружения столкновений, доступных для использования.
В этом руководстве вы будете использовать метод под названием .spritecollideany ()
, который читается как «спрайт сталкивается с любым». Этот метод принимает в качестве параметров Sprite
и Group
. Он просматривает каждый объект в группе
и проверяет, соответствует ли его .rect
пересекается с .rect
из Sprite
. Если да, то он возвращает True
. В противном случае возвращается False
. Это идеально подходит для этой игры, так как вам нужно проверить, не сталкивается ли одиночный игрок
с одним из Группы
из врагов
.
Вот как это выглядит в коде:
130 # Рисуем все спрайты
131 для сущности в all_sprites:
132 screen.blit (entity.surf, entity.rect)
133
134 # Проверить, не столкнулись ли враги с игроком
135if pygame.sprite.spritecollideany (игрок, враги):
136 # Если да, то удалите плеер и остановите цикл
137 player.kill ()
138 running = False
Строка 135 проверяет, столкнулся ли игрок
с каким-либо из объектов в противниках
. Если это так, то вызывается player.kill ()
, чтобы удалить его из каждой группы, к которой он принадлежит. Поскольку визуализируются только объекты в all_sprites
, проигрыватель
больше не будет отображаться. После того, как игрок был убит, вам также необходимо выйти из игры, поэтому вы устанавливаете running = False
, чтобы выйти из игрового цикла в строке 138.
На этом этапе у вас есть основные элементы игры:
А теперь давайте немного украсим его, сделаем более удобным для игры и добавим некоторые расширенные возможности, которые помогут ему выделиться.
Изображения Sprite
Хорошо, у вас есть игра, но давайте будем честными ... Она некрасивая. Игрок и враги - просто белые блоки на черном фоне. Это было по последнему слову техники, когда Pong был новичком, но теперь он уже не годится. Давайте заменим все эти скучные белые прямоугольники более крутыми изображениями, которые сделают игру похожей на настоящую.
Ранее вы узнали, что изображения на диске могут быть загружены в поверхность Surface
с некоторой помощью модуля image
. Для этого урока мы сделали небольшой самолет для игрока и несколько ракет для врагов. Вы можете использовать это искусство, нарисовать свое собственное или загрузить несколько бесплатных игровых материалов для использования. Вы можете щелкнуть ссылку ниже, чтобы загрузить изображения, использованные в этом руководстве:
Изменение конструкторов объектов
Прежде чем использовать изображения для представления спрайтов игрока и врага, необходимо внести некоторые изменения в их конструкторы.Приведенный ниже код заменяет использованный ранее код:
7 # Импортируйте pygame.locals для облегчения доступа к ключевым координатам
8 # Обновлено в соответствии со стандартами flake8 и black
9 # из импорта pygame.locals *
10 из импорта pygame.locals (
11 RLEACCEL,
12 К_УП,
13 K_DOWN,
14 К_ЛЕФТ,
15 К_ПРАВО,
16 K_ESCAPE,
17 КЛЮЧ,
18 ВЫЙТИ,
19)
20
21 # Определить константы для ширины и высоты экрана
22SCREEN_WIDTH = 800
23SCREEN_HEIGHT = 600
24
25
26 # Определите объект Player, расширив pygame.спрайт. спрайт
27 # Вместо поверхности используйте изображение, чтобы спрайт выглядел лучше
Игрок 28 класса (pygame.sprite.Sprite):
29 def __init __ (сам):
30 super (Игрок, сам) .__ init __ ()
31 self.surf = pygame.image.load ("jet.png"). Convert ()
32 self.surf.set_colorkey ((255, 255, 255), RLEACCEL)
33 self.rect = self.surf.get_rect ()
Давайте немного распакуем строку 31. pygame.image.load ()
загружает изображение с диска. Вы передаете ему путь к файлу. Он возвращает Surface,
и .convert ()
оптимизирует Surface
, ускоряя будущие вызовы .blit ()
.
Строка 32 использует .set_colorkey ()
, чтобы указать, что цвет pygame
будет отображаться как прозрачный. В этом случае вы выбираете белый цвет, потому что это цвет фона изображения струи. Константа RLEACCEL - это необязательный параметр, который помогает pygame
быстрее отрисовывать на неускоренных дисплеях. Это добавлено в оператор импорта pygame.locals
в строке 11.
Больше ничего менять не нужно. Изображение по-прежнему Surface
, только теперь на нем нарисовано изображение. Вы по-прежнему используете его таким же образом.
Вот как выглядят похожие изменения в Enemy
:
59 # Определите объект врага, расширив pygame.sprite.Sprite
60 # Вместо поверхности используйте изображение, чтобы спрайт выглядел лучше.
Враг 61 класса (pygame.sprite.Sprite):
62 def __init __ (сам):
63 super (Враг, я) .__ init __ ()
64 сам.surf = pygame.image.load ("missile.png"). convert ()
65 self.surf.set_colorkey ((255, 255, 255), RLEACCEL)
66 # Начальная позиция генерируется случайным образом, как и скорость
67 self.rect = self.surf.get_rect (
68 центр = (
69 random.randint (SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
70 random.randint (0, ВЫСОТА_ЭКРАНА),
71)
72)
73 self.speed = random.randint (5, 20)
Запуск программы сейчас должен показать, что это та же игра, что и у вас раньше, за исключением того, что теперь вы добавили красивую графику скина с изображениями.Но зачем останавливаться на том, чтобы просто сделать красивую внешность игрока и врага? Давайте добавим несколько летящих облаков, чтобы создать впечатление летящего по небу самолета.
Добавление фоновых изображений
Для фоновых облаков используются те же принципы, что и для Player
и Enemy
:
- Создайте класс
Cloud
. - Добавьте к нему изображение облака.
- Создайте метод
.update ()
, который перемещает облако - Создайте настраиваемое событие и обработчик для создания новых объектов
cloud
с заданным интервалом времени. - Добавьте вновь созданные объекты
cloud
в новую группуGroup
под названиемclouds
. - Обновите и нарисуйте облака
Вот как выглядит Cloud
:
83 # Определите объект облака, расширив pygame.sprite.Sprite
84 # Используйте изображение, чтобы спрайт выглядел лучше
85class Cloud (pygame.спрайт. спрайт):
86 def __init __ (сам):
87 super (Облако, я) .__ init __ ()
88 self.surf = pygame.image.load ("cloud.png"). Convert ()
89 self.surf.set_colorkey ((0, 0, 0), RLEACCEL)
90 # Начальная позиция генерируется случайным образом
91 self.rect = self.surf.get_rect (
92 центр = (
93 random.randint (SCREEN_WIDTH + 20, SCREEN_WIDTH + 100),
94 random.randint (0, ВЫСОТА_ЭКРАНА),
95)
96)
97
98 # Перемещение облака на постоянной скорости
99 # Удалите облако, когда оно проходит левый край экрана
Обновление 100 def (самостоятельно):
101 сам.rect.move_ip (-5, 0)
102, если self.rect.right <0:
103 самоубийства ()
Все это должно показаться очень знакомым. Это почти то же самое, что Enemy
.
Чтобы облака появлялись через определенные промежутки времени, вы будете использовать код создания события, аналогичный тому, который вы использовали для создания новых врагов. Поместите его прямо под событием создания врага:
116 # Создание пользовательских событий для добавления нового врага и облака
117ADDENEMY = pygame.USEREVENT + 1
118pygame.time.set_timer (ДОБАВЛЕНИЕ, 250)
119ADDCLOUD = pygame.USEREVENT + 2
120pygame.time.set_timer (ADDCLOUD, 1000)
Это означает, что нужно подождать 1000 миллисекунд или одну секунду перед созданием следующего облака
.
Затем создайте новую группу
для хранения каждого вновь созданного облака
:
125 # Создавайте группы для хранения вражеских спрайтов, облачных спрайтов и всех спрайтов
126 # - враги используются для обнаружения столкновений и обновления позиции
127 # - облака используются для обновления позиции
128 # - all_sprites используется для рендеринга
129enemies = pygame.sprite.Group ()
130clouds = pygame.sprite.Group ()
131all_sprites = pygame.sprite.Group ()
132all_sprites.add (игрок)
Затем добавьте обработчик для нового события ADDCLOUD
в обработчике событий:
137 # Главный цикл
138 во время работы:
139 # Посмотрите на каждое событие в очереди
140 для события в pygame.event.get ():
141 # Пользователь нажал клавишу?
142, если event.type == KEYDOWN:
143 # Это была клавиша Escape? Если да, то остановите цикл.
144, если событие.ключ == K_ESCAPE:
145 работает = Ложь
146
147 # Пользователь нажимал кнопку закрытия окна? Если да, остановите цикл.
148 elif event.type == ВЫЙТИ:
149 running = False
150
151 # Добавить нового врага?
152 elif event.type == ДОБАВЛЕНИЕ:
153 # Создайте нового врага и добавьте его в группы спрайтов
154 new_enemy = Враг ()
155 врагов.add (new_enemy)
156 all_sprites.add (новый_враг)
157
158 # Добавить новое облако?
159 elif event.type == ADDCLOUD:
160 # Создайте новое облако и добавьте его в группы спрайтов
161 new_cloud = Облако ()
162 clouds.add (new_cloud)
163 all_sprites.add (новое_облако)
Наконец, убедитесь, что облака
обновляются каждый кадр:
167 # Обновить положение врагов и облаков
168enemies.update ()
169clouds.update ()
170
171 # Залить экран небесно-голубым
172screen.fill ((135, 206, 250))
Строка 172 обновляет исходный экран .fill ()
, чтобы заполнить экран приятным небесно-голубым цветом. Вы можете изменить этот цвет на другой. Может быть, вам нужен инопланетный мир с фиолетовым небом, токсичные пустоши в неоново-зеленом цвете или поверхность Марса в красном!
Обратите внимание, что каждое новое облако
и Enemy
добавляются к all_sprites
, а также к облакам
и противникам
. Это сделано потому, что каждая группа используется для отдельной цели:
- Отрисовка выполняется с использованием
all_sprites
. - Обновления позиции выполняются с использованием
облаков
иврагов
. - Обнаружение столкновений выполняется с использованием
врагов
.
Вы создаете несколько групп, чтобы изменить способ движения или поведения спрайтов, не влияя на движение или поведение других спрайтов.
Скорость игры
При тестировании игры вы могли заметить, что враги двигаются немного быстрее. Если нет, тогда ничего страшного, так как разные машины на этом этапе будут видеть разные результаты.
Причина этого в том, что игровой цикл обрабатывает кадры настолько быстро, насколько это позволяют процессор и среда. Поскольку все спрайты перемещаются один раз за кадр, они могут перемещаться сотни раз в секунду. Количество кадров, обрабатываемых каждую секунду, называется частотой кадров , и правильное определение - это разница между играбельной игрой и той, которую можно забыть.
Обычно вам нужна как можно более высокая частота кадров, но для этой игры вам нужно немного замедлить ее, чтобы в игру можно было играть.К счастью, модуль time
содержит часы Clock
, которые предназначены именно для этой цели.
Использование Clock
для установки воспроизводимой частоты кадров требует всего две строки кода. Первый создает новые часы Clock
перед началом игрового цикла:
106 # Настройте часы для приличной частоты кадров
107clock = pygame.time.Clock ()
Второй вызывает .tick ()
, чтобы сообщить pygame
, что программа достигла конца кадра:
188 # Перевернуть все на дисплей
189pygame.display.flip ()
190
191 # Убедитесь, что программа поддерживает частоту 30 кадров в секунду
192clock.tick (30)
Аргумент, переданный в .tick ()
, устанавливает желаемую частоту кадров. Для этого .tick ()
вычисляет количество миллисекунд, которое должен занять каждый кадр, на основе желаемой частоты кадров. Затем он сравнивает это число с количеством миллисекунд, прошедших с момента последнего вызова .tick ()
. Если прошло мало времени, то .tick ()
задерживает обработку, чтобы гарантировать, что она никогда не превысит заданную частоту кадров.
Переход на меньшую частоту кадров приведет к увеличению времени в каждом кадре для вычислений, в то время как более высокая частота кадров обеспечивает более плавный (и, возможно, более быстрый) игровой процесс:
Поэкспериментируйте с этим номером, чтобы узнать, что вам больше нравится!
Звуковые эффекты
Пока что вы сосредоточились на игровом процессе и визуальных аспектах игры. А теперь давайте посмотрим, как придать вашей игре слуховой привкус. pygame
предоставляет микшер
для обработки всех действий, связанных со звуком. Вы будете использовать классы и методы этого модуля для создания фоновой музыки и звуковых эффектов для различных действий.
Название микшер
отсылает к тому факту, что модуль смешивает различные звуки в единое целое. Используя подмодуль music
, вы можете передавать отдельные звуковые файлы в различных форматах, таких как MP3, Ogg и Mod. Вы также можете использовать Sound
для воспроизведения одного звукового эффекта в форматах Ogg или несжатом WAV.Все воспроизведение происходит в фоновом режиме, поэтому, когда вы воспроизводите Sound
, метод немедленно возвращается по мере воспроизведения звука.
Примечание: В документации pygame
указано, что поддержка MP3 ограничена, а неподдерживаемые форматы могут вызвать сбои системы. Звуки, упомянутые в этой статье, были протестированы, и мы рекомендуем тщательно протестировать любые звуки перед выпуском игры.
Как и большинство вещей pygame
, использование микшера
начинается с этапа инициализации.К счастью, это уже обрабатывается pygame.init ()
. Вам нужно только вызвать pygame.mixer.init ()
, если вы хотите изменить значения по умолчанию:
106 # Настройка звуков. Значения по умолчанию хороши.
107pygame.mixer.init ()
108
109 # Инициализировать pygame
110pygame.init ()
111
112 # Настройте часы на приличную частоту кадров
113clock = pygame.time.Clock ()
pygame.mixer.init ()
принимает ряд аргументов, но в большинстве случаев значения по умолчанию работают нормально. Обратите внимание: если вы хотите изменить значения по умолчанию, вам нужно вызвать pygame.Mixer.init ()
перед вызовом pygame.init ()
. В противном случае значения по умолчанию будут действовать независимо от внесенных вами изменений.
После инициализации системы вы можете настроить звуки и фоновую музыку:
135 # Загрузка и воспроизведение фоновой музыки
136 # Источник звука: http://ccmixter.org/files/Apoxode/59262
137 # Лицензия: https://creativecommons.org/licenses/by/3.0/
138pygame.mixer.music.load ("Apoxode _-_ Electric_1.mp3")
139pygame.mixer.music.play (петли = -1)
140
141 # Загрузить все звуковые файлы
142 # Источники звука: Джон Финчер
143move_up_sound = pygame.Mixer.Sound ("Rising_putter.ogg")
144move_down_sound = pygame.mixer.Sound ("Falling_putter.ogg")
145collision_sound = pygame.mixer.Sound ("Collision.ogg")
Строки 138 и 139 загружают фоновый звуковой клип и начинают его воспроизведение. Вы можете указать звуковому клипу зацикливаться и никогда не заканчиваться, установив именованный параметр loops = -1
.
Строки с 143 по 145 загружают три звука, которые вы будете использовать для различных звуковых эффектов. Первые два - это звуки подъема и падения, которые воспроизводятся, когда игрок движется вверх или вниз.Последний - звук, используемый при столкновении. Вы также можете добавить другие звуки, такие как звук, когда создается Enemy
, или последний звук, когда игра заканчивается.
Итак, как вы используете звуковые эффекты? Вы хотите воспроизводить каждый звук при наступлении определенного события. Например, когда корабль движется вверх, вы хотите сыграть move_up_sound
. Следовательно, вы добавляете вызов .play ()
всякий раз, когда обрабатываете это событие. В проекте это означает добавление следующих вызовов к .update ()
для Player
:
26 # Определите объект Player, расширив pygame.sprite.Sprite
27 # Вместо поверхности используйте изображение, чтобы спрайт выглядел лучше
Игрок 28 класса (pygame.sprite.Sprite):
29 def __init __ (сам):
30 super (Игрок, сам) .__ init __ ()
31 self.surf = pygame.image.load ("jet.png"). Convert ()
32 self.surf.set_colorkey ((255, 255, 255), RLEACCEL)
33 self.rect = self.surf.get_rect ()
34
35 # Перемещение спрайта на основе нажатия клавиш
36 def update (self, press_keys):
37 если нажата_keys [K_UP]:
38 сам.rect.move_ip (0, -5)
39 move_up_sound.play ()
40, если нажата_keys [K_DOWN]:
41 self.rect.move_ip (0, 5)
42 move_down_sound.play ()
Для столкновения между игроком и противником вы проигрываете звук при обнаружении столкновения:
201 # Проверить, не столкнулись ли враги с игроком
202if pygame.sprite.spritecollideany (игрок, враги):
203 # Если да, то удалите плеер
204 player.kill ()
205
206 # Остановить любые движущиеся звуки и воспроизвести звук столкновения
207 move_up_sound.останавливаться()
208 move_down_sound.stop ()
209 collision_sound.play ()
210
211 # Остановить цикл
212 running = False
Здесь вы сначала останавливаете любые другие звуковые эффекты, потому что при столкновении игрок больше не двигается. Затем вы воспроизводите звук столкновения и продолжаете выполнение оттуда.
Наконец, когда игра закончится, все звуки должны прекратиться. Это верно независимо от того, заканчивается ли игра из-за столкновения или пользователь выходит вручную. Для этого в конце программы после цикла добавьте следующие строки:
220 # Готово! Остановите и выйдите из миксера.221pygame.mixer.music.stop ()
222pygame.mixer.quit ()
Технически, эти последние несколько строк не требуются, так как программа завершается сразу после этого. Однако, если позже вы решите добавить в игру экран вступления или экрана выхода, то после завершения игры может быть запущено больше кода.
Вот и все! Проверьте это еще раз, и вы должны увидеть что-то вроде этого:
Примечание об источниках
Возможно, вы заметили комментарий в строках 136–137 при загрузке фоновой музыки, в котором указан источник музыки и ссылка на лицензию Creative Commons.Это было сделано потому, что этого требовал создатель этого звука. В лицензионных требованиях указано, что для использования звука необходимо предоставить как надлежащую атрибуцию, так и ссылку на лицензию.
Вот несколько источников музыки, звука и искусства, в которых вы можете найти полезный контент:
При создании игр и использовании загруженного содержимого, такого как изображения, музыка или код из других источников, убедитесь, что вы соблюдаете условия лицензирования этих источников.
Заключение
Из этого руководства вы узнали, чем программирование игр с помощью pygame
отличается от стандартного процедурного программирования.Вы также научились:
- Реализовать циклы событий
- Рисовать предметы на экране
- Воспроизведение звуковых эффектов и музыки
- Обработка пользовательского ввода
Для этого вы использовали подмножество модулей pygame
, включая display
, микшер
и music
, time
, image
, event
и key
. Вы также использовали несколько классов pygame
, включая Rect
, Surface
, Sound
и Sprite
.Но это только малая часть того, что может сделать pygame
! Ознакомьтесь с официальной документацией по pygame
для получения полного списка доступных модулей и классов.
Вы можете найти весь код, графические и звуковые файлы для этой статьи, щелкнув ссылку ниже:
Не стесняйтесь оставлять комментарии и ниже. Удачного питонинга!
🐱🏍 stuntcat - это наша мини-игра с открытым исходным кодом, над которой мы работали, чтобы продвигать разработку Pygame 2 вперед.Мы хотели сделать настоящую мини-игру и постараться выпустить ее в продажу на как можно большем количестве платформ. Чтобы другие люди могли просматривать исходный код и распространять свою игру на большем количестве платформ.
У нас было всего 4 дня ... но за это время было задействовано более 14 человек. Мы многому научились во время этого. Инструкции по компиляции для pygame 2 были улучшены, чтобы больше людей могло создавать версии для разработки. Мы автоматизировали создание установщика для Windows, Mac и pypi на github (чтобы другие проекты могли копировать этот базовый код и делать это тоже).Запущено сохранение Gif-анимации (потому что, когда вы выпускаете игру, вы хотите, чтобы гифка была?). Были выявлены недостающие функции и области, в которых можно было бы улучшить документацию (анимированные спрайты и какие-нибудь сцены?). Были внесены исправления в pymunk (отличный 2D-движок для физики), поэтому распространение физических игр среди конечных пользователей стало проще. Также есть пример использования загрузчика тайловых карт (PyTMX) с физическим движком. Более чем через месяц после завершения игрового джема мы работаем над проблемами, обнаруженными при создании 🐱🏍 stuntcat.
Мы хотим упростить распространение приложений pygame для людей. Вы сделали свою игру, а теперь хотите поделиться ею с друзьями или даже продать, верно? В первую очередь мы выпустили релиз на itch.io, платформе для продажи игр и приложений. Там мы загрузили Mac, Windows и исходный код, чтобы люди могли загрузить его с опцией «плати сколько чувствуешь».
Следующим шагом будет выпуск игры в Steam (еще одна популярная игровая платформа). Для следующего шага нам нужно собрать долларов на плату за приложение Steam.Мы также должны сделать игру лучше! Это уже довольно забавная мини-игра, но требует больше мини-игр и большей доработки. Нам также нужно сделать предварительные двоичные файлы pygame 2, чтобы мы могли публиковать их в Steam.
Спасибо создателям stuntcat: bitcraft, blubberquark, Bottersnake, claudeb, illume, Kuba | ThePolish, TJWhale, hfoxp, xeno, M, CaptHurls, dlon, dirk0, viblo и kleines filmröllchen.
день 0: 0 из 100 долларов собрано на плату за приложение Steam.
день 1: 5 долларов из 100 долларов
день 2: 57 долларов из 100 долларов
день 3: 100 долларов из 113 долларов.20
день 14: 107 долларов из 113,20 долларов
день 20: 127 долларов из 113,20 долларов
Если вы когда-либо хотели поддержать разработку pygame финансово и можете себе это позволить, вы можете купить stuntcat на itch.io для 2 доллара или все, что вы чувствуете.
Обновление: мы собрали достаточно, чтобы выпустить Steam. Спасибо всем, кто скинулся!
игр и задач по программированию для начинающих и продвинутых
Спасибо за ваш запрос.Мы свяжемся с вами в ближайшее время.
Здесь, на CheckiO, мы создаем игры для программистов. Мы создали py.checkio.org и js.checkio.org, где вы можете улучшить свои навыки программирования на TypeScript и Python. Мы также создали Empire of Code - космическую игру, в которой сочетаются стратегия, тактика и код.
В дополнение к 50 тысячам активных игроков Python и TypeScript в месяц, которые постоянно совершенствуют свои навыки, участвуя в миссиях CheckiO и анализируя решения других участников, CheckiO используется более чем в 100 различных школах и университетах.
Мы можем помочь компаниям разными способами.
CheckiO - отличный инструмент для продвижения ваших услуг. JetBrains и Hired доказали, что мы эффективно предлагаем взаимодействие, а их услуги пользуются большой популярностью среди наших пользователей.
CheckiO также очень гибок и открыт для новых идей. SendGrid, например, с нашей помощью публикует свой Python API. Остров SendGrid был создан как уникальный способ протестировать их программное обеспечение с нашими кодировщиками, заставляя их решать миссии в игре.В результате нашего сотрудничества Sendgrid получает тысячи экземпляров тестов и важные отзывы о прямом использовании продукта.
Вы ищете других программистов TypeScript или Python, чтобы присоединиться к вашей компании? Мы тоже можем помочь вам в этом. Более половины всех наших пользователей предпочитают получать предложения о работе, поэтому мы знаем, какие кодеры ищут работу прямо сейчас, и можем распространять среди них информацию о ваших открытых вакансиях. После того, как вы отправите нам описание вакансии, мы предоставим вам список адресов электронной почты и участников, которые проявили интерес к открытию, а также их резюме, информацию о ходе работы и решения, принятые в игре.Таким образом, вы сможете лучше познакомиться с навыками кодировщиков, прежде чем решите взять у них интервью.
Здесь мы можем запланировать короткий звонок или просто связаться со мной по электронной почте. Я буду рад рассказать вам больше о CheckiO и о том, как мы можем помочь вашей компании.
Мы знаем, что CheckiO рекомендуется во многих школах и университетах как дополнительный способ изучения Python. CheckiO дает вам возможность улучшить свои навыки программирования в увлекательной игровой форме, пока вы изучаете кодирование в своем классе.
Когда мы проектировали ClassRooms в CheckiO, идея заключалась в том, чтобы дать классным комнатам в реальной жизни дополнительный ресурс. Один, где учителя и ученики могли видеть свой прогресс и учиться друг у друга.
Позвольте мне сначала показать вам, как это выглядит.
Так вот оно. Это все, что вам нужно знать о CheckiO ClassRooms, прежде чем вы сможете начать работу.
Бесплатные аккаунты имеют некоторые ограничения, но для школ и университетов мы можем сделать исключение для вашего класса.Свяжитесь со мной, и я предоставлю вам всю информацию.
Спасибо за просмотр и помните, что ваши отзывы очень важны для нас. Увидимся на CheckiO!
Отзывы учителей
«Это было очень полезно в начале учебного года и вызвало большой интерес студентов» - Карл Терланд, школа Харроу
«Я ЛЮБЛЮ этот продукт и буду продолжать его использовать» - Тим Маки, Tilton School
«Перспектива использования Chekio для дополнительных заданий во время обучения - отличный способ бесконечно занимать тех студентов, которые учатся быстрее остальных» - Алексей Радченко
Создать класс для Python
Создать ClassRoom для TypeScript
CheckiO расширяет кругозор во всем мире с помощью игр.
Мы всегда хотели создать самую увлекательную игру, в которой игровой процесс и кодирование переплетаются, и где нет границы между игрой и изучением новых навыков. Игра, в которой программирование органично превращается в навык, необходимый для прогресса в увлекательной игре.
Мы считаем, что у каждого есть свой способ стать кодером. Мы моделируем бесконечное желание заниматься программированием, потому что это весело. И мы дорожим сообществом, в котором обмен знаниями и поддержка коллег являются ключевыми компонентами игры, которые помогают людям во всем мире свободно и творчески подходить к программированию.Среди наших игроков есть одни из самых талантливых программистов в мире, а также те, кто только начинает свой путь. Такое разнообразное и поддерживающее сообщество в сочетании с инструментами для кодовых игр позволяет CheckiO стать центром инженеров и программистов для обмена знаниями и опытом.
Изучите Python, построив 5 игр
Многие люди лучше всего изучают языки программирования, создавая проекты. Если вы хотите изучить Python, написав код для пяти игр, ознакомьтесь с 7-часовым видеокурсом, который мы только что выпустили на freeCodeCamp.org на канале YouTube. Мы собрали 5 отличных руководств по разработке игр, которые помогут вам изучить Python.
Вы создадите Pong, Snake, Connect Four, Tetris и простую многопользовательскую игру. Это все популярные игры, в которые интересно играть, а также писать код.
Код игры на Python!
Этот курс основан на проектном подходе. Если вы лучше всего учитесь на практике, этот курс для вас. Вы будете учиться у Кристиана Томпсона, Кита Галли и Техника с Тимом. Эти опытные преподаватели помогут вам понять каждую строчку кода в проектах.
Для изучения этого курса вам не требуется предварительный опыт программирования. Тем не менее, будет полезно, если вы знакомы с некоторыми базовыми концепциями программирования, поскольку в этом курсе пропущены основные инструкции по синтаксису и вы сразу перейдете к созданию проектов.
Создавайте игры с помощью командной строки, черепахи и Pygame
Одна из игр просто использует командную строку. Написание кода для командной строки - отличный способ получить базовые навыки программирования, не беспокоясь о графике.
Другая игра использует графический модуль черепахи. Это встроенный модуль, который часто используется для обучения начинающим навыкам программирования и может использоваться для простых игр.
Вы также научитесь создавать игры с помощью Pygame. Pygame - это набор модулей Python, который используется для создания всевозможных игр, даже сложных. Это упрощает добавление графики и звука в программы Python.
В последнем разделе вы узнаете, как кодировать масштабируемую многопользовательскую игру на Python с использованием сокетов и сетей.Вы узнаете, как развернуть свою игру, чтобы люди в любой точке мира могли играть друг против друга.
Создавая многопользовательскую игру, вы узнаете о таких концепциях, как разработка клиентов и серверов, отправка зашифрованных данных и подключение нескольких клиентов к серверу.
Полный курс можно посмотреть на YouTube-канале freeCodeCamp.org (7 часов просмотра).
Создайте свою первую видеоигру с помощью Python (опыт программирования не требуется)
Python - это простой язык для начала, и если вы ищете быструю победу в своем стремлении освоить все языки программирования (Ultimate Quest!) , Python - хорошее место для начала.
Чтобы извлечь хоть какую-то пользу из учебных пособий по Python, связанных с созданием игр, вам нужно сначала быть , знакомыми с некоторыми основными концепциями Python . Лучший способ изучить их - изучить более обычных функций Python . Под приземленным мы подразумеваем отсутствие отношения к играм.
Мы составили список самых полезных руководств по Python . В этот список входят те, которые обучают основным элементам Python, и те, которые направляют вас на пути создания игр.
Помогает, если вы знаете какой-нибудь язык программирования, прежде чем погрузиться в создание игр, даже если это не обязательно Python . Но не бойтесь. По мере прохождения этих руководств вы постоянно будете видеть утверждения относительно о том, насколько просто Python использовать .
Чтобы создавать игры на языке Python, вам понадобится PyGame. Как мы уже говорили ранее, некоторые из руководств, которые мы собрали здесь , включают в себя руководства только для Python .
Лучше всего, если у вас нет , если у вас нет опыта программирования или программирования .Мы рекомендуем изучить Python, прежде чем переходить к PyGame , потому что это, вероятно, сделает ваш переход к компетенции намного более плавным.
Если вы быстро учитесь и раньше занимались программированием (и, очевидно, не хотите слушать наши советы), вы, вероятно, справитесь с проблемами в разработке игр PyGame . Если это слишком сложно, вы всегда можете проверить свои уроки PyGame и перейти к вводным руководствам по Python .
В конечном итоге выбор за вами.Освоение языков программирования не обязательно должно быть спринтом. Если вы думаете о долгосрочной перспективе, вы поймете, что у вас есть время на все. Возьмите его по частям и впитайте язык.
Следующие курсы имеют рейтинг от новичка до уровня эксперта:
5 курсов для разработчиков игр на Python
Удеми
Если вы не против бросить 50 костей (см. $ 50 ) и посмотреть около десяти часов обучающего видео, этот курс по запросу в Udemy может стать вашим быстрым путем к успеху Python.
Это отличный способ изучить основы, если вам нужны видеоуроки. Бесплатные материалы на YouTube не так эффективны для Python, как для некоторых других языков программирования и программного обеспечения.
В среднем 4,6 звезды по более 3000 отзывов , мы говорим о некоторых высококачественных программах. Если у вас нет опыта программирования, этот курс станет вашим билетом в неизведанное. Все начнется с самого начала - вам даже не нужно загружать Python.
Вы могли заметить, что этот курс носит то же название, что и одна из ранее упомянутых книг. Потому что это тот же парень, Эл Свигарт. Трудно найти лучший учебный материал, чем то, что предлагает Свигарт. Даже официальные страницы Python ссылаются на некоторые его материалы.
Если вам понравился его бесплатный письменный контент, но вы хотите, чтобы его видеоруководство помогло вам в работе, то возьмите этот курс. Если вам это не нравится, у вас есть 30-дневная гарантия возврата денег. Это означает, что вы можете попробовать его и отказаться от него, если он не подходит.Здесь мы делаем все возможное, чтобы минимизировать риски.
Месяц дает вам достаточно времени, чтобы пройти хотя бы несколько часов программы и решить, хотите ли вы вернуть свои пятьдесят долларов или получить доступ к программе на всю жизнь.
Python
Как это принято в большинстве компаний, выпускающих программное обеспечение для игрового дизайна, Python предлагает учебные пособия для своей программы разработки. Эти учебные пособия могут помочь, если вы только начинаете или уже какое-то время окунулись в Python.
Если вы новичок в Python, но не новичок в программировании, лучше всего начать с Python для начинающих.Если вы новичок в программировании, Python предлагает вам руководство для начинающих, не являющееся программистом, специально для вас.
« standard » Python Guide познакомит вас с некоторыми наиболее примечательными функциями Python (не всеми его функциями). Само руководство даже говорит, что оно далеко не исчерпывающее.
Прочитав руководство, вы сможете приступить к работе с Python. Вероятно, вы захотите продолжить изучение базы данных Python (или других руководств в нашем списке!), Чтобы повысить свои возможности Python.
LearnPython
Эта программа удобна, и не только потому, что у нее есть собственная группа в Facebook. Эта группа FB хороша тем, что действует как форум «помощь и совет» для людей, использующих Python .
Этот учебник не относится к специально к игре, но это не значит, что вы не найдете его полезным. Изучение всех приемов работы с программным обеспечением, даже тех, которые выходят за рамки того, что, по вашему мнению, может понадобиться для разработки игр, - хороший способ развить свои навыки решения проблем Python.
На сайте LearnPython есть вводные руководства для новичков в Python. В нем также есть более сложные руководства, которые могут помочь тем из вас, кто уже немного занимается Python.
Если вам нужны знания о более широком применении Python , это хорошее руководство, с которым можно потратить некоторое время.
Think Python: как думать как компьютерный ученый
Если вам нужно разобраться с латунными кнопками базового Python, это текстовое веб-руководство может быть именно тем, что вам нужно.
Мы хотим сказать вам кое-что заранее: это подробное руководство.
Учебное пособие можно купить на amazon.com, но оно предоставляется бесплатно в Интернете . Мы снова свяжемся с ним здесь.
Это руководство начинается с таких тем, как анализ различий между языками высокого и низкого уровня. Если у вас нет опыта программирования, вы не останетесь в пыли. Если у вас есть некоторый опыт программирования, дополнительные объяснения могут показаться вам утомительными (по крайней мере, в первых частях руководства).
В руководстве рассматриваются темы языка программирования Python, объясняются такие элементы, как переменные, выражения и инструкции, функции, дизайн интерфейса, условные выражения и рекурсия, классы и функции, и этот список можно продолжить. Это длинное руководство. Подробное руководство.
Учебное пособие также включает в себя несколько упражнений для практики, предлагающих вам написать различные программы и различные функции.
В общем, это очень полезное руководство по быстрому освоению Python .Это станет полезной и стабильной базой, на которой вы сможете развить свои навыки разработки игр на Python.
Изобретайте с Python
Если вы не возражаете против чтения «легкого» PDF, этот 365-страничный учебник « Создание игр с Python и PyGame » может быть как раз тем, что поможет вам начать создавать игры с Python .
Эта конкретная книга - для программиста среднего уровня . Если у вас есть некоторый опыт программирования, особенно с Python , но вы не знаете, как использовать свои знания для создания игр, то это руководство как раз для вас.
В книге «Создание игр» используются примеры игр из библиотеки PyGame, чтобы научить вас создавать похожие игры. Цель этого руководства - дать вам целый ряд новых идей по использованию программного обеспечения Python для разработки ваших игр. Так что, даже если вы знакомы с Python и PyGame, но вам нужны идеи, вы можете просмотреть эту книгу.
Если вы ничего не знаете о языке Python, не бойтесь. У Invent with Python есть и другие варианты для вас. Вы можете использовать это второе руководство для автоматизации некоторых основных компьютерных задач с помощью Python, что является хорошим способом изучения языка (а также автоматизации задач!).
Они также предлагают «Изобретайте свои собственные компьютерные игры с Python», где дает вам исходные коды для завершенных игр, а обучает концепции , используя предоставленные примеры исходного кода. Все три книги - хорошие варианты для вас, в зависимости от того, на каком этапе программирования вы находитесь.
Все три из этих книг предлагаются бесплатно в Интернете , или вы можете купить физическую копию через Amazon (в обмен на деньги). Есть даже субреддит для Invent with Python (это не группа в Facebook, но…), вы можете общаться с другими пользователями Python, которые читали эти книги, пока вы просматриваете их сами.
Вот дополнительные возможности для изучения разработки на Python…
Школа Флэтайрон
Школа Flatiron предлагает программы и, что более важно, ценные сертификаты для выпускников курсов Python. Для тех, кто твердо настроен на карьеру, в школе Flatiron уровень занятости составляет 93%, а средняя зарплата выпускников составляет 76000 долларов. С такими курсами, как дизайн UX / UI, разработка программного обеспечения и наука о данных, ваши знания программирования в сочетании с этими существующими курсами только укрепят ваши навыки работы с Python.
Подробнее…
Data Camp
Data Camp предлагает множество различных курсов по Python. Начиная с курсов для начинающих, Data Camp охватывает все основы. Благодаря множеству классов, практическим инструкциям и примерам Data Camp предлагает, пожалуй, лучший способ изучить Python. Инструкторами являются опытные программисты, которые за несколько часов научат вас, как лучше использовать программирование.
Подробнее…
Pygame
Python - это язык программирования, признанный в сообществах программистов и разработчиков программного обеспечения как стабильный язык.Люди считают, что его намного легче выучить, чем некоторые другие языки программирования, такие как языки C, C ++ и C #.
Вот почему разработка игр с использованием Python и его расширения PyGame, естественно, становится все более распространенным явлением.
Как использовать PyGame
Pygame, набор руководств и модулей Python для игр, является отличным местом для начинающих разработчиков игр, чтобы начать свой путь к программированию и разработке игр.
Как установить Pygame
Перед установкой Pygame вам, естественно, понадобится Python для начала работы.Вы можете скачать Python прямо с официального сайта.
После того, как Python установлен в вашей системе, пришло время для установки Pygame.
Лучше всего установить PyGame с помощью pip, установщика пакетов Python. Это значительно упрощает установку различных аспектов и модулей из PyGame.
Если вам нужна дополнительная помощь в установке Python, ознакомьтесь с официальной документацией.
Как правило, вам нужно ввести следующее: ‘python -m pip install SomePackage.’
Однако специально для PyGame вы собираетесь поместить‘ python3 -m pip install -U pygame –user ’
Основы Pygame
Основные основы PyGame имеют решающее значение для понимания ее как инструмента разработки игр. Все, что вы делаете, происходит на поверхности. Чтобы заполнить поверхность, введите screen.fill (), чтобы заполнить фон.
Далее у нас есть то, что мы называем «блиттингом». Это процесс рендеринга игровых объектов. Вы «копируете» объект, и он отображает его на экране.
Затем у нас есть цикл событий. Вот как на самом деле работает ваша игра. Это помещает вашу игру в цикл до тех пор, пока вы не определите, когда вы выходите из цикла.
Рисование объектов
Это огромная часть процесса PyGame. Вам нужно будет ввести pygame.draw. Это позволяет пользователю рисовать различные формы на поверхности. Давайте посмотрим на некоторые варианты, которые у вас есть.
- Pygame Draw Line
- Pygame Draw Circle
- Pygame Draw Rectangle
Работа со спрайтами PyGame
Спрайты, как вы, возможно, знаете, представляют собой пиксели, объединенные для создания изображения, персонажа или анимации.К счастью, вы можете использовать спрайты в PyGame.
Разработка игр 1-2: Работа со спрайтами
Вы можете создавать спрайты прямо в интерфейсе PyGame и легко включать их в свою игру с помощью всего нескольких строк кода. Все, что вам нужно сделать, это ввести.
pygame.sprite.Sprite .__ init __ (сам)
Открывает модуль спрайтов PyGame. Отсюда вам нужно описать ваши размеры объекта. Если вы создаете синий прямоугольник, введите:
класс Player (pygame.sprite.Sprite):
def __init __ (self):
pygame.sprite.Sprite .__ init __ (self)
self.image = pygame.Surface ((50, 50))
self.image.fill (СИНИЙ)
self. rect = self.image.get_rect ()
self.rect.center = (ШИРИНА / 2, ВЫСОТА / 2)
Учебники Pygame
Вот несколько отличных руководств по Pygame. Это различные учебные пособия, начиная от начальных модулей и заканчивая более сложными проектами, такими как создание вашей первой, более простой игры.
В зависимости от игры Python и, соответственно, Pygame, могут быть фантастическим инструментом для создания игр.С помощью этих руководств вы сможете установить Pygame и освоить более простой процесс создания игр, чем другие средства программирования.
Что бы вы ни выбрали для использования в PyGame, вы, надеюсь, хорошо разбираетесь в разработке игр и сможете освоить Python как язык программирования.
FAQ
Трудно ли выучить Python?
В зависимости от вашего уровня приверженности изучению новых вещей и программированию Python может иметь разную степень сложности. Если вы человек, у которого проблемы с программированием, Python может быть более сложным, чем для тех, кто больше разбирается в информатике.Я гарантирую, что лучший способ изучить Python - это пройти через перечисленные нами уроки.
Какой лучший веб-сайт для изучения Python?
В целом, лучший веб-сайт для изучения Python - это Udemy. Udemy предлагает пользователям (за символическую плату) ценные наглядные пособия и видеоролики, которые действительно делают процесс изучения Python более доступным и всеобъемлющим.
Udemy идеально подходит для новичков не только в Python, но и в программировании в целом. Если вы полностью в неведении относительно тонкостей программирования, Udemy поможет вам в вашем путешествии по изучению Python.Несомненно, за пределами официальной документации Udemy - лучший способ изучить Python.
Какая сертификация лучше всего подходит для Python?
Различные сертификаты помогают в определенных областях, все зависит от того, где вы их получили. Сертификат номер один - это сертификат, который вы получаете от Мичиганского университета.
Эта сертификация ориентирована на данные и анализ данных с использованием Python. Он имеет фантастические отзывы от бывших студентов и дает вам сертификат по Python после изучения 5 курсов.Лекции интерактивные и практические, что является ключом к изучению чего-то вроде Python.
Мичиганский университет предлагает лучший способ изучить Python для получения сертификата. Некоторые курсы посвящены началу работы с данными, структурой данных, использованию баз данных с помощью Python и доступу к данным с помощью Python.
Могу ли я выучить Python за 6 месяцев?
Совершенно верно!
Благодаря ресурсам, предлагаемым во многих разных местах, как физических, так и удаленных, вы можете изучить Python за 6 месяцев.Конечно, в игру вступают и другие факторы, такие как ваша склонность и предшествующие знания кодирования. Те, у кого есть талант к программированию, могут быстро изучить Python, но не волнуйтесь, если вы только начинаете.
Шесть месяцев - разумный расчетный срок. Однако мы рекомендуем потратить больше времени, чтобы понять и полностью использовать Python. Лучший способ изучить Python - сделать его медленным и изучить основы, чтобы у вас был фундамент, на который можно опираться.
Змейка на Python | Программа Snake Game с использованием Pygame
Да, я знаю, что вы все играли в Snake Game и определенно никогда не хотели проигрывать.В детстве мы все любили искать читы, чтобы никогда не увидеть сообщение «Игра окончена», но, как технари, я знаю, что вы хотели бы заставить эту «Змейку» танцевать под свои ритмы. Это то, что я покажу вам в этой статье о Snake Game на Python.
Прежде чем двигаться дальше, давайте кратко рассмотрим все подбиты, которые создают игру «Змейка» на Python:
- Установка Pygame
- Создание экрана
- Создание змейки
- Перемещение змеи
- Игра окончена, когда Змейка выходит за границы
- Добавление еды
- Увеличение длины змеи
- Отображение результатов
Установка Pygame:
Первое, что вам нужно сделать для создания игр с использованием Pygame, - это установить его в ваших системах.Для этого вы можете просто использовать следующую команду:
pip install pygame
Как только это будет сделано, просто импортируйте Pygame и начните разработку игры. Прежде чем двигаться дальше, взгляните на функции Pygame, которые использовались в этой игре-змейке, вместе с их описаниями.
Функция | Описание |
init () | Инициализирует все импортированные модули Pygame (возвращает кортеж, указывающий на успешность и неудачу инициализации) |
display.set_mode () | Принимает кортеж или список в качестве параметра для создания поверхности (предпочтительно кортеж) |
update () | Обновляет экран |
quit () | Используется до неинициализировать все |
set_caption () | Устанавливает текст заголовка в верхней части экрана дисплея |
event.get () | Возвращает список всех событий | Заполнит поверхность сплошным цветом |
time.Clock () | Помогает отслеживать время времени |
font.SysFont () | Создает шрифт Pygame из ресурсы системных шрифтов |
Создание экрана:
Чтобы создать экран с помощью Pygame, вам нужно будет использовать функцию display.set_mode () . Кроме того, вам придется использовать методы init () и quit () для инициализации и деинициализации всего в начале и в конце кода.Метод update () используется для обновления любых изменений, внесенных на экран. Существует еще один метод, например, flip () , который работает аналогично функции update (). Разница в том, что метод update () обновляет только внесенные изменения (однако, если параметры не переданы, обновляет весь экран), а метод flip () повторно воспроизводит весь экран.
КОД:
импорт pygame pygame.init () dis = pygame.display.set_mode ((400,300)) pygame.display.update () pygame.quit () quit ()
ВЫХОД:
Но когда вы запустите этот код, экран появится, но он сразу же закроется. Чтобы исправить это, вы должны использовать игровой цикл с помощью цикла while, прежде чем я фактически выйду из игры, как показано ниже:
import pygame pygame.init () dis = pygame.display.set_mode ((400,300)) pygame.display.update () pygame.display.set_caption ('Змейка от Edureka') game_over = Ложь пока не game_over: для события в pygame.event.get (): print (event) # распечатывает все действия, которые происходят на экране pygame.quit () quit ()
Когда вы запустите этот код, вы увидите, что экран, который вы видели ранее, не закрывается, а также возвращает все действия, которые происходят над ним. Я сделал это с помощью функции event.get () . Кроме того, я назвал экран «Snake Game by Edureka», используя функцию display.set_caption () .
ВЫХОД:
Теперь у вас есть экран для игры в Snake Game, но когда вы пытаетесь нажать кнопку закрытия, экран не закрывается.Это потому, что вы не указали, что ваш экран должен закрываться, когда вы нажимаете эту кнопку закрытия. Для этого Pygame предоставляет событие под названием «QUIT», и его следует использовать следующим образом:
import pygame pygame.init () dis = pygame.display.set_mode ((400,300)) pygame.display.update () pygame.display.set_caption ('Змейка от Edureka') game_over = Ложь пока не game_over: для события в pygame.event.get (): если event.type == pygame.QUIT: game_over = Верно pygame.quit () quit ()
Итак, ваш экран готов.Следующая часть - нарисовать нашу змейку на экране, о чем мы поговорим в следующем разделе.
Создание змеи:
Чтобы создать змею, я сначала инициализирую несколько цветовых переменных, чтобы раскрасить змею, еду, экран и т. Д. Цветовая схема, используемая в Pygame, - это RGB, т.е. . Если вы установите для всех этих значений 0, цвет будет черным, а все 255 будут белыми. Так что наша змейка на самом деле будет прямоугольником. Чтобы рисовать прямоугольники в Pygame, вы можете использовать функцию draw.rect () , который поможет нарисовать прямоугольник желаемого цвета и размера.
импорт pygame pygame.init () dis = pygame.display.set_mode ((400,300)) pygame.display.set_caption ('Змейка от Edureka') синий = (0,0,255) красный = (255,0,0) game_over = Ложь пока не game_over: для события в pygame.event.get (): если event.type == pygame.QUIT: game_over = Верно pygame.draw.rect (дис, синий, [200,150,10,10]) pygame.display.update () pygame.quit () quit ()
ВЫХОД:
Как видите, змееголовый создан в виде синего прямоугольника.Следующий шаг - заставить вашу змею двигаться.
Перемещение змейки:
Чтобы переместить змейку, вам нужно будет использовать ключевые события, присутствующие в классе KEYDOWN Pygame. Здесь используются события K_UP, K_DOWN, K_LEFT и K_RIGHT, чтобы змея двигалась вверх, вниз, влево и вправо соответственно. Кроме того, экран дисплея изменяется с черного по умолчанию на белый с помощью метода fill () .
Я создал новые переменные x1_change и y1_change для хранения обновляемых значений координат x и y.
импорт pygame pygame.init () белый = (255, 255, 255) черный = (0, 0, 0) красный = (255, 0, 0) dis = pygame.display.set_mode ((800, 600)) pygame.display.set_caption ('Змейка от Edureka') game_over = Ложь х1 = 300 y1 = 300 x1_change = 0 y1_change = 0 часы = pygame.time.Clock () пока не game_over: для события в pygame.event.get (): если event.type == pygame.QUIT: game_over = Верно если event.type == pygame.KEYDOWN: если event.key == pygame.K_LEFT: x1_change = -10 y1_change = 0 elif event.key == pygame.K_RIGHT: x1_change = 10 y1_change = 0 elif event.key == pygame.K_UP: y1_change = -10 x1_change = 0 elif event.key == pygame.K_DOWN: y1_change = 10 x1_change = 0 x1 + = x1_change y1 + = y1_change dis.fill (белый) pygame.draw.rect (dis, черный, [x1, y1, 10, 10]) pygame.display.update () часы.tick (30) pygame.quit () quit ()
ВЫХОД:
Игра заканчивается, когда Змея достигает границ:
В этой игре со змеями, если игрок попадает в границы экрана, он проигрывает. Чтобы указать это, я использовал оператор «if», который определяет пределы для координат x и y змеи, которые должны быть меньше или равны координатам экрана. Кроме того, не забудьте, что я удалил жесткие коды и использовал вместо них переменные, чтобы было проще, если вы захотите внести какие-либо изменения в игру позже.
импорт pygame время импорта pygame.init () белый = (255, 255, 255) черный = (0, 0, 0) красный = (255, 0, 0) dis_width = 800 dis_height = 600 dis = pygame.display.set_mode ((dis_width, dis_width)) pygame.display.set_caption ('Змейка от Edureka') game_over = Ложь x1 = dis_width / 2 y1 = dis_height / 2 snake_block = 10 x1_change = 0 y1_change = 0 часы = pygame.time.Clock () snake_speed = 30 font_style = pygame.font.SysFont (Нет, 50) сообщение def (сообщение, цвет): mesg = font_style.render (сообщение, True, цвет) дис.blit (mesg, [dis_width / 2, dis_height / 2]) пока не game_over: для события в pygame.event.get (): если event.type == pygame.QUIT: game_over = Верно если event.type == pygame.KEYDOWN: если event.key == pygame.K_LEFT: x1_change = -snake_block y1_change = 0 elif event.key == pygame.K_RIGHT: x1_change = змеиный_блок y1_change = 0 elif event.key == pygame.K_UP: y1_change = -snake_block x1_change = 0 elif событие.ключ == pygame.K_DOWN: y1_change = змеиный_блок x1_change = 0 если x1> = dis_width или x1 <0 или y1> = dis_height или y1 <0: game_over = Верно x1 + = x1_change y1 + = y1_change dis.fill (белый) pygame.draw.rect (dis, черный, [x1, y1, snake_block, snake_block]) pygame.display.update () часы.tick (snake_speed) сообщение («Ты проиграл», красный) pygame.display.update () время сна (2) pygame.quit () quit ()
ВЫХОД:
Добавление еды:
Здесь я добавлю немного еды для змеи, и когда змея пересечет эту еду, у меня будет сообщение с надписью «Yummy !!» .Кроме того, я сделаю небольшое изменение, в котором добавлю возможность выйти из игры или снова сыграть, когда игрок проиграет.
импорт pygame время импорта случайный импорт pygame.init () белый = (255, 255, 255) черный = (0, 0, 0) красный = (255, 0, 0) синий = (0, 0, 255) dis_width = 800 dis_height = 600 dis = pygame.display.set_mode ((dis_width, dis_height)) pygame.display.set_caption ('Змейка от Edureka') часы = pygame.time.Clock () snake_block = 10 snake_speed = 30 font_style = pygame.font.SysFont (Нет, 30) сообщение def (сообщение, цвет): mesg = font_style.render (сообщение, True, цвет) dis.blit (mesg, [dis_width / 3, dis_height / 3]) def gameLoop (): # создание функции game_over = Ложь game_close = Ложь x1 = dis_width / 2 y1 = dis_height / 2 x1_change = 0 y1_change = 0 foodx = round (random.randrange (0, dis_width - snake_block) / 10.0) * 10.0 foody = round (random.randrange (0, dis_width - snake_block) / 10.0) * 10.0 пока не game_over: в то время как game_close == True: дис.заливка (белый) сообщение («Вы проиграли! Нажмите Q-Quit или C-Play снова», красный) pygame.display.update () для события в pygame.event.get (): если event.type == pygame.KEYDOWN: если event.key == pygame.K_q: game_over = Верно game_close = Ложь если event.key == pygame.K_c: gameLoop () для события в pygame.event.get (): если event.type == pygame.ПОКИДАТЬ: game_over = Верно если event.type == pygame.KEYDOWN: если event.key == pygame.K_LEFT: x1_change = -snake_block y1_change = 0 elif event.key == pygame.K_RIGHT: x1_change = змеиный_блок y1_change = 0 elif event.key == pygame.K_UP: y1_change = -snake_block x1_change = 0 elif event.key == pygame.K_DOWN: y1_change = змеиный_блок x1_change = 0 если x1> = dis_width или x1 <0 или y1> = dis_height или y1 <0: game_close = Верно x1 + = x1_change y1 + = y1_change dis.fill (белый) pygame.draw.rect (дис, синий, [foodx, foody, snake_block, snake_block]) pygame.draw.rect (dis, черный, [x1, y1, snake_block, snake_block]) pygame.display.update () если x1 == foodx и y1 == foody: print ("Вкуснятина !!") Часы.тик (snake_speed) pygame.quit () покидать() gameLoop ()
ВЫХОД:
Терминал:
Увеличение длины змеи:
Следующий код увеличит размер нашего саке, когда он ест еду. Кроме того, если змея сталкивается со своим телом, игра окончена, и вы увидите сообщение «Вы проиграли! Нажмите Q-Quit или C-Play Again ». Длина змейки в основном содержится в списке, а начальный размер, указанный в следующем коде, составляет один блок.
импорт pygame время импорта случайный импорт pygame.init () белый = (255, 255, 255) желтый = (255, 255, 102) черный = (0, 0, 0) красный = (213, 50, 80) зеленый = (0, 255, 0) синий = (50, 153, 213) dis_width = 600 dis_height = 400 dis = pygame.display.set_mode ((dis_width, dis_height)) pygame.display.set_caption ('Змейка от Edureka') часы = pygame.time.Clock () snake_block = 10 snake_speed = 15 font_style = pygame.font.SysFont ("bahnschrift", 25) score_font = pygame.font.SysFont ("comicsansms", 35) def our_snake (snake_block, snake_list): для x в snake_list: pygame.draw.rect (dis, черный, [x [0], x [1], snake_block, snake_block]) сообщение def (сообщение, цвет): mesg = font_style.render (сообщение, True, цвет) dis.blit (mesg, [dis_width / 6, dis_height / 3]) def gameLoop (): game_over = Ложь game_close = Ложь x1 = dis_width / 2 y1 = dis_height / 2 x1_change = 0 y1_change = 0 snake_List = [] Length_of_snake = 1 foodx = round (random.randrange (0, dis_width - snake_block) / 10.0) * 10.0 foody = round (random.randrange (0, dis_height - snake_block) / 10.0) * 10,0 пока не game_over: в то время как game_close == True: dis.fill (синий) сообщение («Вы проиграли! Нажмите C-Play снова или Q-Quit», красный) pygame.display.update () для события в pygame.event.get (): если event.type == pygame.KEYDOWN: если event.key == pygame.K_q: game_over = Верно game_close = Ложь если event.key == pygame.K_c: gameLoop () для события в pygame.event.get (): если event.type == pygame.QUIT: game_over = Верно если event.type == pygame.KEYDOWN: если event.key == pygame.K_LEFT: x1_change = -snake_block y1_change = 0 elif event.key == pygame.K_RIGHT: x1_change = змеиный_блок y1_change = 0 elif event.key == pygame.K_UP: y1_change = -snake_block x1_change = 0 elif событие.ключ == pygame.K_DOWN: y1_change = змеиный_блок x1_change = 0 если x1> = dis_width или x1 <0 или y1> = dis_height или y1 <0: game_close = Верно x1 + = x1_change y1 + = y1_change dis.fill (синий) pygame.draw.rect (дис, зеленый, [foodx, foody, snake_block, snake_block]) snake_Head = [] snake_Head.append (x1) snake_Head.append (y1) snake_List.append (snake_Head) если len (snake_List)> Length_of_snake: del snake_List [0] для x в snake_List [: - 1]: если x == snake_Head: game_close = Верно наша_змея (snake_block, snake_List) pygame.display.update () если x1 == foodx и y1 == foody: foodx = round (random.randrange (0, dis_width - snake_block) / 10.0) * 10.0 foody = round (random.randrange (0, dis_height - snake_block) / 10.0) * 10.0 Длина_змеи + = 1 часы.tick (snake_speed) pygame.quit () покидать() gameLoop ()
ВЫХОД:
Отображение счета:
И последнее, но не менее важное: вам нужно будет отобразить счет игрока.Для этого я создал новую функцию «Your_score». Эта функция отобразит длину змеи за вычетом 1, потому что это начальный размер змеи.
импорт pygame время импорта случайный импорт pygame.init () белый = (255, 255, 255) желтый = (255, 255, 102) черный = (0, 0, 0) красный = (213, 50, 80) зеленый = (0, 255, 0) синий = (50, 153, 213) dis_width = 600 dis_height = 400 dis = pygame.display.set_mode ((dis_width, dis_height)) pygame.display.set_caption ('Змейка от Edureka') часы = pygame.time.Clock () snake_block = 10 snake_speed = 15 font_style = pygame.font.SysFont ("bahnschrift", 25) score_font = pygame.font.SysFont ("comicsansms", 35) def Your_score (оценка): value = score_font.render ("Your Score:" + str (score), True, yellow) dis.blit (значение, [0, 0]) def our_snake (snake_block, snake_list): для x в snake_list: pygame.draw.rect (dis, черный, [x [0], x [1], snake_block, snake_block]) сообщение def (сообщение, цвет): mesg = font_style.render (сообщение, True, цвет) дис.blit (mesg, [dis_width / 6, dis_height / 3]) def gameLoop (): game_over = Ложь game_close = Ложь x1 = dis_width / 2 y1 = dis_height / 2 x1_change = 0 y1_change = 0 snake_List = [] Length_of_snake = 1 foodx = round (random.randrange (0, dis_width - snake_block) / 10.0) * 10.0 foody = round (random.randrange (0, dis_height - snake_block) / 10.0) * 10.0 пока не game_over: в то время как game_close == True: dis.fill (синий) сообщение («Вы проиграли! Нажмите C-Play снова или Q-Quit», красный) Ваша_оценка (Длина_змеи - 1) pygame.display.update () для события в pygame.event.get (): если event.type == pygame.KEYDOWN: если event.key == pygame.K_q: game_over = Верно game_close = Ложь если event.key == pygame.K_c: gameLoop () для события в pygame.event.get (): если event.type == pygame.QUIT: game_over = Верно если event.type == pygame.KEYDOWN: если событие.ключ == pygame.K_LEFT: x1_change = -snake_block y1_change = 0 elif event.key == pygame.K_RIGHT: x1_change = змеиный_блок y1_change = 0 elif event.key == pygame.K_UP: y1_change = -snake_block x1_change = 0 elif event.key == pygame.K_DOWN: y1_change = змеиный_блок x1_change = 0 если x1> = dis_width или x1 <0 или y1> = dis_height или y1 <0: game_close = Верно x1 + = x1_change y1 + = y1_change дис.заливка (синий) pygame.draw.rect (дис, зеленый, [foodx, foody, snake_block, snake_block]) snake_Head = [] snake_Head.append (x1) snake_Head.append (y1) snake_List.append (snake_Head) если len (snake_List)> Length_of_snake: del snake_List [0] для x в snake_List [: - 1]: если x == snake_Head: game_close = Верно наша_змея (snake_block, snake_List) Ваша_оценка (Длина_змеи - 1) pygame.display.update () если x1 == foodx и y1 == foody: foodx = круглый (случайный.randrange (0, dis_width - snake_block) / 10.0) * 10.0 foody = round (random.randrange (0, dis_height - snake_block) / 10.0) * 10.0 Длина_змеи + = 1 часы.tick (snake_speed) pygame.quit () покидать() gameLoop ()
ВЫХОД:
На этом мы подошли к концу статьи о Snake Game на Python. Я надеюсь, что вы понимаете все, что было поделено с вами в этой статье.