フェーズ 1 3 つのドット絵を描く

男の子・お化け・お菓子を用意し、画面に出して確かめる

トップページstep1 概要 / フェーズ 1

ゴール

リソースエディタで 8×8 ドットの絵を 3 つ描いて保存し、 それを画面に並べて表示するところまでを確認します。 このフェーズで書くコードは 20 行ほどで、動きはまだありません。

このフェーズで作るファイル step1/ フォルダを作り、その中に次の 2 つを置きます。 フォルダとファイルはご自身で作ってください。
step1/
├── candy_hunt.py       これから書くコード
└── candy_hunt.pyxres   リソースエディタで作る絵
名前は好きなもので構いませんが、以降のページはこの名前で説明します。

1. 考え方

1-1. コードより先に、絵を用意する

step0 では「星を pset で描く」ところから始めて、あとから宇宙船の絵を足しました。 今回は最初に絵を作ります。動かす対象が 3 種類あり、 それぞれ「どんな見た目か」が決まっていないと、位置や大きさの数字を決められないからです。

絵のサイズは 8×8 ドットにします。画面が 160×120 なので、 横に 20 個・縦に 15 個ぶん並ぶ計算です。追いかけっこをするのにちょうどよい大きさで、 step0 の宇宙船(16×16)の 4 分の 1 の面積になります。

1-2. 「どこに置くか」を先に決めておく

ここがこのフェーズの本題です。イメージバンクは 256×256 ドットの 1 枚の大きな紙で、 3 つの絵はその紙の上に並べて描きます。コードから絵を呼び出すときは、 名前ではなく「紙のどこから、何ドットぶん切り出すか」という座標で指定します。

つまり配置がそのままコードの中の数字になります。 あとから絵の位置を動かすと、コードの数字も全部直すことになります。 先に決めておきましょう。

イメージバンク 0 の左上(切り出し位置 u・v の数字が、そのままコードに出てくる) 男の子u = 0お化けu = 8お菓子u = 16空きこの段は空けておく(あとで動きをつけたくなったとき用) 081624320816
3 つを左上から横一列に、8 ドットおきに並べる
切り出し位置大きさ
男の子u = 0, v = 08 × 8
お化けu = 8, v = 08 × 8
お菓子u = 16, v = 08 × 8
なぜ 8 の倍数の位置に置くのか 絵が 8×8 なので、8 ドットおきに置くと切り出し位置がきれいな数字になります。 もし 5 ドットずらして描いてしまうと u = 5u = 13 のような数字を コードに書くことになり、あとで読み返したときに何のことか分からなくなります。 エディタの方眼も 8 ドット単位なので、目でも合わせやすくなります。
2 段目を空けておく理由 今回はまだ使いませんが、あとで「歩いているように見せたい」と思ったときに、 2 コマ目の絵をすぐ下(v = 8)に足せるようにしておきます。 step0 の魚が 2 枚の絵を切り替えて泳いでいたのと同じ仕組みです。

1-3. 背景は黒のままにする

絵の背景(何も描かない部分)は黒=色番号 0 のままにしておきます。 画面に出すとき「この色は透明として扱う」と指定することで、 四角い枠が見えず、キャラクターの形だけが表示されます。step0 の宇宙船と同じやり方です。

2. このフェーズで使う機能

機能役割
pyxel edit ファイル名.pyxresリソースエディタを開く。ファイルが無ければ新規作成される
pyxel.load("ファイル名.pyxres")作った絵をプログラムから読み込む
pyxel.blt(x, y, img, u, v, w, h, colkey)イメージバンクから切り出して画面に貼る
エディタの操作は step0 で扱いました 画面の見方・ペンや塗りつぶしの使い方・保存のしかたは step0 フェーズ 4 にまとめてあります。 操作を忘れたときはそちらを開いてください。ここでは配置だけに集中します。

3. 手順

3-1. エディタを開く

step1 フォルダを作ったら、その中で次を実行します。 ファイルがまだ無いので、新しく作られます。

cd step1
pyxel edit candy_hunt.pyxres

3-2. 3 つの絵を描く

イメージバンク 0 のタブを開き、上の配置図のとおり左上から横一列に描いていきます。 1 つ描くごとに Ctrl + S で保存しておくと安心です。

描くときのコツ 8×8 は思ったより狭く、細かい描き込みはできません。形の輪郭で見分けがつくかを優先します。 迷ったら、目を細めて画面を見てください。3 つが色と大きさだけで区別できるなら成功です。

3-3. 保存して閉じる

Ctrl + S で保存し、Esc でエディタを閉じます。 step1 フォルダに candy_hunt.pyxres ができていれば完了です。

4. コード

描いた絵がちゃんと出るかを確かめます。step1/candy_hunt.py に次を入力してください。

# candy_hunt.py
# step1 フェーズ1:描いた 3 つの絵を並べて表示する

import pyxel

SCREEN_WIDTH = 160
SCREEN_HEIGHT = 120

class App:
    def __init__(self):
        """起動時の設定"""
        pyxel.init(SCREEN_WIDTH, SCREEN_HEIGHT, title="Candy Hunt")
        pyxel.load("candy_hunt.pyxres")
        pyxel.run(self.update, self.draw)

    def update(self):
        """フレーム毎の更新処理(まだ何もしない)"""
        pass

    def draw(self):
        """描画処理"""
        pyxel.cls(pyxel.COLOR_BLACK)

        pyxel.blt(40, 56, 0,  0, 0, 8, 8, pyxel.COLOR_BLACK)    # 男の子
        pyxel.blt(76, 56, 0,  8, 0, 8, 8, pyxel.COLOR_BLACK)    # お化け
        pyxel.blt(112, 56, 0, 16, 0, 8, 8, pyxel.COLOR_BLACK)   # お菓子

App()

5. 実行する

cd step1
python candy_hunt.py

黒い画面の真ん中あたりに、描いた 3 つの絵が横に並んで表示されれば成功です。 まだ何も動きません。

6. コードの解説

pass は「ここは何もしない」の印

Python では、def の中身を空っぽにするとエラーになります。 かといって今の update() には書くことがありません。 そこで 「何もしないことを、はっきり書いておく」ための命令が pass です。

次のフェーズで男の子を動かす処理を書くので、この passすぐに消えます。 「あとで中身が入る場所」の目印だと思ってください。

blt() の 8 個の数字

step0 でも使いましたが、引数が多いので改めて整理します。

pyxel.blt(40, 56, 0,  0, 0, 8, 8, pyxel.COLOR_BLACK)
          ~~~~~~  ~   ~~~~  ~~~~  ~~~~~~~~~~~~~~~~~
          (1)    (2)  (3)   (4)   (5)
意味
(1)40, 56画面のどこに貼るか(左上の座標)
(2)0どのイメージバンクを使うか
(3)0, 0絵のほうのどこから切り出すか(u, v
(4)8, 8切り出す幅と高さ
(5)pyxel.COLOR_BLACK透明として扱う色

3 行の違いは (1) の貼る位置(3) の切り出し位置だけです。 切り出し位置が 0816 と変わっているのが、 さきほど決めた配置に対応しています。

数字がじかに書いてあるのは、今だけです 40568 といった数字がコードに散らばっていますが、 次のフェーズからは SPRITE_SIZE = 8 のように名前を付けた定数に置き換えていきます。 今は「どの数字が何を指しているか」を目で確かめるために、あえてそのまま書いています。

7. うまくいかないときは

症状原因と対処
黒い画面のまま、何も出ない 絵を描いた場所がずれている可能性があります。エディタを開き直して、 左上の角ぴったりから描けているか確かめてください。 また、イメージバンクの 0 番のタブに描けているかも確認します
FileNotFoundError と出る .pyxres が見つかっていません。pyxel.load() の相対パスは 実行するスクリプトの置き場所を基準に解決されるので、 candy_hunt.pycandy_hunt.pyxres同じフォルダにあるか確認してください
絵のまわりに黒い四角が見える 透過色の指定が抜けています。blt() の最後の pyxel.COLOR_BLACK があるか確認してください
絵が途中で切れている 切り出す幅と高さが合っていません。8, 8 になっているか確認します
となりの絵が混ざって表示される 8 ドットの区切りをまたいで描いてしまっています。 はみ出した部分をエディタで消してください

8. 次のフェーズ

絵が用意できました。次は男の子を矢印キーで動かします。 このフェーズで書いた candy_hunt.py がそのまま土台になり、 update()pass が中身に置き換わります。