Игровой проект
В этой части мы используем pygame, чтобы создать немного более крупную игру. Это вариант классической игры Sokoban, где игрок перемещает робота по сетке и толкает коробки в правильные места, стараясь сделать как можно меньше ходов.
Итоговый результат будет выглядеть так:
Карта игры
Начнем с рисования карты, используемой в игре. Игра реализована в классе Sokoban, который будет содержать всю функциональность, необходимую для игры. На первом этапе содержимое класса выглядит так:
import pygame
class Sokoban:
def __init__(self):
pygame.init()
self.load_images()
self.new_game()
self.height = len(self.map)
self.width = len(self.map[0])
self.scale = self.images[0].get_width()
window_height = self.scale * self.height
window_width = self.scale * self.width
self.window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("Sokoban")
self.main_loop()
def load_images(self):
self.images = []
for name in ["floor", "wall", "target", "box", "robot", "done", "target_robot"]:
self.images.append(pygame.image.load(name + ".png"))
def new_game(self):
self.map = [[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
[1, 2, 3, 0, 0, 0, 1, 0, 0, 1, 2, 3, 0, 0, 0, 0, 1],
[1, 0, 0, 1, 2, 3, 0, 2, 3, 0, 0, 0, 1, 0, 0, 0, 1],
[1, 0, 4, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
def main_loop(self):
while True:
self.check_events()
self.draw_window()
def check_events(self):
for event in pygame.event.get():
if event.type == pygame.QUIT:
exit()
def draw_window(self):
self.window.fill((0, 0, 0))
for y in range(self.height):
for x in range(self.width):
square = self.map[y][x]
self.window.blit(self.images[square], (x * self.scale, y * self.scale))
pygame.display.flip()
if __name__ == "__main__":
Sokoban()Запуск программы должен показать окно с начальным состоянием игры. Посмотрим подробнее на код, который это делает.
Конструктор
Конструктор класса инициализирует модули pygame, а также основные переменные и структуры данных, участвующие в игре. Он также вызывает метод главного цикла игры.
def __init__(self):
pygame.init()
self.load_images()
self.new_game()
self.height = len(self.map)
self.width = len(self.map[0])
self.scale = self.images[0].get_width()
window_height = self.scale * self.height
window_width = self.scale * self.width
self.window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("Sokoban")
self.main_loop()Метод load_images загружает изображения, используемые в игре, в список с именем images. Метод new_game создает двумерный список с именем map, который содержит состоя ние игровой сетки в начале игры.
Переменные height и width инициализируются на основе размеров игровой сетки. Переменная scale содержит длину стороны одной клетки сетки. Поскольку каждое изображение является квадратом точно такого же размера, размер всех клеток покрывается этой одной переменной, и ширина первого изображения вполне подходит в качестве значения. Это же значение можно использовать для вычисления ширины и высоты всей сетки, что позволяет создать окно подходящего размера для отображения игровой сетки.
Загрузка изображений
Метод load_images загружает все изображения, используемые в игре:
def load_images(self):
self.images = []
for name in ["floor", "wall", "target", "box", "robot", "done", "target_robot"]:
self.images.append(pygame.image.load(name + ".png"))В игре используются следующие изображения:
Клетка пола
- Имя файла:
floor.png - Позиция в списке: 0