Pyxel入門|Pythonでレトロゲームを作る完全ガイド

プログラミング・電子工作






【2026年版】Pyxel入門ガイド|Pythonでつくる、はじめてのレトロゲーム(コピペ可の部品集12選つき)






PYTHON RETRO GAME ENGINE

自分だけのレトロゲームを作ろう
「Pyxel」入門ガイド_

ドット絵と8bitサウンドで動く、小さくて自由なゲーム作りの世界へ。インストールから公開まで、ステージを1つずつクリアする感覚で読み進められます。コピペで動く部品集12本つき。

  • Pyxel 2.9.9 対応
  • 動くコード 21本
  • 旧API→新API 対応表
  • AI共同開発テンプレート
Pyxelで作られたドット絵レトロゲームのイメージ
Pyxelは、少ない色数と小さな画面で「あの頃のゲーム」の雰囲気を再現します

Pyxel(ピクセル)は、プログラミング言語 Python で動く、無料のレトロゲームエンジンです。この記事は「読み終えたら自分のゲームが1本動いている」ことをゴールに、インストール、画面と色、入力、ドット絵、音、タイルマップ、当たり判定、そしてブラウザで遊べる形での公開までを順番に案内します。

今回の改訂では、現行のPyxel 2系の書き方にすべて書き直しました。ネット上の古いサンプルやAIチャットの回答には、今のPyxelではエラーになる書き方(caption= や colkey=-1 など)がよく混ざっています。どこが変わったのかも対応表にまとめたので、古い記事で動かなかった人の答え合わせにも使ってください。

執筆・実機検証:YOFUKASI LAB運営者

理学療法士/Arduino・Pythonを使った医療機器制作・学会発表経験あり

対象バージョンPyxel 2.9.9
必要なものパソコンとPython 3.11以上
読む時間のめやすじっくり40分
最初の1本までSTAGE 03で約10分

急いでいる人の読み方: とにかく動かしたいなら STAGE 02→03→12。古いコードが動かなくて困っているなら STAGE 16 と 18 の対応表へ。部品だけ欲しいなら STAGE 13 へどうぞ。
STAGE 00

Pyxelってなに?

Pyxelは、日本人エンジニアのkitaoさんが個人で開発を続けている、オープンソースのゲームエンジンです。設計図にあたるコードはGitHubで公開されていて、2026年10月時点でスターは1.7万を超えています。Python向けのゲームライブラリとしては世界的に見てもかなり人気のある部類です。

いちばんの特徴は、昔のゲーム機のような「制限」をわざと持たせていることです。使える色は16色、同時に鳴らせる音は4つ。できることが絞られているぶん、覚える命令が少なく、絵が苦手でもそれらしい見た目にまとまります。

🎮 かんたん解説:レトロゲームってどんなゲーム?

画面が四角いドット(マス目)でできていて、色の数も少ない、昔のファミコンやゲームボーイのようなゲームのことです。今のなめらかなゲームとは違う、あたたかい雰囲気があります。

項目 Pyxelの仕様 ひとことで言うと
色 16色のパレット 色えらびで迷わない
絵の置き場 イメージバンク3枚(各256×256ドット) キャラや背景をまとめて保管
マップ タイルマップ8枚(各256×256タイル、1タイル8×8ドット) 広いステージも作れる
音 同時再生4チャンネル、サウンド64個、ミュージック8曲 BGM3音+効果音1音が定番
入力 キーボード・マウス・ゲームパッド スマホではバーチャルパッド
動く場所 Windows・macOS・Linux・Webブラウザ 作ったものをURLで配れる
ライセンス MITライセンス 無料。商用利用もOK

中身(エンジンの心臓部)は高速なRust言語で書かれていて、私たちはそれをPythonから呼び出すだけです。「書くのはやさしいPython、動くのは速いRust」という分業になっているので、初心者向けのわりに動作は軽快です。

SPONSORED


STAGE 01

Pyxelが選ばれる理由と、向かないこと

① 命令が少なく、名前が短い

「画面を消す」はcls、「四角を描く」はrect、「文字を出す」はtext。ほとんどの命令が1行で完結し、引数の並びも「位置→大きさ→色」でそろっています。この記事の最後にあるチートシートに収まる量を覚えれば、ひととおりのゲームが作れます。

② 制限があるから、完成までたどり着ける

ゲーム作りで挫折する一番の原因は「やれることが多すぎて終わらない」ことです。Pyxelは色も音も画面も小さいので、凝りようがありません。その結果、週末だけで1本完成させるという体験がしやすくなります。完成させた経験は、次の1本を作る一番の燃料になります。

③ 絵も音も、1つのコマンドで作れる

ドット絵・マップ・効果音・BGMを作る専用エディタが最初から付いてきます。別のお絵かきソフトや作曲ソフトを探して、書き出し形式で悩む必要がありません(詳しくはSTAGE 09)。

④ ブラウザで動くので、人に見せやすい

作ったゲームはHTMLファイル1つに変換でき、パソコンにもスマホにもPythonを入れてもらわずに遊んでもらえます。「家族や友だちにURLを送るだけ」で済むのは、続けるうえで想像以上に効きます(STAGE 15)。

⑤ お手本が最初から手元にある

インストールすると、ジャンプゲームやシューティング、アクションゲームなど約20本の公式サンプルも一緒に入ります。pyxel copy_examples と打つだけで手元にコピーでき、そのまま改造の材料にできます。

正直に書く「向かないこと」

  • 高解像度のイラストや写真を使うゲーム:16色のドット絵が前提です。フルカラーの絵を見せたいならPygameやGodotが向いています
  • 3Dゲーム:基本は2D専用です
  • 日本語の長い文章を読ませるゲーム:標準フォントは英数字向けです。日本語は別途フォントファイルを読み込めば表示できますが、ひと手間かかります
  • 物理演算やUI部品が欲しい場合:ボタンやスクロールバーのような部品はないので、自分で描いて作ります

逆に言えば、「小さなゲームを自分の手で最後まで作ってみたい」という目的には、これ以上ないほど合っています。


RELATED
同じPythonゲーム制作の実例Arduino×Pygameのジャンプゲーム開発は、生成AIを使うとどこまで速くなるのか。

STAGE 02

はじめよう:インストール

Pyxelのインストール方法を初心者向けに解説。Pythonの準備からpipコマンド、動作確認、公式サンプルの実行までの手順

Pyxelは、PythonのパッケージとしてPyPIで配布されています。まだPythonを入れていない場合はPython公式サイトから先にインストールしましょう。Pyxel 2.9.9はPython 3.11以上が必要なので、古いPythonが入っている人は新しくしてください。Windowsではインストーラの最初の画面にある「Add python.exe to PATH」に必ずチェックを入れてください。ここを飛ばすと、あとで「pipが見つかりません」というエラーで止まります。

OS コマンド メモ
Windows pip install -U pyxel コマンドプロンプトかPowerShellで実行
macOS pip3 install -U pyxel ターミナルで実行
Linux pip3 install -U pyxel 環境によってはSDL2関連のライブラリが別途必要

入ったかどうかは、次の2つで確かめます。バージョン番号と使い方の一覧が表示されれば成功です。

terminal
python -c "import pyxel; print(pyxel.VERSION)"
pyxel

続けて、公式サンプルを手元にコピーしておきましょう。今いるフォルダに pyxel_examples というフォルダができ、中の .py ファイルはすべてそのまま動かせます。

terminal
pyxel copy_examples
cd pyxel_examples
pyxel run 02_jump_game.py

インストール前に雰囲気を知りたい人へ公式リポジトリのトップページにあるサンプルの画像をクリックすると、ジャンプゲームやアクションゲームがブラウザ上でそのまま動きます。まずは遊んでみて、「これを作るのか」というイメージをつかむのがおすすめです。

コードを書くエディタに迷ったら、無料のVisual Studio Codeがおすすめです。Python拡張機能を入れると、pyxel. と打った時点で命令の候補と説明が出るようになります。Pyxelは型情報を同梱しているので、この補完がかなり正確です。venvなどの仮想環境を使う人は、環境を有効にしてからインストールしてください(venvの公式ガイド)。

STAGE 03

最初の一歩:最小プログラムと実行コマンド

Pyxelの基本プログラムの仕組みを解説。initによる画面設定とupdate・draw・runによるゲームループの流れ

まずは「画面を開いて、文字をひとつ表示するだけ」の、いちばん小さなプログラムです。hello_pyxel.py という名前で保存してください。

hello_pyxel.py
import pyxel


def update():
    # 毎フレーム呼ばれる「考える」場所(今回は何もしない)
    pass


def draw():
    # 毎フレーム呼ばれる「描く」場所
    pyxel.cls(0)                              # 画面を色0(黒)で消す
    pyxel.text(54, 56, "Hello, Pyxel!", 7)    # (x, y, 文字, 色)


pyxel.init(160, 120, title="Hello Pyxel")     # 幅, 高さ, タイトル
pyxel.run(update, draw)

ポイント: pyxel.initで画面を用意し、pyxel.run(update, draw)を呼ぶと、そこから先はupdate → drawの順番が、ゲームを閉じるまで自動でくり返されます。終了は Esc キーです。

実行のしかたは3通り

コマンド 動き 使いどころ
python hello_pyxel.py ふつうにPythonとして実行 いつでも使える基本形
pyxel run hello_pyxel.py Pyxelのコマンド経由で実行 pythonコマンドの名前がOSで違っても同じ書き方で済む
pyxel watch . hello_pyxel.py フォルダを見張り、ファイルを保存するたびに自動で再実行 改造しながら試すときの本命

特に pyxel watch は覚えておく価値があります。数字を1つ変えて保存すると、その瞬間にゲームが立ち上がり直すので、「色を変えたらどう見えるか」「速さを変えたらどう感じるか」を数秒単位で試せます。ゲーム作りは調整の回数がそのまま面白さになるので、この往復の速さは大事です。

古い記事との違いウィンドウのタイトルは title="..." で指定します。以前は caption="..." という名前でしたが、今のPyxelでこれを書くと TypeError: init() got an unexpected keyword argument 'caption' で止まります。この記事の旧版にもこの書き方が残っていました。古いサンプルが動かない原因の第1位です。

initで決められること

  • title ……ウィンドウのタイトル(省略すると “Pyxel”)
  • fps ……1秒間に何回 update / draw を回すか(省略すると30)
  • quit_key ……終了キー(省略するとEsc)
  • display_scale ……画面を何倍に拡大して表示するか(省略すると自動)
STAGE 04

画面・座標・16色のひみつ

Pyxelの画面座標と16色パレットの解説図。左上を原点とするX・Y座標、160×120の画面サイズ、色番号の基本

画面の大きさ

画面サイズは pyxel.init(幅, 高さ) で自由に決められます。レトロな雰囲気にしたいなら160×120あたりが扱いやすく、公式サンプルもこの前後のサイズが中心です。ドットが小さくても、ウィンドウは自動で拡大表示されるので見づらくはなりません。

大きな画面も指定できますが、広くするほど描く量が増え、ドット絵1枚あたりの存在感は薄くなります。最初の1本は、参考までに次の数字から選ぶと迷いません。

サイズ 雰囲気 向いているゲーム
128×128 正方形。かなりレトロ パズル、ミニゲーム
160×120 横長。定番 よけゲーム、シューティング、アクション
256×192前後 情報量を増やせる RPG風、文字が多いゲーム

座標:左上が(0, 0)、yは下にいくほど大きい

算数のグラフと違い、yは下向きがプラスです。「上に動かす」は y -= 1。ここを逆に覚えていると、ジャンプしたつもりのキャラが地面にもぐっていきます。初心者がほぼ全員1回はやるミスなので、動きがおかしいときは真っ先に疑ってください。

もうひとつ、絵や四角の位置は「左上の角」で指定します(円だけは中心)。8×8のキャラを画面の右端ぴったりに置くなら、xは 160 - 8 = 152 です。

使える16色

色は名前ではなく0〜15の番号(カラーID)で指定します。pyxel.COLOR_RED のような定数も用意されているので、番号を覚えたくない人はそちらを使えます。

ID 0 · #000000
黒
COLOR_BLACK
ID 1 · #2B335F
紺
COLOR_NAVY
ID 2 · #7E2072
紫
COLOR_PURPLE
ID 3 · #19959C
緑
COLOR_GREEN
ID 4 · #8B4852
茶
COLOR_BROWN
ID 5 · #395C98
濃い青
COLOR_DARK_BLUE
ID 6 · #A9C1FF
水色
COLOR_LIGHT_BLUE
ID 7 · #EEEEEE
白
COLOR_WHITE
ID 8 · #D4186C
赤
COLOR_RED
ID 9 · #D38441
オレンジ
COLOR_ORANGE
ID 10 · #E9C35B
黄
COLOR_YELLOW
ID 11 · #70C6A9
黄緑
COLOR_LIME
ID 12 · #7696DE
青
COLOR_CYAN
ID 13 · #A3A3A3
グレー
COLOR_GRAY
ID 14 · #FF9798
ピンク
COLOR_PINK
ID 15 · #EDC7B0
ピーチ
COLOR_PEACH
旧版からの訂正以前のこの記事では、別のレトロゲーム環境のものに近い色を掲載していました。上の16色が、Pyxel 2.9.9の pyxel.DEFAULT_COLORS から取り出した実際の値です。
🎨 かんたん解説:色えらびのコツ

1つのキャラに使う色は3色までにすると、まとまって見えます。「ベースの色」「影の色」「目立たせる色」の3つです。背景には1(紺)や5(濃い青)のような暗い色、キャラには10(黄)や11(黄緑)のような明るい色を選ぶと、動いているものがはっきり見えます。

パレットの色そのものを入れかえることもできます。たとえば pyxel.colors[1] = 0x102040 と書くと、1番の色だけが別の色になります。夕方のステージだけ全体を赤っぽくする、といった演出に使えます。

STAGE 05

ゲームの心臓部:update と draw

Pyxelのゲームは、次の2つの関数を1秒間に30回くり返すことで動いています。

  1. update() — キー入力のチェックや位置の計算など、「頭で考える」部分
  2. draw() — 考えた結果を画面に映す「見た目」の部分

パラパラ漫画を思い浮かべてください。updateで「次のコマでは、キャラは2ドット右にいる」と決め、drawでそのコマを1枚描く。これを1秒に30枚めくると、動いて見えます。この仕組みはゲームループと呼ばれ、ほぼすべてのゲームエンジンに共通する考え方です。

守ると楽になる3つの約束

  • drawの最初で画面を消す:pyxel.cls(色) を忘れると、前のコマの絵が残って残像だらけになります
  • drawの中で数値を変えない:位置やスコアを変えるのはupdateだけ。こう決めておくと、バグを探す場所が半分になります
  • 時間は「フレーム数」で数える:pyxel.frame_count は起動からのコマ数です。fpsが30なら、30増えるごとに1秒。frame_count % 30 == 0 で「1秒に1回」が作れます

場面(シーン)の切り替え

タイトル画面、プレイ中、ゲームオーバー。ゲームらしく見せるには、この3つの場面を切り替える必要があります。やり方は単純で、「今どの場面か」を覚えておく変数を1つ作り、updateとdrawの中で分岐するだけです。

scene.py(考え方)
TITLE, PLAY, OVER = 0, 1, 2
scene = TITLE

def update():
    global scene
    if scene == TITLE:
        if pyxel.btnp(pyxel.KEY_SPACE):
            scene = PLAY          # スペースで開始
    elif scene == PLAY:
        ...                       # ゲーム本体の処理
    elif scene == OVER:
        if pyxel.btnp(pyxel.KEY_SPACE):
            scene = TITLE         # タイトルに戻る

この形を先に作っておくと、「とりあえず遊べる」状態にいつでも戻れるので、作りかけで放置しにくくなります。完成形はSTAGE 12のよけゲームで確認できます。

関数で書くか、クラスで書くか

短いうちは、この記事の多くのサンプルのように関数と global で十分です。変数が10個を超えてきたら、class App: にまとめて self.x のように持たせると、global を書き並べる必要がなくなって見通しがよくなります。どちらで書いてもPyxelの動きは同じです。

SPONSORED


STAGE 06

操作をつくる:キー・マウス・ゲームパッド

Pyxelのキー入力を比較した図解。btn・btnp・btnrの違いと移動、ジャンプ、ため撃ちへの使い分け

入力を調べる命令は3つだけです。違いは「いつTrueになるか」です。

命令 Trueになるタイミング 向いている操作
pyxel.btn(key) 押している間ずっと 歩く、走る、ためる
pyxel.btnp(key) 押した瞬間の1フレームだけ ジャンプ、決定、弾を1発
pyxel.btnr(key) 離した瞬間の1フレームだけ ため撃ちの発射、ドラッグの終わり

次のコードは、矢印キー(またはゲームパッドの十字キー)で四角を動かし、スペースで色を変えます。

move.py
import pyxel

pyxel.init(160, 120, title="Move")
x, y = 76, 56
color = 11


def update():
    global x, y, color
    # 押している間ずっと反応(移動向き)
    if pyxel.btn(pyxel.KEY_LEFT) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_LEFT):
        x -= 2
    if pyxel.btn(pyxel.KEY_RIGHT) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_RIGHT):
        x += 2
    if pyxel.btn(pyxel.KEY_UP) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_UP):
        y -= 2
    if pyxel.btn(pyxel.KEY_DOWN) or pyxel.btn(pyxel.GAMEPAD1_BUTTON_DPAD_DOWN):
        y += 2
    # 押した瞬間だけ反応(決定・ジャンプ向き)
    if pyxel.btnp(pyxel.KEY_SPACE) or pyxel.btnp(pyxel.GAMEPAD1_BUTTON_A):
        color = pyxel.rndi(8, 15)
    # 画面の外に出ないようにする
    x = max(0, min(x, pyxel.width - 8))
    y = max(0, min(y, pyxel.height - 8))


def draw():
    pyxel.cls(0)
    pyxel.rect(x, y, 8, 8, color)
    pyxel.text(4, 4, "ARROWS: MOVE  SPACE: COLOR", 13)


pyxel.run(update, draw)

押しっぱなしで連射:btnpのholdとrepeat

pyxel.btnp(key, hold=10, repeat=5) と書くと、「押した瞬間に1回、10フレーム押し続けたらその後は5フレームごとに1回」Trueになります。シューティングの連射や、メニューのカーソル送りがこれ1行で作れます。

マウス

  • pyxel.mouse_x / pyxel.mouse_y ……カーソルの位置(ゲーム画面の座標)
  • pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT) ……左クリックした瞬間
  • pyxel.mouse(True) ……カーソルを表示する。初期状態では非表示なので、マウスを使うゲームでは最初に呼びます

ゲームパッドとスマホ対応

ゲームパッドは pyxel.GAMEPAD1_BUTTON_A や pyxel.GAMEPAD1_BUTTON_DPAD_LEFT のように、キーと同じ感覚で調べられます。上のサンプルのように or でキーボードと両方に対応させておくのがおすすめです。というのも、ブラウザ版をスマホで開いたときに表示されるバーチャルパッドは、このゲームパッド入力として届くからです。最初から両対応で書いておけば、あとでスマホ対応に悩まずに済みます。


RELATED
入力をゲームに変える実例リアルタイム握力計測ゲームのコードを徹底解説、応用も簡単|Arduino & Python

STAGE 07

図形とドット絵を描いて動かす

Pyxelでドット絵や効果音・BGMを作る方法。bltによる画像表示とPyxel Editorの基本機能を解説

まずは図形だけで描く

絵を用意しなくても、図形の命令だけでゲームは作れます。試作の段階では四角や丸で十分です。面白さが確かめられてからドット絵に差しかえるほうが、遠回りに見えて早く完成します。

shapes.py
import pyxel

pyxel.init(160, 120, title="Shapes")


def update():
    pass


def draw():
    pyxel.cls(1)
    pyxel.pset(10, 10, 7)                       # 点
    pyxel.line(20, 10, 60, 30, 10)              # 線
    pyxel.rect(10, 40, 30, 20, 8)               # 塗りつぶし四角
    pyxel.rectb(50, 40, 30, 20, 9)              # 枠だけの四角
    pyxel.circ(110, 25, 12, 11)                 # 塗りつぶし円
    pyxel.circb(140, 25, 12, 12)                # 枠だけの円
    pyxel.elli(95, 45, 50, 18, 14)              # だ円
    pyxel.tri(20, 110, 40, 75, 60, 110, 3)      # 三角形
    pyxel.text(75, 95, "x->  y is DOWN", 7)     # 文字


pyxel.run(update, draw)

名前の最後に b が付くもの(rectb、circb)は「border=枠線だけ」という意味です。

イメージバンクという「絵の保管庫」

Pyxelには、絵をしまっておくイメージバンクが3枚あります(0〜2番、それぞれ256×256ドット)。1枚の大きな方眼紙に、キャラも敵もアイテムも並べて描いておき、使うときに必要な部分だけ切り取って画面に貼る、という使い方をします。

絵を入れる方法は3つあります。

  1. Pyxel Editorで描く(STAGE 09)……本格的に作るならこれ
  2. コードの中に文字で書く……下のサンプルの方法。ファイルが1つで済むので、人に渡したりAIに見せたりするときに便利
  3. 画像ファイルを読み込む……pyxel.images[0].load(0, 0, "chara.png")。色は自動的に16色のうち近いものに置きかえられます

絵を画面に貼る:blt

sprite.py
import pyxel

pyxel.init(160, 120, title="Sprite")

# イメージバンク0の (0,0) に、8x8のドット絵を2コマぶん書き込む
# 1文字が1ドット。0〜9とa〜fがカラーID(0は透明として使う)
pyxel.images[0].set(0, 0, [
    "00aaaa00",
    "0aaaaaa0",
    "aa7aa7aa",
    "aa0aa0aa",
    "aaaaaaaa",
    "0a8888a0",
    "00a00a00",
    "0aa00aa0",
])
pyxel.images[0].set(8, 0, [
    "00aaaa00",
    "0aaaaaa0",
    "aa7aa7aa",
    "aa0aa0aa",
    "aaaaaaaa",
    "0a8888a0",
    "0a0000a0",
    "aa0000aa",
])

x = 76
direction = 1  # 1なら右向き、-1なら左向き


def update():
    global x, direction
    if pyxel.btn(pyxel.KEY_LEFT):
        x -= 1
        direction = -1
    if pyxel.btn(pyxel.KEY_RIGHT):
        x += 1
        direction = 1


def draw():
    pyxel.cls(5)
    # 8フレームごとにコマを切り替える(0→8→0→8…)
    u = (pyxel.frame_count // 8 % 2) * 8
    # 幅をマイナスにすると左右反転。最後の0は「色0を透明に」
    pyxel.blt(x, 56, 0, u, 0, 8 * direction, 8, 0)
    # 回転と拡大もできる
    pyxel.blt(120, 30, 0, 0, 0, 8, 8, 0, rotate=pyxel.frame_count * 4, scale=3)


pyxel.run(update, draw)

pyxel.blt(x, y, img, u, v, w, h, colkey) の引数は次のとおりです。

  • x, y ……画面のどこに貼るか(左上の角)
  • img ……イメージバンクの番号(0〜2)
  • u, v ……イメージバンクのどこから切り取るか
  • w, h ……切り取る幅と高さ。マイナスにすると反転(wなら左右、hなら上下)
  • colkey ……透明にする色の番号。透明にしないなら書かずに省略
古い記事との違い「透明色がいらないときは colkey に -1 を入れる」と書かれた記事がありますが、今のPyxelでは OverflowError になります。いらないときは引数ごと省略してください。また、イメージバンクは pyxel.images[0] と書くのが現行の書き方です。

アニメーションの考え方

アニメーションは「何コマ目の絵を出すか」を時間で切り替えるだけです。サンプルの pyxel.frame_count // 8 % 2 は、「8フレームごとに0と1を行ったり来たりする数」を作っています。これに絵の幅(8)を掛ければ、切り取り位置 u が0→8→0→8と切り替わります。コマを4枚に増やしたいなら % 4 にするだけです。

STAGE 08

音を鳴らす

音が1つ鳴るだけで、四角が動いているだけの画面が急に「ゲーム」になります。後回しにされがちですが、効果音は早めに入れるのがおすすめです。

Pyxelの音は3段がまえです。

  • サウンド(0〜63番)……短いフレーズ。効果音や、曲の1パートぶん
  • ミュージック(0〜7番)……サウンドを各チャンネルに並べて1曲にしたもの
  • チャンネル(0〜3番)……同時に鳴らせる4本のレーン。同じチャンネルで新しい音を鳴らすと、前の音は止まります
sound.py
import pyxel

pyxel.init(160, 120, title="Sound")

# sounds[番号].set(音階, 音色, 音量, エフェクト, 速さ)
pyxel.sounds[0].set("c3e3g3c4", "p", "6", "n", 8)        # 決定音
pyxel.sounds[1].set("c3c2c1", "n", "742", "f", 6)        # 爆発音
pyxel.sounds[2].set("e2g2c3e3 g2c3e3g3", "t", "5", "v", 20)  # メロディ
pyxel.sounds[3].set("c1r c1r g0r g0r", "s", "4", "f", 20)    # ベース

# musics[番号].set(チャンネル0の曲順, チャンネル1の曲順, ...)
pyxel.musics[0].set([2], [3])
pyxel.playm(0, loop=True)   # BGMをループ再生


def update():
    if pyxel.btnp(pyxel.KEY_Z):
        pyxel.play(3, 0)     # チャンネル3で決定音
    if pyxel.btnp(pyxel.KEY_X):
        pyxel.play(3, 1)     # チャンネル3で爆発音
    if pyxel.btnp(pyxel.KEY_S):
        pyxel.stop()         # すべて止める


def draw():
    pyxel.cls(1)
    pyxel.text(30, 50, "Z: COIN  X: BOMB  S: STOP", 7)


pyxel.run(update, draw)

setに渡す文字の読み方

引数 書き方 例
音階 ドレミファソラシ=c d e f g a b、後ろにオクターブ0〜4。半音上げは#、下げは-、休みはr "c2e2g2 r"
音色 t=三角波(やわらかい)、s=矩形波(ピコピコ)、p=パルス波(するどい)、n=ノイズ(ザー) "p"
音量 0〜7。数字を並べると1音ずつ変えられる "7642"
エフェクト n=なし、s=スライド、v=ビブラート、f=フェードアウト、h / q=短めのフェードアウト "f"
速さ 数字が小さいほど速い(120で1音=1秒) 8

音色・音量・エフェクトが音階より短いときは、最初からくり返して使われます。"p" と1文字だけ書けば全部パルス波、という意味です。

🔊 かんたん解説:効果音づくりの型

うれしい音は音階を上げていく("c3e3g3c4")。残念な音は下げていく("c3g2e2c2")。爆発や衝突は音色を n(ノイズ)にして音量を下げていく。この3つの型だけで、たいていの効果音は作れます。

チャンネルの割りふり

「BGMにチャンネル0〜2、効果音にチャンネル3」と決めておくのが定番です。効果音をBGMと同じチャンネルで鳴らすと、その瞬間にメロディが途切れてしまいます。

なお、pyxel.play(0, "T120 L8 CDEFG") のように、MMLと呼ばれる楽譜用の書き方を文字列で直接渡すこともできます。作曲に慣れている人や、AIに曲を書いてもらうときはこちらが便利です。作曲が苦手な人向けの自動作曲機能はSTAGE 13の部品12で紹介します。

STAGE 09

Pyxel Editorで創作

Pyxelのタイルマップと当たり判定の仕組み。地形や足場の配置、キャラクターの衝突判定、collideの使い方

絵や音をコードに文字で書くのは、小さいうちは手軽ですが、凝りはじめるとつらくなります。そこで専用エディタの出番です。

terminal
pyxel edit my_game.pyxres

ファイル名を付けて起動すると、そのファイルが無ければ新しく作られ、あれば続きから編集できます。Ctrl+S(Macは Cmd+S)で保存です。

古い記事との違いエディタの起動は pyxel edit です。以前の pyxeleditor というコマンドは古いバージョンのものなので、見つからないと言われたらこちらを試してください。
タブ できること コツ
Image ペン・四角・丸・塗りつぶしで、ドット絵を1マスずつ描く 8×8か16×16のマスに合わせて描くと、あとで切り取り位置が計算しやすい
Tilemap 描いた絵を8×8のタイルとして並べ、ステージを作る 左上のタイル(0,0)は「何もない」用に空けておく
Sound 鍵盤とピアノロールで効果音やメロディを作る 再生しながら直せる。耳で確かめるのが一番早い
Music 作ったサウンドをチャンネルごとに並べて、1曲に組み立てる メロディ・伴奏・ベースの3チャンネルで十分それらしくなる

作ったデータは .pyxres という1つのファイルにまとまります。ゲーム側では、pyxel.init のあとに1行足すだけで読み込めます。

load.py
pyxel.init(160, 120, title="My Game")
pyxel.load("my_game.pyxres")   # 絵・マップ・音がまとめて読み込まれる

読み込んだあとは、これまでと同じ pyxel.blt や pyxel.play がそのまま使えます。つまり、最初はコード内の文字で絵を作り、あとからエディタ製の絵に差しかえても、ゲーム本体のコードはほとんど変わりません。

知っておくと得する録画ショートカット

ゲームの実行中、次のキーで画面を保存できます(Macは Alt の代わりに Option)。SNSやブログに載せるGIFが、追加のソフトなしで作れます。

  • Alt+1 ……スクリーンショットをデスクトップに保存
  • Alt+2 ……録画の開始位置をリセット
  • Alt+3 ……直前の最大10秒をGIFアニメとしてデスクトップに保存
  • Alt+0 ……処理の重さ(fpsや処理時間)を表示
  • Alt+Enter ……フルスクリーン切り替え
STAGE 10

マップでステージ作り

広いステージを作るときは、絵を1枚ずつ置くのではなくタイルマップを使います。8×8ドットの小さな絵(タイル)を、方眼紙のマス目に並べていくイメージです。同じレンガの絵を100回描く代わりに、「このマスはレンガ」という印を100個置くだけなので、データが小さく、直すのも簡単です。

タイルは「何列目・何行目」で指定する

タイルは、イメージバンクを8×8のマスに区切ったときの(列, 行)という2つの数字の組で表します。イメージバンクの左上のマスが (0, 0)、その右隣が (1, 0) です。

  • pyxel.tilemaps[0].pset(x, y, (1, 0)) ……マス(x, y)にタイル(1, 0)を置く
  • pyxel.tilemaps[0].pget(x, y) ……そのマスに何が置いてあるか調べる
  • pyxel.bltm(x, y, tm, u, v, w, h, colkey) ……タイルマップを画面に描く(u, v, w, h はドット単位)

カメラでスクロールさせる

画面より広いステージを見せるには pyxel.camera(x, y) を使います。これを呼ぶと、それ以降の描画がすべて「カメラがその位置にある」ものとしてずれて描かれます。キャラやマップの座標を自分で引き算する必要はありません。スコアなどの表示は、pyxel.camera() で元に戻してから描きます。

壁にぶつかる処理は、命令1つでできる

アクションゲームで一番むずかしいのが「床に立つ」「壁で止まる」処理です。今のPyxelには、これを計算してくれる collide という命令がタイルマップに用意されています。「この四角を(dx, dy)だけ動かしたい。壁はこのタイル」と伝えると、めり込まない範囲に直した移動量を返してくれます。

tilemap.py
import pyxel

pyxel.init(160, 120, title="Tilemap")

# タイルの絵を用意する:イメージバンク0の(8,0)にレンガを描く
pyxel.images[0].set(8, 0, [
    "44444444",
    "49994999",
    "49994999",
    "44444444",
    "99499949",
    "99499949",
    "44444444",
    "22222222",
])
BRICK = (1, 0)   # タイルは「イメージバンクの何マス目か」で指定する
tm = pyxel.tilemaps[0]

# 横40マスぶんのステージをコードで組み立てる
tm.rect(0, 13, 40, 2, BRICK)     # 地面
tm.rect(8, 10, 4, 1, BRICK)      # 浮き足場
tm.rect(16, 8, 5, 1, BRICK)
tm.rect(26, 11, 2, 2, BRICK)     # 段差

px, py, vy = 16, 80, 0.0
on_ground = False


def update():
    global px, py, vy, on_ground
    dx = (pyxel.btn(pyxel.KEY_RIGHT) - pyxel.btn(pyxel.KEY_LEFT)) * 2
    vy = min(vy + 0.5, 6)                     # 重力
    if on_ground and pyxel.btnp(pyxel.KEY_SPACE):
        vy = -6.5                             # ジャンプ
    dy = round(vy)                            # 1ドット単位で動かす
    # 壁にめり込まない移動量を計算してもらう
    mx, my = tm.collide(px, py, 8, 8, dx, dy, [BRICK])
    on_ground = dy > 0 and my < dy            # 下向きの動きが止められた=着地
    if my != dy:
        vy = 1                                # 床や天井に当たったら速度をリセット
    px = max(0, min(px + int(mx), 40 * 8 - 8))
    py += int(my)


def draw():
    pyxel.cls(6)
    cam_x = max(0, min(px - 76, 40 * 8 - pyxel.width))
    pyxel.camera(cam_x, 0)                    # カメラをプレイヤーに追従
    pyxel.bltm(0, 0, 0, 0, 0, 40 * 8, 120, 0)
    pyxel.rect(px, py, 8, 8, 8)
    pyxel.camera()                            # UIはカメラの影響を受けない位置に
    pyxel.text(4, 4, "ARROWS + SPACE", 1)


pyxel.run(update, draw)

60行ほどで、ジャンプして足場に乗れる横スクロールアクションの土台になっています。ステージの形は tm.rect(...) の行を足したり変えたりするだけで作りかえられます。

この記事のコードを検証していて気づいた注意点: collide に渡す移動量は整数にしてから渡すのが安全です。0.5のような1ドット未満の移動はそのまま通ってしまい、床に半ドット沈んで「着地したり浮いたり」をくり返す原因になりました。サンプルで round(vy) としているのはそのためです。
STAGE 11

ぶつかったを判定する

壁との衝突は前のステージの collide に任せられますが、「敵に当たった」「アイテムを取った」のようなキャラどうしの当たり判定は自分で書きます。とはいえ、使う形は2つだけです。

collision.py
def hit_rect(x1, y1, w1, h1, x2, y2, w2, h2):
    """四角どうしが重なっていたら True"""
    return x1 < x2 + w2 and x2 < x1 + w1 and y1 < y2 + h2 and y2 < y1 + h1


def hit_circle(x1, y1, r1, x2, y2, r2):
    """円どうしが重なっていたら True(ルートを使わず二乗で比べる)"""
    dx, dy = x1 - x2, y1 - y2
    return dx * dx + dy * dy < (r1 + r2) ** 2

四角の判定はなぜこれで合っているのか

「重なっている」を直接考えるとややこしいので、逆から考えます。2つの四角が重なっていないのは、「相手が完全に右にある」「完全に左にある」「完全に上にある」「完全に下にある」のどれかのときだけです。この4つがどれも当てはまらなければ、重なっています。hit_rect の4つの条件は、それをそのまま式にしたものです。

どちらを使うか

  • 四角:キャラ、ブロック、弾など、ほとんどの場面はこれで足ります
  • 円:丸い弾や、「半径いくつ以内に入ったら反応する」ような範囲の判定に向いています
🎯 かんたん解説:当たり判定は「見た目より小さく」

8×8のキャラなら、当たり判定は6×6くらいに小さくするのがコツです。角がかすっただけでやられると、遊ぶ人は「今のは当たってない!」と感じます。逆に、アイテムを取る判定は見た目より少し大きくすると、気持ちよく取れます。プレイヤーに不利な判定は小さく、有利な判定は大きく、と覚えてください。

敵や弾が何百個にも増えると、総当たりの判定は重くなってきます。ただ、小さなレトロゲームでそこまで増えることはまれです。最初から工夫しようとせず、重くなってからSTAGE 16の方法で確かめれば十分です。

STAGE 12

実践!よけゲームを作る

ここまでの内容をすべて使って、「左右キーで動き、上から降ってくる敵をよけ続ける」ゲームを完成させます。タイトル画面、ドット絵、効果音、だんだん上がる難易度、ハイスコアまで入って約90行です。

操作← → で移動
開始・再挑戦スペースキー
使っている要素STAGE 05〜08, 11
必要なファイルこれ1つだけ

avoid_game.py
import pyxel

TITLE, PLAY, OVER = 0, 1, 2


class App:
    def __init__(self):
        pyxel.init(160, 120, title="Avoid Game")
        # 自機(8x8)と敵(8x8)のドット絵
        pyxel.images[0].set(0, 0, [
            "000bb000", "00bbbb00", "0bb77bb0", "bbb77bbb",
            "bbbbbbbb", "0b3bb3b0", "0b0000b0", "bb0000bb",
        ])
        pyxel.images[0].set(8, 0, [
            "00888800", "08888880", "88788788", "88088088",
            "88888888", "08822880", "00800800", "08000080",
        ])
        pyxel.sounds[0].set("c3e3g3c4", "p", "5", "n", 6)     # スタート音
        pyxel.sounds[1].set("f2c2f1c1", "n", "7642", "f", 8)  # やられ音
        self.scene = TITLE
        self.hi_score = 0
        self.reset()
        pyxel.run(self.update, self.draw)

    def reset(self):
        self.x = 76
        self.enemies = []   # [x, y, 速さ] のリスト
        self.score = 0

    def update(self):
        if self.scene == PLAY:
            self.update_play()
        elif pyxel.btnp(pyxel.KEY_SPACE):
            # タイトル or ゲームオーバーからスタート
            self.reset()
            self.scene = PLAY
            pyxel.play(0, 0)

    def update_play(self):
        if pyxel.btn(pyxel.KEY_LEFT):
            self.x -= 2
        if pyxel.btn(pyxel.KEY_RIGHT):
            self.x += 2
        self.x = max(0, min(self.x, pyxel.width - 8))

        # スコアが上がるほど敵が出やすく、速くなる
        level = 1 + self.score // 300
        if pyxel.rndi(0, 99) < 2 + level:
            self.enemies.append([pyxel.rndi(0, pyxel.width - 8), -8,
                                 pyxel.rndf(1.0, 1.5 + level * 0.3)])
        for e in self.enemies:
            e[1] += e[2]
        self.enemies = [e for e in self.enemies if e[1] < pyxel.height]

        # 当たり判定は見た目より少し小さく(6x6)すると理不尽さが減る
        for ex, ey, _ in self.enemies:
            if abs(ex - self.x) < 6 and abs(ey - 104) < 6:
                self.hi_score = max(self.hi_score, self.score)
                self.scene = OVER
                pyxel.play(0, 1)
                return
        self.score += 1

    def draw(self):
        pyxel.cls(1)
        # 流れる星(背景)
        for i in range(20):
            pyxel.pset(i * 37 % 160, (i * 53 + pyxel.frame_count * (1 + i % 3)) % 120, 5)
        if self.scene == TITLE:
            pyxel.text(52, 44, "AVOID  GAME", 10)
            if pyxel.frame_count // 15 % 2:
                pyxel.text(44, 70, "PRESS SPACE KEY", 7)
            return
        pyxel.blt(self.x, 104, 0, 0, 0, 8, 8, 0)
        for ex, ey, _ in self.enemies:
            pyxel.blt(ex, ey, 0, 8, 0, 8, 8, 0)
        pyxel.text(4, 4, f"SCORE {self.score}", 7)
        pyxel.text(100, 4, f"HI {self.hi_score}", 10)
        if self.scene == OVER:
            pyxel.text(62, 50, "GAME OVER", 8)
            pyxel.text(40, 64, "SPACE KEY TO RETRY", 7)


App()

ブロックごとに読む

  • __init__:画面を作り、絵と音を登録し、最後に pyxel.run でループ開始。run を呼んだ行から先には進まないので、必ず最後に書きます
  • reset:1プレイぶんの変数を初期値に戻す関数。これを分けておくと、リトライが1行で済みます
  • update:プレイ中だけゲームを進め、それ以外の場面ではスペースキーを待つ。STAGE 05の場面切り替えそのままです
  • update_play:移動→敵を出す→敵を動かす→画面外の敵を消す→当たり判定→スコア加算、の順。消す処理を忘れると、見えない敵が無限に増えて重くなるので注意
  • draw:背景→キャラ→文字の順に描く。あとに描いたものが手前に見えます

ここから自分のゲームにする:改造の順番

写して動かしただけでは、まだ「自分のゲーム」ではありません。次の順番で1つずつ変えていくと、無理なくオリジナルになります。1つ変えるたびに必ず動かして確かめるのがコツです。

  1. 数字を変える:移動の速さ 2、敵の出やすさ 2 + level、難易度が上がる間隔 300。面白さは数字で決まります
  2. 見た目を変える:images[0].set の文字を書きかえて、自分のキャラにする
  3. 音を変える:STAGE 08の型を使って効果音を作りなおす
  4. ルールを1つ足す:取ると得点になるアイテム、3回まで当たれるライフ、など
  5. 演出を足す:やられたときの画面ゆれ(部品07)、爆発の粒(部品05)
  6. 記録を残す:ハイスコアをファイルに保存(部品09)
SPONSORED


STAGE 13

コピペですぐ試せる部品集12選

ゲームでよく使う動きを、それぞれ1ファイルで完結して動く形にまとめました。どれも20〜40行ほどです。そのまま保存して実行でき、気に入ったら自分のゲームに移植してください。すべてPyxel 2.9.9で実行を確認しています。




01

壁ではね返るボール

動き

速度(vx, vy)を毎フレーム足し、壁に着いたら符号を反転させる。動くもの全般の基本形です。

コードを見る(22行)
parts_01.py
import pyxel

pyxel.init(160, 120, title="Bounce")
x, y, vx, vy = 80.0, 60.0, 1.7, 1.3


def update():
    global x, y, vx, vy
    x += vx
    y += vy
    if x < 4 or x > pyxel.width - 4:
        vx = -vx          # 左右の壁で反転
    if y < 4 or y > pyxel.height - 4:
        vy = -vy          # 上下の壁で反転


def draw():
    pyxel.cls(0)
    pyxel.circ(x, y, 4, 10)


pyxel.run(update, draw)

改造ポイント:vx・vy を大きくすると速くなります。ブロック崩しの出発点に。

02

流れる星空の背景

演出

速さの違う点を流すだけで奥行きが生まれます。シューティングの背景の定番。

コードを見る(21行)
parts_02.py
import pyxel

pyxel.init(160, 120, title="Stars")
# [x, y, 速さ] を60個。速い星ほど手前にあるように見える
stars = [[pyxel.rndi(0, 159), pyxel.rndi(0, 119), pyxel.rndf(0.3, 2.5)] for _ in range(60)]


def update():
    for s in stars:
        s[1] += s[2]
        if s[1] > pyxel.height:
            s[0], s[1] = pyxel.rndi(0, 159), 0


def draw():
    pyxel.cls(0)
    for sx, sy, speed in stars:
        pyxel.pset(sx, sy, 7 if speed > 1.8 else 13 if speed > 1 else 5)


pyxel.run(update, draw)

改造ポイント:星の数 60 と色の分け方を変えて、雪や雨にもできます。

03

重力つきジャンプ

動き

「上向きの速度を与える→毎フレーム重力を足す」だけで、放物線のジャンプになります。

コードを見る(25行)
parts_03.py
import pyxel

pyxel.init(160, 120, title="Jump")
GROUND = 96
y, vy = float(GROUND), 0.0


def update():
    global y, vy
    if y >= GROUND and pyxel.btnp(pyxel.KEY_SPACE):
        vy = -6.0             # 上向きの速度を一気に与える
    vy += 0.4                 # 毎フレーム重力で下向きに加速
    y += vy
    if y > GROUND:            # 地面で止める
        y, vy = float(GROUND), 0.0


def draw():
    pyxel.cls(12)
    pyxel.rect(0, GROUND + 8, 160, 16, 3)
    pyxel.rect(76, y, 8, 8, 8)
    pyxel.text(4, 4, "SPACE: JUMP", 1)


pyxel.run(update, draw)

改造ポイント:-6.0(ジャンプ力)と 0.4(重力)の組み合わせで操作感が大きく変わります。

04

弾を撃つ(押しっぱなしで連射)

動き

弾はリストで管理し、画面外に出たら捨てる。btnp の hold / repeat で連射にします。

コードを見る(28行)
parts_04.py
import pyxel

pyxel.init(160, 120, title="Shot")
x = 76
bullets = []   # [x, y]


def update():
    global x, bullets
    x += (pyxel.btn(pyxel.KEY_RIGHT) - pyxel.btn(pyxel.KEY_LEFT)) * 2
    x = max(0, min(x, 152))
    # hold=8, repeat=6:押しっぱなしで6フレームごとに連射
    if pyxel.btnp(pyxel.KEY_SPACE, hold=8, repeat=6):
        bullets.append([x + 3, 100])
    for b in bullets:
        b[1] -= 4
    bullets = [b for b in bullets if b[1] > -4]   # 画面外の弾は捨てる


def draw():
    pyxel.cls(0)
    pyxel.tri(x, 112, x + 4, 104, x + 8, 112, 11)
    for bx, by in bullets:
        pyxel.rect(bx, by, 2, 4, 10)
    pyxel.text(4, 4, f"BULLETS {len(bullets)}", 7)


pyxel.run(update, draw)

改造ポイント:repeat=6 を小さくすると連射が速く。弾を3方向に増やすのも簡単です。

05

クリックで弾けるパーティクル

演出

小さな点をたくさん飛ばして、寿命が尽きたら消す。爆発やキラキラの基本です。

コードを見る(29行)
parts_05.py
import pyxel

pyxel.init(160, 120, title="Particles")
pyxel.mouse(True)     # マウスカーソルを表示
parts = []            # [x, y, vx, vy, 寿命]


def update():
    global parts
    if pyxel.btnp(pyxel.MOUSE_BUTTON_LEFT):
        for _ in range(24):
            parts.append([pyxel.mouse_x, pyxel.mouse_y,
                          pyxel.rndf(-2, 2), pyxel.rndf(-3, 1), 30])
    for p in parts:
        p[0] += p[2]
        p[1] += p[3]
        p[3] += 0.15      # 重力
        p[4] -= 1
    parts = [p for p in parts if p[4] > 0]


def draw():
    pyxel.cls(1)
    for px, py, _, _, life in parts:
        pyxel.pset(px, py, 10 if life > 20 else 9 if life > 10 else 4)
    pyxel.text(4, 4, "CLICK!", 7)


pyxel.run(update, draw)

改造ポイント:個数 24、重力 0.15、色の変わり方を変えて花火や煙に。

06

カウントダウンタイマー

しくみ

frame_count の差で経過時間を測ります。制限時間つきゲームに。

コードを見る(25行)
parts_06.py
import pyxel

FPS = 30
pyxel.init(160, 120, title="Timer", fps=FPS)
LIMIT = 10 * FPS          # 10秒ぶんのフレーム数
start = 0


def update():
    global start
    if pyxel.btnp(pyxel.KEY_SPACE):
        start = pyxel.frame_count     # 押した時点から数え直す


def draw():
    left = max(0, LIMIT - (pyxel.frame_count - start))
    pyxel.cls(0)
    pyxel.text(60, 44, f"TIME {left / FPS:4.1f}", 7 if left else 8)
    pyxel.rect(20, 60, 120 * left // LIMIT, 6, 11)
    pyxel.rectb(19, 59, 122, 8, 7)
    if left == 0:
        pyxel.text(62, 80, "TIME UP!", 8)


pyxel.run(update, draw)

改造ポイント:10 * FPS の10を変えれば制限時間が変わります。

07

画面ゆれ(シェイク)

演出

camera をランダムにずらすだけ。ダメージや着地の手ごたえが一気に増します。

コードを見る(25行)
parts_07.py
import pyxel

pyxel.init(160, 120, title="Shake")
shake = 0


def update():
    global shake
    if pyxel.btnp(pyxel.KEY_SPACE):
        shake = 12                    # 12フレームだけ揺らす
    shake = max(0, shake - 1)


def draw():
    # 揺れが残っている間、描画位置をランダムにずらす
    if shake:
        pyxel.camera(pyxel.rndi(-shake // 3, shake // 3), pyxel.rndi(-shake // 3, shake // 3))
    else:
        pyxel.camera()
    pyxel.cls(5)
    pyxel.rect(40, 40, 80, 40, 9)
    pyxel.text(52, 58, "SPACE: SHAKE", 0)


pyxel.run(update, draw)

改造ポイント:shake = 12 を大きくすると長く強くゆれます。やりすぎると酔うので控えめに。

08

1文字ずつ出るメッセージウィンドウ

しくみ

文字列を「何文字目まで見せるか」で切り取って表示します。RPGや説明画面に。

コードを見る(29行)
parts_08.py
import pyxel

pyxel.init(160, 120, title="Message")
MESSAGES = ["HELLO, ADVENTURER.", "THIS IS A MESSAGE WINDOW.", "PRESS SPACE TO CONTINUE."]
page, shown = 0, 0


def update():
    global page, shown
    text = MESSAGES[page]
    if pyxel.btnp(pyxel.KEY_SPACE):
        if shown < len(text):
            shown = len(text)                       # 途中なら全文表示
        else:
            page, shown = (page + 1) % len(MESSAGES), 0   # 次のページへ
    elif pyxel.frame_count % 2 == 0:
        shown = min(shown + 1, len(text))           # 2フレームに1文字ずつ


def draw():
    pyxel.cls(3)
    pyxel.rect(8, 80, 144, 32, 0)
    pyxel.rectb(8, 80, 144, 32, 7)
    pyxel.text(14, 88, MESSAGES[page][:shown], 7)
    if shown == len(MESSAGES[page]) and pyxel.frame_count // 10 % 2:
        pyxel.text(142, 102, "v", 10)


pyxel.run(update, draw)

改造ポイント:標準フォントは英数字向け。日本語で出したい場合はFAQのフォント読み込みを参照。

09

ハイスコアをファイルに保存

しくみ

user_data_dir で保存場所を用意し、JSONで読み書きします。

コードを見る(34行)
parts_09.py
import json
import os

import pyxel

pyxel.init(160, 120, title="Save")
# OSごとの「アプリ用データ置き場」を作って、その場所を返してくれる
SAVE = os.path.join(pyxel.user_data_dir("yofukasi", "save_demo"), "save.json")

try:
    with open(SAVE) as f:
        best = json.load(f)["best"]
except (OSError, ValueError, KeyError):
    best = 0              # 初回やファイルが壊れているときは0から
count = 0


def update():
    global count, best
    if pyxel.btnp(pyxel.KEY_SPACE):
        count += 1
        if count > best:
            best = count
            with open(SAVE, "w") as f:
                json.dump({"best": best}, f)


def draw():
    pyxel.cls(0)
    pyxel.text(40, 50, f"COUNT {count}   BEST {best}", 7)
    pyxel.text(40, 64, "SPACE: +1 (AUTO SAVE)", 13)


pyxel.run(update, draw)

改造ポイント:保存する中身を増やせば、ステージ進行や設定も残せます(ブラウザ版では挙動が変わります)。

10

プレイヤーを追いかける敵

動き

相手との差を「長さ1の向き」に直してから速さを掛けると、ななめでも同じ速さで追ってきます。

コードを見る(25行)
parts_10.py
import pyxel

pyxel.init(160, 120, title="Chase")
pyxel.mouse(True)
ex, ey = 10.0, 10.0
SPEED = 1.2


def update():
    global ex, ey
    dx, dy = pyxel.mouse_x - ex, pyxel.mouse_y - ey
    dist = pyxel.sqrt(dx * dx + dy * dy)
    if dist > SPEED:
        # 向きだけ取り出して(長さ1にして)一定の速さで近づく
        ex += dx / dist * SPEED
        ey += dy / dist * SPEED


def draw():
    pyxel.cls(0)
    pyxel.circ(ex, ey, 4, 8)
    pyxel.line(ex, ey, pyxel.mouse_x, pyxel.mouse_y, 5)


pyxel.run(update, draw)

改造ポイント:SPEED をプレイヤーより少し遅くするのが、逃げられる緊張感のコツ。

11

ダメージの点滅とフェード

演出

pal で色を一時的に置きかえ、dither で半透明ふうに描きます。

コードを見る(28行)
parts_11.py
import pyxel

pyxel.init(160, 120, title="Flash & Fade")
flash = 0


def update():
    global flash
    if pyxel.btnp(pyxel.KEY_SPACE):
        flash = 10
    flash = max(0, flash - 1)


def draw():
    pyxel.cls(1)
    if flash and flash % 4 < 2:
        pyxel.pal(8, 7)               # 赤(8)を白(7)に置きかえて描く=ダメージ表現
    pyxel.circ(50, 60, 16, 8)
    pyxel.pal()                       # 置きかえを元に戻す(忘れやすい)

    # ディザリングで半透明ふうのフェード(0.0=透明 〜 1.0=不透明)
    pyxel.dither(abs(pyxel.sin(pyxel.frame_count * 3)))
    pyxel.rect(90, 44, 40, 32, 10)
    pyxel.dither(1.0)                 # こちらも元に戻す
    pyxel.text(40, 100, "SPACE: DAMAGE FLASH", 7)


pyxel.run(update, draw)

改造ポイント:pal() と dither(1.0) で元に戻すのを忘れると、画面全体の色が変わります。

12

自動作曲でBGMを付ける

しくみ

gen_bgm は、場面のタイプと乱数の種からBGMを自動で作る命令です。作曲が苦手でも曲が付きます。

コードを見る(31行)
parts_12.py
import pyxel

pyxel.init(160, 120, title="Auto BGM")
NAMES = ["TITLE", "DEPARTURE", "TOWN", "PEACEFUL", "FIELD", "ADVENTURE", "BATTLE", "CRISIS"]
preset, seed = 0, 1


def start():
    # gen_bgm(プリセット0-7, 移調, 楽器構成0-3, 乱数の種, play=Trueで即再生)
    pyxel.gen_bgm(preset, 0, 3, seed, play=True)


def update():
    global preset, seed
    if pyxel.btnp(pyxel.KEY_RIGHT):
        preset = (preset + 1) % 8
        start()
    if pyxel.btnp(pyxel.KEY_SPACE):
        seed += 1                     # 種を変えると別のメロディになる
        start()


def draw():
    pyxel.cls(2)
    pyxel.text(30, 46, f"PRESET {preset}: {NAMES[preset]}", 7)
    pyxel.text(30, 58, f"SEED {seed}", 10)
    pyxel.text(30, 78, "RIGHT: NEXT  SPACE: NEW SEED", 13)


start()
pyxel.run(update, draw)

改造ポイント:気に入った preset と seed の数字をメモしておけば、いつでも同じ曲を再生できます。

STAGE 14

応用:センサーとつないで「体で遊ぶ」ゲームにする

PyxelとArduinoを連携したセンサー操作ゲームの仕組みと、完成したゲームをHTML化してWeb公開する方法

ここからは、YOFUKASI LABらしい寄り道です。PyxelはふつうのPythonプログラムなので、Pythonから読めるものなら何でもゲームの入力にできます。Arduinoにつないだセンサーの値をシリアル通信で受け取れば、握る・押す・傾けるといった体の動きで遊ぶゲームが作れます。

リハビリや運動の場面では、「あと10回」より「あと1面」のほうが続くことがあります。レトロゲームの見た目は情報量が少なく、何をすればいいかが一目でわかるので、こうした用途とも相性のよい組み合わせです。

Arduino側:値を1行ずつ送るだけ

sensor_send.ino
void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(analogRead(A0));  // 0〜1023 を1行ずつ送る
  delay(20);                       // 1秒に約50回
}

Pyxel側:届いた数値をメーターにする

次のコードは、届いた値を横棒のメーターとして表示します。Arduinoがつながっていないときは、自動的にスペースキーで代用するモードになるので、センサーがなくても動きを確かめられます。

serial_meter.py
import pyxel

try:
    import serial                      # pip install pyserial
    ser = serial.Serial("COM3", 9600, timeout=0)   # Macなら "/dev/tty.usbmodem..." など
except Exception:
    ser = None                         # つながらなければキーボードで代用

pyxel.init(160, 120, title="Sensor Meter")
value = 0      # 0〜1023 を想定(ArduinoのanalogReadの範囲)
buf = ""


def update():
    global value, buf
    if ser:
        # 届いているぶんだけ読み、改行ごとに数値として取り出す
        buf += ser.read(ser.in_waiting or 0).decode(errors="ignore")
        lines = buf.split("\n")
        buf = lines.pop()
        for s in lines:
            if s.strip().isdigit():
                value = int(s.strip())
    else:
        # センサーなしでも試せるように、スペースキーで増減させる
        value += 30 if pyxel.btn(pyxel.KEY_SPACE) else -15
    value = max(0, min(value, 1023))


def draw():
    pyxel.cls(0)
    w = value * 140 // 1023
    col = 11 if value < 600 else 10 if value < 900 else 8
    pyxel.rectb(9, 49, 142, 22, 7)
    pyxel.rect(10, 50, w, 20, col)
    pyxel.text(10, 36, f"VALUE {value}", 7)
    pyxel.text(10, 80, "SERIAL" if ser else "KEYBOARD MODE (SPACE)", 13)


pyxel.run(update, draw)

つなぐときのポイント: ①ポート名(COM3 の部分)は自分の環境に合わせる ②timeout=0 にして「待たずに読む」。ここで待ってしまうと、ゲーム全体がカクカクになります ③値は1行に1つ、数字だけを送る。単位や説明の文字を混ぜると、受け取る側の処理が一気にややこしくなります。

このメーターの value を、よけゲームの自機の位置や、ジャンプの強さに置きかえれば、もうセンサー操作のゲームです。なお、シリアル通信を使ったゲームはブラウザ版(STAGE 15)では動かないので、パソコン上で実行してください。こうした用途で人の体に使う場合は、あくまで遊びや動機づけの道具として、無理のない範囲で試してください。


RELATED
Arduino側のコードを基礎から【2026年版】AIを用いたArduinoのコードの書き方|基礎から応用まで全てがわかる初心者の手引き

STAGE 15

完成したら公開しよう

ゲームは、人に遊んでもらって初めて完成します。Pyxelには配布用のコマンドがそろっていて、いちばん手軽なのはHTMLファイル1つにしてしまう方法です。

手順:フォルダにまとめて、2つのコマンドを打つ

まず、ゲームのファイル(main.py と、使っていれば .pyxres)を1つのフォルダに入れます。ここでは my_game フォルダとします。

terminal
pyxel package my_game my_game/main.py
pyxel app2html my_game.pyxapp

  1. 1行目で、フォルダの中身が my_game.pyxapp という1つのファイルにまとまります
  2. 2行目で、それが my_game.html に変換されます
  3. できたHTMLをブラウザで開けば、そのまま遊べます

このHTMLファイルを、itch.ioのようなゲーム投稿サイトや、GitHub Pages、自分のブログのサーバーに置けば、URLを送るだけで遊んでもらえます。スマホで開くと画面にバーチャルパッドが表示されるので、STAGE 06で触れたようにゲームパッド入力にも対応させておきましょう。

配り方 コマンド 相手に必要なもの
HTML(おすすめ) pyxel app2html ゲーム.pyxapp ブラウザとネット接続だけ
Pyxelアプリ pyxel play ゲーム.pyxapp で遊ぶ Pyxelのインストール
実行ファイル pyxel app2exe ゲーム.pyxapp なし(作ったOSと同じOS向け。別途PyInstallerを使います)
ブラウザ版の注意生成されたHTMLは、Pyxel本体をインターネット上から読み込む仕組みです。そのため、遊ぶときにネット接続が必要です。また、パソコン内のファイルへの保存や、シリアル通信のような機能はブラウザ版では使えないか、動きが変わります。公開前に必ず一度、ブラウザで最後まで遊んで確かめてください。

ほかの人の作品を見たい・自分の作品を見てもらいたいときは、公式のユーザー作品集がおすすめです。世界中のユーザーが作った作品が200本以上紹介されていて、「Pyxelでここまでできるのか」という目標が見つかります。

STAGE 16

うまく動かない時は

エラーは「どこが違うか」を教えてくれる手がかりです。赤い文字が出たら、いちばん下の1行を読んでください。そこに原因の要約が書いてあります。Pyxelでよく出会うものを表にしました。

症状・エラー よくある原因 直し方
unexpected keyword argument 'caption' 古い書き方 title= に変える
OverflowError(bltの行) colkey に -1 を渡している 引数を省略する
インストールで「対応するバージョンがない」と出る Pythonが古い Python 3.11以上を入れなおす
ModuleNotFoundError: No module named 'pyxel' 別のPythonに入れてしまった/仮想環境が有効でない python -m pip install pyxel で、実行に使うPythonへ入れる
pyxel コマンドが見つからない PATHが通っていない python -m pyxel run ファイル.py を試す
ウィンドウが一瞬で閉じる/真っ黒 pyxel.run を呼んでいない、またはdrawで何も描いていない 最後の行に pyxel.run(update, draw) があるか確認
絵が残像のように残る drawの最初で画面を消していない pyxel.cls(0) を先頭に
UnboundLocalError 関数の中で外の変数を書きかえている 関数の先頭に global 変数名 を書く。またはクラスにまとめる
キャラが上下逆に動く yの向きの勘違い 上へは y -= 、下へは y +=
絵のまわりに四角い色がつく 透明色を指定していない bltの最後に背景に使った色の番号を渡す
BGMが効果音で途切れる 同じチャンネルで鳴らしている 効果音はチャンネル3に分ける
日本語が表示されない 標準フォントは英数字向け ローマ字にするか、フォントファイルを読み込む(FAQ参照)
だんだん重くなる 画面外に出た弾や敵を消していない リストから取りのぞく処理を入れる

原因をしぼり込む4つの手

  1. 画面に数字を出す:pyxel.text(0, 0, f"{x} {y}", 7) をdrawに1行足して、変数の中身を見ながら遊ぶ。動いているゲームでは print より読みやすい方法です
  2. ゆっくり動かす:pyxel.init(..., fps=5) にすると、1コマずつ目で追えます。当たり判定のズレを見つけるのに最適です
  3. 当たり判定を見える化する:判定に使っている四角を pyxel.rectb で描いてみる。「思っていた場所と違った」がすぐわかります
  4. 重さを測る:実行中に Alt+0 で、updateとdrawにかかっている時間が表示されます。勘で直す前に、どちらが重いのかを見ましょう

それでも解決しないときは、エラーメッセージの全文と該当するコードをそのままAIチャットに貼るのが早道です。貼り方のコツはSTAGE 18で紹介します。

STAGE 17

似ているツールと比較

ゲームを作る道具は他にもたくさんあります。優劣ではなく、「何を作りたいか」で選ぶための比較です。

ツール 言語 特徴 向いている人
Pyxel Python 16色・4音の制限つき。絵と音のエディタ付き。無料。ブラウザ出力あり Pythonで小さなゲームを最後まで作りたい
Pygame Python 制限なしの定番。フルカラー画像や好きなフォントが使える。素材づくりは別ソフトで 見た目や規模を自由に決めたい
PICO-8 Lua 128×128・16色の仮想ゲーム機。有料。コード量にも上限があり、制限はPyxelより厳しめ 制限そのものを楽しみたい
TIC-80 Luaなど PICO-8に近い無料の仮想ゲーム機。240×136・16色 無料で仮想ゲーム機を試したい
LÖVE Lua 制限の少ない2Dゲーム向けフレームワーク Luaで本格的に2Dを作りたい
Scratch ブロック 文字を打たずに作れる。ブラウザだけで完結 プログラミング自体が初めての小学生

PyxelとPygame、迷ったら

迷ったときのおすすめは、「1本目はPyxel、作りたいものがPyxelの枠に収まらなくなったらPygame」という順番です。ゲームループ、当たり判定、場面の切り替えといった考え方はどちらも同じなので、Pyxelで身につけたことはPygameでもそのまま使えます。逆に、Pygameから始めると「画像を用意する」「フォントを選ぶ」「画面サイズを決める」といった、ゲームの面白さとは別の決めごとが最初に並び、そこで手が止まりがちです。

Scratchを卒業して文字のプログラミングに進みたい、というお子さんにも、Pyxelはちょうどよい次の一歩になります。Pygameでの実装イメージを先に見ておきたい人は、以下の記事もあわせてどうぞ。


RELATED
Pygameでの表現の幅を知る【コピペ可】色(カラー)、デザインの変化を自由自在に操る|VRレンズ風デジタルアート、Python、Pygame

STAGE 18

AIと一緒に作ろう

ChatGPTやClaudeのようなAIチャットは、Pyxelでのゲーム作りの頼れる相棒になります。Pyxelは命令が少なく、1ファイルで完結しやすいので、AIとのやり取りに向いています。ただし、Pyxel特有の落とし穴が1つあります。

落とし穴:AIは古いPyxelの書き方を混ぜてくることがある

Pyxelはバージョン1から2にかけて命令の名前がいくつか変わりました。ネット上には古い書き方のサンプルが今もたくさん残っているため、AIの回答にもそれが混ざることがあります。もらったコードがエラーになったら、まず次の表と見比べてください。

古い書き方(今は動かない・非推奨) 今の書き方
pyxel.init(160, 120, caption="...") pyxel.init(160, 120, title="...")
pyxel.init(..., scale=4) pyxel.init(..., display_scale=4)
pyxel.image(0) pyxel.images[0]
pyxel.tilemap(0) / pyxel.sound(0) / pyxel.music(0) pyxel.tilemaps[0] / pyxel.sounds[0] / pyxel.musics[0]
pyxel.blt(..., colkey=-1) colkey を省略する
タイルを1つの数字で指定(pset(x, y, 3)) (列, 行) の組で指定(pset(x, y, (3, 0)))
pyxeleditor コマンド pyxel edit
pyxelpackager コマンド pyxel package と pyxel app2exe / app2html

最初に貼る「前提プロンプト」

この問題は、会話の最初に前提を伝えておくだけでかなり防げます。下の文章をコピーして、最初のメッセージとして送ってください。

最初に送る前提プロンプト
これからPythonのゲームエンジン「Pyxel」でゲームを作ります。
次の条件を守ってコードを書いてください。

・Pyxel 2系(2.9)の書き方を使う
  - pyxel.init の引数は title(caption は使わない)
  - 画像は pyxel.images[0]、音は pyxel.sounds[0] の書き方
  - blt の colkey に -1 は使わない(不要なら省略)
  - タイルは (列, 行) のタプルで指定
・1つの .py ファイルで完結させ、外部の画像や音のファイルは使わない
  (絵は pyxel.images[0].set、音は pyxel.sounds[0].set で作る)
・画面サイズは 160x120
・コードには日本語のコメントを付ける
・私はプログラミング初心者です。変更したときは、
  どこをなぜ変えたかを短く説明してください

場面別のお願いテンプレート

機能を足す

「次のコードに、取ると100点入るコインが上から降ってくる機能を足してください。今ある変数名や書き方はなるべく変えず、変更した部分がわかるようにしてください。(コード全文を貼る)」

エラーを直す

「次のコードを実行したら、このエラーが出ました。原因と直し方を教えてください。Pyxelのバージョンは2.9.9です。(エラー全文とコード全文を貼る)」

動きがおかしい

「エラーは出ませんが、ジャンプしたあと地面をすり抜けて落ちていきます。期待している動きは地面の上で止まることです。原因として考えられることを可能性の高い順に挙げてください。」

理解する

「このコードの update 関数を、小学生にもわかるように1行ずつ説明してください。そのあと、私が理解できたか確かめるクイズを3問出してください。」

ドット絵を作る

「Pyxelの images[0].set で使える形式で、8×8ドットのスライムの絵を作ってください。使う色は3色まで、0番は透明として使います。」

企画を練る

「160×120の画面、操作は左右とボタン1つだけ、という条件で、30秒で面白さが伝わるミニゲームの案を5つ出してください。それぞれ作る難しさも教えてください。」

うまくいく進め方:小さく頼んで、毎回動かす

  • 一度に頼むのは1機能だけ:「敵とアイテムとボスとセーブ機能」をまとめて頼むと、動かなかったときにどこが原因かわからなくなります
  • 動いたら保存してから次へ:game_v1.py、game_v2.py と名前を変えて残しておくと、壊れたときにすぐ戻れます
  • コードは毎回全文を貼る:AIは、あなたが手元で直した内容を知りません。食い違いを防ぐ一番確実な方法です
  • 「期待した動き」と「実際の動き」をセットで伝える:「動きません」だけでは、AIも人間も答えようがありません
🤖 かんたん解説:AIが書いたコードは、そのまま100点?

AIはとても頼りになりますが、まちがえることもあります。もらったコードは必ず自分で動かして、思った通りかたしかめましょう。そして、数字を1つ、自分の手で変えてみることをおすすめします。速さの 2 を 5 にしたら何が起きるか。それを自分で確かめた瞬間に、そのコードは「AIが書いたもの」から「自分がわかっているもの」に変わります。


RELATED
AIの使い分けをもっと詳しく【実務比較】ChatGPTとClaudeはどう使い分ける?記事作成・画像制作・調査で検証

STAGE 19

Pyxelでよく使う命令チートシート

開発中に手元で見返せるよう、よく使う命令を1つの表にまとめました。ブックマークしておくと便利です。

分類 命令 役割
準備 pyxel.init(w, h, title="", fps=30) 画面を作る
準備 pyxel.run(update, draw) ゲームループを開始(最後に呼ぶ)
準備 pyxel.load("file.pyxres") エディタで作った素材を読み込む
情報 pyxel.width / pyxel.height 画面の幅と高さ
情報 pyxel.frame_count 起動からのフレーム数
描画 pyxel.cls(col) 画面を1色で消す
描画 pyxel.pset(x, y, col) 点を打つ
描画 pyxel.line(x1, y1, x2, y2, col) 線を引く
描画 pyxel.rect / rectb(x, y, w, h, col) 四角(塗り/枠)
描画 pyxel.circ / circb(x, y, r, col) 円(塗り/枠)。x, yは中心
描画 pyxel.elli / ellib(x, y, w, h, col) だ円(塗り/枠)
描画 pyxel.tri / trib(x1, y1, x2, y2, x3, y3, col) 三角形(塗り/枠)
描画 pyxel.text(x, y, s, col) 文字(1文字は幅4×高さ6ドット)
描画 pyxel.blt(x, y, img, u, v, w, h, colkey) イメージバンクの絵を貼る
描画 pyxel.bltm(x, y, tm, u, v, w, h, colkey) タイルマップを描く
描画 pyxel.camera(x, y) / pyxel.camera() 描画位置をずらす/戻す
描画 pyxel.pal(c1, c2) / pyxel.pal() 色を置きかえて描く/戻す
描画 pyxel.dither(alpha) 半透明ふうに描く(0.0〜1.0)
入力 pyxel.btn(key) 押している間 True
入力 pyxel.btnp(key, hold, repeat) 押した瞬間 True(連射も可)
入力 pyxel.btnr(key) 離した瞬間 True
入力 pyxel.mouse_x / pyxel.mouse_y マウスの位置
入力 pyxel.mouse(True) マウスカーソルを表示
音 pyxel.sounds[n].set(notes, tones, volumes, effects, speed) サウンドを作る
音 pyxel.play(ch, snd, loop=False) サウンドを鳴らす
音 pyxel.playm(msc, loop=False) ミュージックを鳴らす
音 pyxel.stop() / pyxel.stop(ch) 全部止める/チャンネルを止める
素材 pyxel.images[n].set(x, y, [文字列...]) コードでドット絵を作る
素材 pyxel.tilemaps[n].pset(x, y, (tx, ty)) タイルを置く
素材 pyxel.tilemaps[n].collide(x, y, w, h, dx, dy, walls) 壁にめり込まない移動量を得る
数学 pyxel.rndi(a, b) / pyxel.rndf(a, b) a以上b以下の乱数(整数/小数)
数学 pyxel.sin(deg) / pyxel.cos(deg) 三角関数。角度は度(0〜360)
数学 pyxel.clamp(x, lo, hi) xをlo〜hiの範囲におさめる

ここに載せていない命令や細かい仕様は、公式ユーザーガイドで確認できます。VS Codeなら、命令にマウスを乗せるだけで説明が表示されるので、そちらも活用してください。

STAGE 20

よくある質問

Pyxelはプログラミング未経験でも使えますか?

Python自体が初めての場合は、変数・if文・for文・関数の4つを先に軽くさわっておくと理解がスムーズです。Pyxelの命令自体はとてもシンプルなので、入門を一つ終えた程度の知識があれば、この記事の内容には十分ついていけます。わからない行はAIチャットに「この行を説明して」と聞きながら進めるのもおすすめです。

作ったゲームをスマホやブラウザで遊べるようにできますか?

できます。pyxel package でアプリ化し、pyxel app2html でHTMLファイルに変換すれば、ブラウザでそのまま遊べます。スマホではバーチャルパッドが表示されるので、ゲームパッド入力にも対応させておきましょう。手順はSTAGE 15を参照してください。

PyxelとPygame、結局どちらを選べばいいですか?

手早く1本完成させたい、レトロな見た目を楽しみたいならPyxel、解像度や色数の制限なく自由に作りたいならPygameが向いています。ゲームループや当たり判定の考え方は共通なので、Pyxelで覚えたことはPygameでも活かせます。STAGE 17の比較表もあわせてどうぞ。

無料で商用利用してもよいのでしょうか?

PyxelはMITライセンスで公開されており、商用・非商用を問わず無料で利用できます。ただし、ゲームに使う絵や音楽に第三者の素材を使う場合は、その素材側のライセンスを別途確認してください。

古い記事やAIが出したコードがエラーになります。なぜですか?

Pyxelはバージョン1から2にかけて、caption→title、pyxel.image(0)→pyxel.images[0] など、いくつかの書き方が変わりました。古い書き方のままだとエラーになることがあります。STAGE 18の対応表で、該当する箇所を書きかえてみてください。

日本語の文字を表示するにはどうすればいいですか?

標準のフォントは英数字と記号向けです。日本語を表示したい場合は、日本語のフォントファイル(BDF形式など)を用意して font = pyxel.Font("ファイル名.bdf") で読み込み、pyxel.text(x, y, "こんにちは", 7, font) のように最後の引数に渡します。フォントファイルにも利用条件があるので、配布するときはライセンスを確認してください。

自分で描いた画像や、持っている音声ファイルは使えますか?

画像は pyxel.images[0].load(0, 0, "ファイル名.png") で読み込めます。色はPyxelの16色のうち近いものに自動で置きかえられるので、写真のような画像は大きく印象が変わります。音についても、サウンドにWAVやOGGファイルを読み込ませる機能があります。

画面がカクついたり重くなったりするのはなぜですか?

一番多い原因は、画面外に出た弾や敵をリストから消しておらず、見えないところで数が増え続けていることです。次に多いのが、数が多い状態での総当たりの当たり判定です。実行中に Alt+0 を押すと処理時間が表示されるので、updateとdrawのどちらが重いかをまず確かめましょう。

何歳くらいから使えますか?

キーボードで英数字が打てて、Scratchなどで「順番に実行する」「もし〜なら」「くり返す」の感覚をつかんでいれば、小学校高学年くらいから大人と一緒に楽しめます。最初はこの記事のコードの数字を変えて遊ぶところから始めるのがおすすめです。

🏆 STAGE CLEAR

Pyxelは、Pythonの知識だけで、あの頃のゲームの手ざわりを再現できる、小さくて自由なゲームエンジンです。update と draw の2つを用意すればゲームが動き出し、絵も音もマップも同じ道具の中で作れて、最後はURL1つで人に遊んでもらえます。

制限が多いことは弱点ではなく、完成までたどり着くための近道です。まずは今日のよけゲームの数字を1つ変えるところから始めてください。

おすすめの進み方

  1. 1日目:インストールして、STAGE 03と12のコードを動かす
  2. 2日目:よけゲームの数字・絵・音を変えて、自分のゲームにする
  3. 3日目:STAGE 13の部品を2つ移植する(画面ゆれとセーブがおすすめ)
  4. 1週間後:HTMLにして、誰か1人に遊んでもらう
  5. その次:タイルマップのサンプルを土台に、アクションゲームに挑戦する

次に挑戦したい応用アイデア

  • アクションゲーム:STAGE 10の土台に、敵とゴールを足す
  • シューティング:部品04の弾と、よけゲームの敵を組み合わせる
  • 落ち物パズル:タイルマップを盤面として使う
  • ミニRPG:タイルマップ+部品08のメッセージウィンドウ
  • 体で遊ぶゲーム:STAGE 14のセンサー入力で、握力や傾きを操作にする

AIという相棒を借りつつ、自分だけのドット絵と音で、世界に1つのレトロゲームを育てていきましょう。



関連記事

特集記事

コメント

この記事へのコメントはありません。

TOP
CLOSE