Гид по технологиям

Сохранение и загрузка прогресса в PyGame

5 min read Разработка игр Обновлено 06 Jan 2026
Сохранение и загрузка в PyGame — руководство
Сохранение и загрузка в PyGame — руководство

Important: модуль pickle небезопасен для загрузки данных из ненадёжных источников — используйте безопасные форматы или дополнительные проверки.

Игрок играет на мониторе, держит контроллер

В современной разработке игр возможность сохранять и загружать прогресс повышает вовлечённость и удобство для игрока. PyGame — популярная библиотека для 2D-игр на Python — даёт инструменты, чтобы реализовать эту функцию относительно просто.

Что даёт система сохранений

  • Позволяет игрокам вернуться к прогрессу позже.
  • Поддерживает несколько сценариев (разные ветки игры, эксперименты).
  • Даёт возможность восстановления после сбоев или тестирования.

Требования и установка

Убедитесь, что на устройстве установлен pip и Python. Для установки PyGame выполните:

pip install pygame

Рекомендуется также иметь базовые библиотеки для работы с файлами: pickle (входит в стандартную библиотеку), os и json для альтернатив.

Простой пример игры (минимальная структура)

Ниже — базовый шаблон игры, где игрок может двигаться влево/вправо. Этот код — отправная точка для добавления сохранения состояния.

import pygame  
  
# Initialize Pygame  
pygame.init()  
  
# Set up the game window  
window_width = 800  
window_height = 600  
window = pygame.display.set_mode((window_width, window_height))  
pygame.display.set_caption("Save and Load System Tutorial")  
  
# Game variables  
player_x = 400  
player_y = 500  
player_speed = 5  
  
# Game loop  
running = True  
while running:  
    for event in pygame.event.get():  
        if event.type == pygame.QUIT:  
            running = False  
  
    keys = pygame.key.get_pressed()  
    if keys[pygame.K_LEFT]:  
        player_x -= player_speed  
    if keys[pygame.K_RIGHT]:  
        player_x += player_speed  
  
    # Clear the screen  
    window.fill((0, 0, 0))  
  
    # Draw the player  
    pygame.draw.rect(window, (255, 255, 255), (player_x, player_y, 50, 50))  
  
    # Update the display  
    pygame.display.flip()  
  
# Quit the game  
pygame.quit()

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

Управление состоянием игры

Один из простых способов — хранить состояние игры в Python-словаре. Это удобно для сериализации и восстановления.

# Game variables  
game_state = {  
    'player_x': 400,  
    'player_y': 500  
}  
  
# Game loop  
running = True  
while running:  
    # ...  
  
    keys = pygame.key.get_pressed()  
    if keys[pygame.K_LEFT]:  
        game_state['player_x'] -= player_speed  
    if keys[pygame.K_RIGHT]:  
        game_state['player_x'] += player_speed  
  
    # ...  
  
    pygame.display.flip()

Сохранение и загрузка: вариант с pickle (простой)

Модуль pickle сериализует объекты Python в байтовую последовательность. Это удобно, но небезопасно для данных из ненадёжных источников.

Создайте файл save-game.py и добавьте функции сохранения и загрузки. Примерный код:

import pickle

# game_state = { 'player_x': player_x, 'player_y': player_y }

# Save game state
def save_game_state(game_state, file_name):
    try:
        with open(file_name, 'wb') as file:
            pickle.dump(game_state, file)
            print("Game state saved successfully!")
    except IOError:
        print("Error: Unable to save game state.")

# Load game state
def load_game_state(file_name):
    try:
        with open(file_name, 'rb') as file:
            game_state = pickle.load(file)
            print("Game state loaded successfully!")
            return game_state
    except (IOError, pickle.UnpicklingError):
        print("Error: Unable to load game state.")
        return None

И пример интеграции в цикл игры (с обработкой нажатий S/L):

# Внутри игрового цикла
if keys[pygame.K_LEFT]:
    player_x -= player_speed
    game_state['player_x'] = player_x
if keys[pygame.K_RIGHT]:
    player_x += player_speed
    game_state['player_x'] = player_x

if keys[pygame.K_s]:
    save_game_state(game_state, 'save_game.pickle')
if keys[pygame.K_l]:
    loaded = load_game_state('save_game.pickle')
    if loaded:
        game_state = loaded
        player_x = game_state.get('player_x', player_x)

Сохранение и загрузка слотов в аркадной игре

Важное замечание о безопасности

  • Никогда не загружайте pickle-файлы из ненадёжных источников — они могут выполнить произвольный код.
  • Для обмена сохранениями между игроками используйте безопасные форматы (JSON, SQLite) или подписывайте/верифицируйте файлы.

Интерфейс для слотов сохранений

Для наглядности можно реализовать слоты сохранений. В примере ниже варианты показываются в консоли, но интерфейс можно отрисовать внутри PyGame.

# Game variables
save_slots = ['Slot 1', 'Slot 2', 'Slot 3']
selected_slot = None

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

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_s:
                # Show save slots
                selected_slot = None
                for i, slot in enumerate(save_slots):
                    print(f"Save Slot {i+1}: {slot}")
                print("Choose a slot to save the game.")

            if event.key == pygame.K_l:
               print("Select Slot:- a - Slot 1 , b - Slot 3, c - Slot 3")
               # Show save slots
               selected_slot = None
                for i, slot in enumerate(save_slots):
                    print(f"Save Slot {i+1}: {slot}")
                print("Choose a slot to load the game.")

            if event.key in [pygame.K_1, pygame.K_2, pygame.K_3]:
                slot_index = event.key - pygame.K_1
                selected_slot = save_slots[slot_index]
                save_game_state(game_state, f"{selected_slot}.pickle")
                print(f"Game saved in {selected_slot}!")

            if event.key in [pygame.K_a, pygame.K_b, pygame.K_c]:
               slot_index = event.key - pygame.K_a
               selected_slot = save_slots[slot_index]
               game_state = load_game_state(f"{selected_slot}.pickle")
               player_x = game_state['player_x']
               print(f"Game loaded from {selected_slot}!")
    # ...

    pygame.display.flip()

Окно PyGame с опциями сохранения и загрузки слотов

No attribution required: Screenshot by Imran

Подтверждение перезаписи и обработка ошибок

Перед перезаписью файла полезно спросить у игрока подтверждение. Пример с os.path.exists:

import os
import pickle

def save_game_state(game_state, file_name):
    if os.path.exists(file_name):
        overwrite = input("Save file already exists. Do you want to overwrite? (y/n): ")
        if overwrite.lower() != 'y':
            print("Save cancelled.")
            return
    try:
        with open(file_name, 'wb') as file:
            pickle.dump(game_state, file)
            print("Game state saved successfully!")
    except IOError:
        print("Error: Unable to save game state.")

def load_game_state(file_name):
    if not os.path.exists(file_name):
        print("Error: Save file does not exist.")
        return None
    try:
        with open(file_name, 'rb') as file:
            game_state = pickle.load(file)
            print("Game state loaded successfully!")
            return game_state
    except (IOError, pickle.UnpicklingError):
        print("Error: Unable to load game state.")
        return None

Лучшие практики

  • Определите структуру состояния и держите её компактной.
  • Создайте отдельную папку для сохранений (например, saves/).
  • Добавьте обработку ошибок и пользовательские сообщения.
  • Реализуйте несколько слотов сохранений.
  • Будьте осторожны с pickle: документируйте версию формата сохранения и обеспечьте миграцию при изменениях структуры.

Альтернативы и когда pickle не подходит

  • JSON — безопаснее для простых структур (числа, строки, списки, словари). Удобен для совместимости между версиями и языками.
  • SQLite — подходит для больших объёмов данных, транзакций и запросов.
  • shelve — простая key-value оболочка над pickle (всё равно использует pickle для значений).

Простой пример сохранения в JSON:

import json

def save_json(game_state, file_name):
    with open(file_name, 'w', encoding='utf-8') as f:
        json.dump(game_state, f, ensure_ascii=False, indent=2)

def load_json(file_name):
    with open(file_name, 'r', encoding='utf-8') as f:
        return json.load(f)

Методология внедрения (мини-план)

  1. Определите набор данных, которые нужно сохранять.
  2. Выберите формат (pickle/JSON/SQLite) и структуру папок.
  3. Реализуйте функции save/load и базовую интеграцию в цикл игры.
  4. Добавьте UI для слотов и подтверждений перезаписи.
  5. Напишите тесты и кейсы при смене версий состояния.
  6. Проведите ручное тестирование и QA.

Критерии приёмки

  • Сохранение в выбранный слот создаёт файл в папке saves/.
  • Загрузка корректно восстанавливает позицию игрока и ключевые поля.
  • При отсутствии файла выводится информативное сообщение.
  • При перезаписи файл не теряется без подтверждения.
  • Формат сохранения документирован и поддерживает простую миграцию.

Тестовые случаи (минимум)

  • Сохранение и загрузка в пустой слот.
  • Попытка загрузки несуществующего файла.
  • Перезапись существующего файла с отменой и с подтверждением.
  • Смена структуры game_state: файл старой версии не ломает игру (обработка отсутствующих ключей).
  • Попытка загрузки испорченного файла (ошибка десериализации).

Контрольный список по ролям

  • Разработчик: реализовать save/load, документировать формат, добавить тесты.
  • QA: проверить сценарии загрузки/сохранения и edge-case’ы.
  • Дизайнер UI: спроектировать понятный интерфейс слотов и подтверждений.
  • Операции/DevOps: выбрать папку для сохранений, обеспечить права доступа и бэкапы при необходимости.

Как выбирать формат: решающее дерево

flowchart TD
  A[Требуется обмен между игроками?] -->|Да| B[JSON или SQLite]
  A -->|Нет| C[Нужна полная структура Python?]
  C -->|Да| D[pickle или shelve]
  C -->|Нет| B
  D --> E[Есть риск загрузки из сети?]
  E -->|Да| B
  E -->|Нет| D

Миграция формата сохранений

  • Храните версию формата в game_state, напр. “save_version”: 1.
  • При изменениях формата пишите функции-миграторы, которые преобразуют старую структуру в новую.

Шаблон имен файлов и структура папок

  • Папка: saves/
  • Имена: saves/slot-1.pickle, saves/slot-2.json
  • Включайте дату/время и версию при автоматическом бэкапе: slot-1-2026-01-01-v1.pickle

Note: при использовании дат используйте ISO-формат YYYY-MM-DDTHH:MM:SS для удобного парсинга.

Приватность и соответствие правилам

  • Если сохранения содержат персональные данные (никнеймы, e‑mail), подумайте о шифровании и соблюдении местных правил приватности.
  • Для европейских игроков учтите принципы минимизации данных и возможность удаления сохранений по запросу.

Итог и рекомендации

Добавление сохранений повышает качество игрового опыта и расширяет дизайн-потенциал. Для простых проектов достаточно JSON или pickle; для публичного обмена и безопасности выбирайте JSON/SQLite и документируйте версию формата. Всегда обрабатывайте ошибки чтения и записывайте понятные сообщения для игрока.

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


Summary:

  • Используйте отдельную папку для сохранений.
  • Документируйте формат и версию сохранений.
  • Предпочитайте JSON/SQLite для обмена и pickle только для доверенных данных.

1-line glossary:

  • Сериализация — преобразование структуры данных в формат, пригодный для записи на диск и последующего восстановления.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

RDP: полный гид по настройке и безопасности
Инфраструктура

RDP: полный гид по настройке и безопасности

Android как клавиатура и трекпад для Windows
Гайды

Android как клавиатура и трекпад для Windows

Советы и приёмы для работы с PDF
Документы

Советы и приёмы для работы с PDF

Calibration в Lightroom Classic: как и когда использовать
Фото

Calibration в Lightroom Classic: как и когда использовать

Отключить Siri Suggestions на iPhone
iOS

Отключить Siri Suggestions на iPhone

Рисование таблиц в Microsoft Word — руководство
Office

Рисование таблиц в Microsoft Word — руководство