Эта статья для тех кто знает основы pygame!
В этой статье рассмотрим способ создания меню для игры.
Итак перед тем как начать что-то делать надо это понять.Возможно кто-то не знает, но
Игровой сценой называют пространство в котором пользователь что-либо делает: выбирает уровень, видит заставку, выбирает персонажа или банально играет.
Сегодня мы рассмотрим создание таких двух сцен на pygame: сцену меню и сцену уровня.
Для начала создадим файл с обычной конструкцией любой игры pygame c одной сценой:
import pygame as p
import sys as s
p.init()
size = (1280, 840)
screen = p.display.set_mode(size)
fps = 60
clock = p.time.Clock()
while True:
for event in p.event.get():
if event.type == p.QUIT:
p.quit()
s.exit()
p.display.flip()
clock.tick(fps)
if __name__ == '__main__':
main_scene(screen)
Когда я писал, что вы должны знать основы pygame, я имел ввиду что вы должны понимать что делает данный выше код!
Теперь мы можем добавить пару штрихов в нашу программу как предлагает pycharm:
def main_scene(display):
while True:
for event in p.event.get():
if event.type == p.QUIT:
p.quit()
s.exit()
p.display.flip()
clock.tick(fps)
if __name__ == '__main__':
main_scene(screen)
Теперь можно догадаться как будет реализована система сцен, каждая сцена в нашей программе - это цикл, в нём мы выводим изображения, кнопки, проверяем события.Пока мы выполняем одну функцию мы находимся в одной сцене, а переходя на следующую сцену мы будем вызывать другую функцию со своим выводом и проверкой событий.
Игровая сцена в pygame - это цикл с определённым выводом и проверкой событий, к примеру в тетрис - это вывод падающих фигур.
Ну что же давайте зададим оформление нашему меню: текст, и прямоугольник выбирающий уровень.Для простоты сделаем переход только на первый уровень:
def menu():
global screen
y = 100
up = False
down = True
list_of_level = []
f1 = p.font.SysFont('serif', 48)
text_level1 = f1.render("Level 1", False, (0, 180, 0))
f2 = p.font.SysFont('serif', 48)
text_level2 = f2.render("Level 2", False, (0, 180, 0))
f3 = p.font.SysFont('serif', 48)
text_level3 = f3.render("Level 3", False, (0, 180, 0))
f4 = p.font.SysFont('serif', 48)
text_level4 = f4.render("Level 4", False, (0, 180, 0))
f5 = p.font.SysFont('serif', 48)
text_level5 = f5.render("Level 5", False, (0, 180, 0))
list_of_level.append(text_level1)
list_of_level.append(text_level2)
list_of_level.append(text_level3)
list_of_level.append(text_level4)
list_of_level.append(text_level5)
level_is_1 = False
while True:
for event in p.event.get():
if event.type == p.QUIT:
p.quit()
s.exit()
elif event.type == p.KEYDOWN:
if event.key == p.K_UP and up:
y -= 100
if event.key == p.K_DOWN and down:
y += 100
if event.key == p.K_RETURN and level_is_1:
level1()
break
if y == 100:
up = False
level_is_1 = True
elif y == 500:
down = False
else:
up = True
down = True
level_is_1 = False
y_t = 0
for i in list_of_level:
y_t += 100
screen.blit(i, (400, y_t))
p.draw.rect(screen, (25, 146, 132), (200, y, 100, 75))
p.display.flip()
clock.tick(fps)
screen.fill((100, 100, 100))
Ну ладно, погнали разбирать код:
Переменная y отвечает за то на какой высоте по пикселям выводится прямоугольник которым мы выбираем уровень.
Переменные up и down отвечают за то, чтобы не дать прямоугольнику двигаться дальше верха и ниже низа.
Переменная-список list_of_level нужна чтобы в цикле выводить все текст пяти уровней на экран.
f1 = p.font.SysFont('serif', 48)
text_level1 = f1.render("Level 1", False, (0, 180, 0))
list_of_level.append(text_level1)
Разберём на примере первого уровня переменные остальных тоже.С помощью f1 мы задаём шрифт и высоту шрифта.Затем с помощью text_level1 задаём текст, сглаживание и цвет соответственно.А третьей строкой добавляем переменную в список list_of_level.
Далее создаём переменную для проверки находится ли прямоугольник на экране на уровне текста первого уровня.По этой переменной мы узнаем когда перейти на другую сцену при нажатии Enter.
for event in p.event.get():
if event.type == p.QUIT:
p.quit()
s.exit()
elif event.type == p.KEYDOWN:
if event.key == p.K_UP and up:
y -= 100
if event.key == p.K_DOWN and down:
y += 100
if event.key == p.K_RETURN and level_is_1:
level1()
break
if y == 100:
up = False
level_is_1 = True
elif y == 500:
down = False
else:
up = True
down = True
level_is_1 = False
Ну тут разобраться не трудно поэтому взял сразу такой большой кусок кода:
В цикле for проверяем события если клавиша вверх и прямоугольник не вверху, то уменьшаем переменную y на 100.Если клавиша вниз и прямоугольник не внизу, то увеличиваем y на 100.А если нажата Enter и прямоугольник на уровне 1, то запускаем функцию которой пока ещё нету и завершаем цикл.
Автор не ошибся в pygame и вправду название клавиши Enter - это RETURN
А далее вне цикла for мы проверяем и задаём y и другим переменным значения.Сначала если y стал равен 100 то up становится False так как прямоугольник уже в самом верху и level_is_1 равен True так как прямоугольник напротив текста text_level1.Далее если y равен 500, то down равен False так как прямоугольник в самом низу.А последним делом мы проверяем что если прямоугольник и не внизу и не вверху, то ему можно двигаться и вверх и вниз, а уровень выбран не первый.
Эти проверки идут не в цикле for, а в общем цикле while
Теперь рассмотрим последний цикл for на этой сцене:
y_t = 0
for i in list_of_level:
y_t += 100
screen.blit(i, (400, y_t))
Итак заводим вспомогательную переменную y_t для вывода текста по высоте, а по длине значение у всего текста одно - 400.В цикле проходимся по заведённому ранее списку list_of_level и каждый раз пребавляем к переменной 100 - это то расстояние на котором друг от друга будут держаться названия уровней.И выводим наш текст из списка который будет находится в 400 пикселях по ширине и y_t пикселях по высоте.
В данном коде всё расстояние в пикселях
p.draw.rect(screen, (25, 146, 132), (200, y, 100, 75))
p.display.flip()
clock.tick(fps)
screen.fill((100, 100, 100))
Ну и в конце цикла выводим наш прямоугольник, обновляем экран, проверяем частоту кадров,и красим экран в фоновый цвет.
Теперь рассмотрим код второй сцены(мы просто выведим там текст):
def level1():
global screen
while True:
f = p.font.SysFont('serif', 100)
text = f.render("Level 1", False, (0, 180, 0))
for event in p.event.get():
if event.type == p.QUIT:
p.quit()
s.exit()
screen.blit(text, (300, 300))
p.display.flip()
clock.tick(fps)
screen.fill((100, 100, 100))
Тут всё должно быть предельно понятно, а если что-то забыли то полистайте наверх.
Единственное хотелось бы отметить что мы берём в обоих функциях именно глобальную переменную экрана, а не новую, чтобы pygame не создавал второй окно, а выводил это на том же окне.Этого также можно было бы избежать просто задав аргумент функции, но автору так не хочеться.
Итак теперь у вас есть шаблон для меню.Пишите в комментах новые темы для статей.
Пожалуй предоставлю вам скрины кода и выполнения программы: