Практика разработки игр на Python: примеры и инструкции

Раздел: Разработка на Python -> Игровая разработка

Примеры игр на Python: от простых к сложным

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

Наиболее эффективное решение: игра «Змейка» на Pygame

Pygame - популярная библиотека для создания 2D-игр. Она предоставляет инструменты для работы с графикой, звуком и событиями. Рассмотрим создание классической змейки.

import pygame, random

pygame.init()
W, H = 600, 400
CELL = 20
screen = pygame.display.set_mode((W, H))
clock = pygame.time.Clock()

snake = [(W//2, H//2)]
dx, dy = CELL, 0
food = (random.randrange(0, W, CELL), random.randrange(0, H, CELL))

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP and dy == 0: dx, dy = 0, -CELL
            elif event.key == pygame.K_DOWN and dy == 0: dx, dy = 0, CELL
            elif event.key == pygame.K_LEFT and dx == 0: dx, dy = -CELL, 0
            elif event.key == pygame.K_RIGHT and dx == 0: dx, dy = CELL, 0

    head = (snake[0][0] + dx, snake[0][1] + dy)
    if head in snake or head[0] < 0 or head[0] >= W or head[1] < 0 or head[1] >= H:
        running = False
    snake.insert(0, head)
    if head == food:
        food = (random.randrange(0, W, CELL), random.randrange(0, H, CELL))
    else:
        snake.pop()

    screen.fill((0,0,0))
    for seg in snake:
        pygame.draw.rect(screen, (0,255,0), (seg[0], seg[1], CELL, CELL))
    pygame.draw.rect(screen, (255,0,0), (food[0], food[1], CELL, CELL))
    pygame.display.flip()
    clock.tick(10)

pygame.quit()

игры на python примеры (примеры игр на python)

Этот код инициализирует окно, создаёт змейку, управление стрелками, еду и проверку столкновений. Основной цикл обрабатывает события и обновляет экран.

Типичные ошибки:

  • Забыть pygame.display.flip() - экран не обновляется.
  • Неправильное управление: разрешён поворот на 180 градусов (змейка врезается в себя). В примере проверяется, что направление не противоположное.
  • Мерцание - решается постоянной перерисовкой и ограничением FPS через clock.tick().

Цель: освоить базовые концепции игрового цикла, обработки пользовательского ввода и коллизий. Подходит для первого графического проекта.

Как реализовать консольную игру «Угадай число»?

Простой вариант для начинающих, не требующий внешних библиотек.

import random

number = random.randint(1, 100)
attempts = 0
print('Угадайте число от 1 до 100')
while True:
    guess = input('Ваше предположение: ')
    if not guess.isdigit():
        print('Введите целое число')
        continue
    guess = int(guess)
    attempts += 1
    if guess < number:
        print('Больше')
    elif guess > number:
        print('Меньше')
    else:
        print(f'Поздравляю! Вы угадали за {attempts} попыток')
        break

Python game codes (коды для игр на python)

Ошибки:

  • Не проверяется ввод нечисловых данных - программа крашится. Используется isdigit().
  • Бесконечный цикл при некорректном вводе - добавлено continue.

Цель: отработать циклы, условные операторы и обработку ввода. Хорошая отправная точка.

Как создать крестики-нолики с графическим интерфейсом?

Используем Pygame для отрисовки и обработки кликов.

import pygame

pygame.init()
SIZE = 300
screen = pygame.display.set_mode((SIZE, SIZE))
board = [[None]*3 for _ in range(3)]
player = 'X'

def draw_board():
    screen.fill((255,255,255))
    for i in range(1,3):
        pygame.draw.line(screen, (0,0,0), (i*100,0), (i*100,SIZE), 2)
        pygame.draw.line(screen, (0,0,0), (0,i*100), (SIZE,i*100), 2)
    for r in range(3):
        for c in range(3):
            if board[r][c] == 'X':
                pygame.draw.line(screen, (255,0,0), (c*100+10,r*100+10), (c*100+90,r*100+90), 2)
                pygame.draw.line(screen, (255,0,0), (c*100+90,r*100+10), (c*100+10,r*100+90), 2)
            elif board[r][c] == 'O':
                pygame.draw.circle(screen, (0,0,255), (c*100+50,r*100+50), 40, 2)

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            x, y = event.pos
            r, c = y//100, x//100
            if board[r][c] is None:
                board[r][c] = player
                player = 'O' if player == 'X' else 'X'
    draw_board()
    pygame.display.flip()
pygame.quit()

создание игры на python (создание игры на python)

Проблемы:

  • Нет проверки на победу или ничью - игра бесконечна. Можно добавить функцию проверки линий.
  • Координаты мыши не масштабируются при изменении размера окна. В примере окно фиксировано.

Цель: изучить работу с мышью, сеточную логику и чередование ходов.

Как написать текстовый квест с выбором действий?

Интерактивная история без графики - развивает логику ветвлений.

def start():
    print('Вы просыпаетесь в лесу. Рядом тропинка.')
    choice = input('1 - пойти по тропинке, 2 - остаться: ')
    if choice == '1':
        path()
    elif choice == '2':
        print('Вы сидите и ждёте. Ничего не происходит. Конец.')
    else:
        print('Некорректный ввод')
        start()

def path():
    print('На тропинке вы видите сундук.')
    choice = input('1 - открыть, 2 - обойти: ')
    if choice == '1':
        print('В сундуке золото! Вы победили.')
    elif choice == '2':
        print('Вы обошли сундук и вышли к деревне. Конец.')
    else:
        print('Некорректный ввод')
        path()

start()

Ошибки:

  • Рекурсия может привести к переполнению стека при частых неправильных вводах. Лучше использовать цикл.
  • Отсутствие сохранения состояния - для больших квестов нужна структура данных.

Цель: понять ветвление и пользовательский ввод. Подходит для прототипирования сюжетных историй.

Как создать простую аркаду на библиотеке Arcade?

Arcade - современная альтернатива Pygame, проще в использовании.

import arcade

SCREEN_WIDTH, SCREEN_HEIGHT = 600, 400

class Game(arcade.Window):
    def __init__(self):
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT)
        self.player_x = 100
        self.player_y = 100

    def on_draw(self):
        arcade.start_render()
        arcade.draw_circle_filled(self.player_x, self.player_y, 20, arcade.color.BLUE)

    def on_key_press(self, key, modifiers):
        if key == arcade.key.LEFT:
            self.player_x -= 10
        elif key == arcade.key.RIGHT:
            self.player_x += 10

if __name__ == '__main__':
    Game()
    arcade.run()

Проблемы:

  • Объект нереагирующий на границы - уходит за экран. Нужно добавить проверки.
  • Нет обработки столкновений с другими объектами.

Цель: познакомиться с объектно-ориентированным подходом в игровом программировании и библиотекой Arcade.

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

Полный код игры «Змейка» с улучшениями

Добавлены счёт, рестарт по пробелу и фиксация FPS.

Пример
import pygame, random

pygame.init()
W, H = 600, 400
CELL = 20
screen = pygame.display.set_mode((W, H))
clock = pygame.time.Clock()
font = pygame.font.SysFont('arial', 24)

def game_loop():
    snake = [(W//2, H//2)]
    dx, dy = CELL, 0
    food = (random.randrange(0, W, CELL), random.randrange(0, H, CELL))
    score = 0
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    return True
                elif event.key == pygame.K_UP and dy == 0:
                    dx, dy = 0, -CELL
                elif event.key == pygame.K_DOWN and dy == 0:
                    dx, dy = 0, CELL
                elif event.key == pygame.K_LEFT and dx == 0:
                    dx, dy = -CELL, 0
                elif event.key == pygame.K_RIGHT and dx == 0:
                    dx, dy = CELL, 0

        head = (snake[0][0] + dx, snake[0][1] + dy)
        if head in snake or head[0] < 0 or head[0] >= W or head[1] < 0 or head[1] >= H:
            break
        snake.insert(0, head)
        if head == food:
            food = (random.randrange(0, W, CELL), random.randrange(0, H, CELL))
            score += 1
        else:
            snake.pop()

        screen.fill((0,0,0))
        for seg in snake:
            pygame.draw.rect(screen, (0,255,0), (seg[0], seg[1], CELL, CELL))
        pygame.draw.rect(screen, (255,0,0), (food[0], food[1], CELL, CELL))
        text = font.render(f'Score: {score}', True, (255,255,255))
        screen.blit(text, (10,10))
        pygame.display.flip()
        clock.tick(10)
    return True  # restart flag

while game_loop():
    pass
pygame.quit()
Результат: запускается окно с игрой. При столкновении или нажатии пробела игра перезапускается. Счёт отображается вверху слева.

Тетрис на Pygame (упрощённая версия)

Реализуется поворот фигур и удаление заполненных линий.

Пример
import pygame, random

pygame.init()
W, H = 300, 600
CELL = 30
screen = pygame.display.set_mode((W, H))
board = [[0]*10 for _ in range(20)]
figures = [
    [[1,1,1,1]],  # I
    [[1,1],[1,1]], # O
    [[0,1,0],[1,1,1]], # T
    [[1,0,0],[1,1,1]], # L
    [[0,0,1],[1,1,1]]  # J
]

def draw_board():
    for r in range(20):
        for c in range(10):
            if board[r][c]:
                pygame.draw.rect(screen, (0,255,0), (c*CELL, r*CELL, CELL, CELL))

clock = pygame.time.Clock()
fall_time = 0
fall_speed = 500
current = {'shape': random.choice(figures), 'x': 3, 'y': 0}

def collision(shape, x, y):
    for r, row in enumerate(shape):
        for c, val in enumerate(row):
            if val and (y+r >= 20 or x+c < 0 or x+c >= 10 or board[y+r][x+c]):
                return True
    return False

def merge():
    for r, row in enumerate(current['shape']):
        for c, val in enumerate(row):
            if val:
                board[current['y']+r][current['x']+c] = 1

running = True
while running:
    screen.fill((0,0,0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT and not collision(current['shape'], current['x']-1, current['y']):
                current['x'] -= 1
            elif event.key == pygame.K_RIGHT and not collision(current['shape'], current['x']+1, current['y']):
                current['x'] += 1
            elif event.key == pygame.K_UP:
                rotated = list(zip(*current['shape'][::-1]))
                if not collision(rotated, current['x'], current['y']):
                    current['shape'] = rotated
            elif event.key == pygame.K_DOWN:
                if not collision(current['shape'], current['x'], current['y']+1):
                    current['y'] += 1

    fall_time += clock.get_rawtime()
    if fall_time >= fall_speed:
        fall_time = 0
        if not collision(current['shape'], current['x'], current['y']+1):
            current['y'] += 1
        else:
            merge()
            for r in range(19, -1, -1):
                if all(board[r]):
                    del board[r]
                    board.insert(0, [0]*10)
            current = {'shape': random.choice(figures), 'x': 3, 'y': 0}
            if collision(current['shape'], current['x'], current['y']):
                running = False

    draw_board()
    for r, row in enumerate(current['shape']):
        for c, val in enumerate(row):
            if val:
                pygame.draw.rect(screen, (255,255,0), ((current['x']+c)*CELL, (current['y']+r)*CELL, CELL, CELL))
    pygame.display.flip()
    clock.tick(30)

pygame.quit()
Результат: игра Тетрис с базовыми фигурами, автоматическим падением и удалением заполненных линий. Управление стрелками, поворот - вверх.

Игра на выживание с библиотекой Arcade

Летающие объекты, которые нужно избегать.

Пример
import arcade, random

SCREEN_WIDTH, SCREEN_HEIGHT = 600, 400

class Enemy(arcade.SpriteCircle):
    def __init__(self):
        super().__init__(20, arcade.color.RED)
        self.center_x = random.randrange(SCREEN_WIDTH)
        self.center_y = SCREEN_HEIGHT
        self.change_y = -random.uniform(2,5)

    def update(self):
        self.center_y += self.change_y
        if self.top < 0:
            self.center_y = SCREEN_HEIGHT + 20
            self.center_x = random.randrange(SCREEN_WIDTH)

class Game(arcade.Window):
    def __init__(self):
        super().__init__(SCREEN_WIDTH, SCREEN_HEIGHT)
        self.player = arcade.SpriteCircle(30, arcade.color.BLUE)
        self.player.center_x = SCREEN_WIDTH//2
        self.player.center_y = 50
        self.enemies = arcade.SpriteList()
        for _ in range(5):
            self.enemies.append(Enemy())

    def on_draw(self):
        arcade.start_render()
        self.player.draw()
        self.enemies.draw()

    def on_key_press(self, key, modifiers):
        if key == arcade.key.LEFT and self.player.left > 0:
            self.player.center_x -= 20
        elif key == arcade.key.RIGHT and self.player.right < SCREEN_WIDTH:
            self.player.center_x += 20

    def update(self, delta_time):
        self.enemies.update()
        if arcade.check_for_collision_with_list(self.player, self.enemies):
            arcade.close_window()

if __name__ == '__main__':
    Game()
    arcade.run()
Результат: игрок управляет синим кругом, уклоняясь от падающих красных. При столкновении окно закрывается.

Примеры игр на Python - comments

En
игры на python примеры (python)