セーブデータ ── 冒険の記録をアカウントに残す

RPG の続きから遊びたい。ハイスコアを次回も覚えていてほしい。そんなときは Pyxel 標準の pyxel.user_data_dir() が返すフォルダにファイルを書き込むだけ。Code & Magic が、その中身をあなたのアカウントに自動で保存します。

特別な API もおまじないも要りません。普通の Python の open() と、Pyxel が用意している保存先だけで動きます。

使い方

pyxel.user_data_dir(ベンダー名, アプリ名) は、そのゲーム専用の保存フォルダのパスを返します。そこにファイルを読み書きします。

import pyxel
import json

VENDOR = "Your Name"   # あなた(作者)の名前
APP = "My Game"        # 作品の名前

def _save_path():
    # user_data_dir() は pyxel.init() の後に呼びます
    return pyxel.user_data_dir(VENDOR, APP) + "save.json"

def save_game(state):
    with open(_save_path(), "w") as f:
        json.dump(state, f)

def load_game():
    try:
        with open(_save_path(), "r") as f:
            return json.load(f)
    except (FileNotFoundError, OSError):
        return {"level": 1, "score": 0}   # はじめての冒険

ポイントは2つだけ:

  • pyxel.init() を呼んだ後に user_data_dir() を使う(ゲーム開始時に init するので、プレイ中に保存する分には自然と満たせます)。
  • 初回プレイではまだファイルが無い ので、FileNotFoundError を受け止めて初期値を返す。

これだけで、リロードしても・別の日にまた開いても、続きから遊べます。

ベンダー名・アプリ名は「作品の住所」

VENDORAPP は、その作品を指す 住所 です。一度決めたら変えないでください。変えると保存先フォルダが変わり、前のセーブと別物になってしまいます。自分の名前と作品名を入れておけば十分です。

これは Pyxel 公式の作法そのままなので、同じコードがデスクトップ版 Pyxel でも動きます(その場合はあなたの PC の中に保存されます)。Code & Magic では、それがクラウド(アカウント)に保存される、というだけの違いです。

だれのアカウントに保存される?

  • 自分の魔導書を試遊するとき ── あなたのアカウントに保存されます。
  • クリスタル化して公開した作品を、ほかの冒険者が遊ぶとき ── 遊んだその人のアカウントに、同じ仕組みで保存されます。プレイヤーごとに別々のセーブです。

作者であるあなたのセーブと、遊んでくれた人のセーブが混ざることはありません。

アプリを更新してもセーブは続く

作品を改良して**もう一度クリスタル化(再公開)**しても、セーブデータは引き継がれます。保存先は「作品のもとになった魔導書」に結びついているので、版が新しくなってもプレイヤーは続きから遊べます(VENDOR/APP を変えなければ、です)。

セーブの形(JSON のキーなど)を更新したときは、古いセーブを読んでも壊れないよう、load_game() 側で「無いキーは初期値で補う」ようにしておくと安心です。

サインインしていないと?

サインインしていない人が遊ぶと、セーブはそのブラウザの中に保存されます。同じブラウザなら続きから遊べますが、別の端末には持ち運べません。サインインすると、どの端末からでも同じセーブを使えます。

使うときの約束

  • 中身は JSON でもテキストでも自由です(バイナリも置けます)。読みやすさとアップデートのしやすさから、JSON がおすすめです。
  • 1 ファイルは 64 KB まで、1 作品あたり 16 ファイルまで。進行状況やスコアなら十分な大きさです。大きくなりすぎたら、必要な情報だけに絞りましょう。
  • セーブはあなた(プレイヤー)だけのものです。ほかの人から見えることはありません。

ちょっとした仕組みの話(興味があれば)

ゲームが user_data_dir() のフォルダに書き込んだ瞬間を Code & Magic が検知して保存し、次に開くときには読み込みの前にそっと書き戻しています。だからゲーム側は、Pyxel 標準の open() を使うだけでよいのです。一時的な作業ファイル(保存しなくてよいもの)は、これまでどおり /tmptempfile を使ってください。