レトロゲームエンジンpyxelをつかったプログラミング教育 

# はじめに

大阪大学の1年生を対象に、4月から8月まで、[pyxel](https://github.com/kitao/pyxel)をつかってプログラミングの授業を行いました。pyxelはpython用のレトロゲームエンジンです。プログラムに興味をもってもらうことを目的として、自分でゲームをつくり、最後にどんなゲームを作ったかプレゼンを行う、という授業をしました。

受講した学生は15名ほどで、全員プログラミングは未経験でした。所属の学部は様々でしたが、文系の学部の学生はかなり少なかったです。

# 計算機環境
大学のシンクライアント上のwindowsで、基本的にIDLEだけを使ってプログラミングしました。ただし、途中から自分のノートPCを持ってくる学生もかなりいました。

pythonのバージョンは3.6です。pyxelのバージョンは1.0だったと思います。

# 授業のスケジュール

科目全体で、90分授業を全15週実施します。

## 1～4週
pyxelは使わないで、簡単なpythonプログラムを触りながら、if, while, forなどの基本的なコンストラクトと、関数、タプル、リスト、乱数について、ざっと見ていきました。具体的なプログラム例を示して、それを自分で改良しながらコンセプトを学んでもらいました。まだこの段階ではテキストだけですが、ゲーム風のプログラムを例に使いました。

たとえば、第2週の課題は、以下のプログラムを変更して、どちらかが3勝するまで「じゃんけん」を繰り返すようにする、というものにしました。

```python
import random
jan = ('グー', 'チョキ', 'パー')

while True:
    a = random.randint(0, 2)
    b = ""
    while b != '0' and b != '1' and b != '2':
        print(0, jan[0], 1, jan[1], 2, jan[2], '?')
        b = input()
    b = int(b)  # 入力を整数に変換
    print('こちら', jan[b])
    print('あいて', jan[a])

    if a == b:
        print('あいこ')
    elif (a == 0 and b == 1) or (a == 1 and b == 2) or (a == 2 and b == 0):
        print('まけ :-(')
        break
    else:
        print('かち :-)')
        break
```

## 5, 6週
pyxelを導入しました。pyxel付属のサンプルのゲームプログラムについて、コードを少し改変してみる、あるいは、pyxelについてくるpyxeleditorを使ってキャラクターの絵を書き換えてみる、といったことをしました。まずは、pyxelのプログラムがどんなものか、体験してもらうことを意図しています。

## 7～13週
7週をつかって最終的なプログラムを作っていきました。まず、どのようなゲームにするか検討してもらい、それからプログラミングをしてもらいました。ただ、スクラッチからつくるのは難しいので、ネット上のプログラム等を参考にするとよいと指示しました。構想しているゲーム内容にあった適当なサンプルがない場合は、私の方で基本的な部分をつくって提供しました。

今回の進め方では学習はほとんど学生の自主性に任せており、独力でかなり作りこむ学生もいれば、思うように進まない学生もいるといった状況になります。後者の場合については、一人一人制作中のプログラムを私が見てバグをとったり、具体的に書くべきコードを指示して、13週目までに動くプログラムができあがるようにしました。

![pyxel-191013-003454.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348779/d0c8d6d2-5f00-a6da-bb1c-81661ebb77cb.gif)


## 14, 15週
プレゼン用のパワーポイント資料作成を14週目に行い、15週は各自4, 5分くらいで作成したゲームについてプレゼンしました。

# 反省点など

## ゲームループ

ゲームループの概念になじむのが難しかったと思います。つまり、一瞬一瞬におけるキャラクターの処理をループすることでゲームが成り立つわけですが、ループ自体はエンジン側で用意してあって、プログラミングするのはループの中身だけになります。これが、普通の繰り返し処理のプログラムを見たあとだと、簡単には理解できないようです。

たとえば、上の「じゃんけん」プログラムなどでは、入力を待って、入力が行われたら処理をして、また次の入力を待つ、という動作になりますが、これがゲームループの場合だと、入力が来なくてもすぐ次のループの繰り返しに進まなければなりません。

### 改善策

ゲームループについて、しっかり説明すべきでした。
また、テキストベースのプログラムの後にすぐpyxelのゲームに移行するとギャップが大きかったので、途中にゲームではないがグラフィックスをつかったプログラムを扱うことができればよかったです。なお、pyxelの今のバージョン(1.2以上)では、ゲームループなしでグラフィックスを利用することができるようになっています。たとえば、円をランダムに描写するプログラムは、以下のように書けます。

```python
import random
import pyxel

pyxel.init(200, 200)
pyxel.cls(0)
for i in range(0, 50):
    pyxel.circ(random.randint(0, 200),
               random.randint(0, 200),
               random.randint(0, 25),
               random.randint(1, 15))
pyxel.show()
```


![circles.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348779/43223f6b-1893-c6cf-6296-38d62160443a.png)

## キャラクター画像

自前のPCを使っていた学生は問題なかったのですが、用意した環境だとpyxeleditorが重くてあまり自由に作画できません。
そこで、他のツールでpngファイルをつくって読み込むことを考えたのですが、ビット深度の関係なのかうまくいきませんでした。
結局、pyxel.image().set()をつかって、ドット絵の情報をハードコードしておいてイメージバンクに書き込む方法を提示しました。

```python
# 8x8のドット絵を描く
# 0からfまでで15色を指定
plane_dot = ["0006d000",
             "0006d000",
             "00688660",
             "065586d0",
             "d6c656dd",
             "d6c65ddd",
             "02665d20"]

# 上で記述した画像を，イメージバンクにコピー
# ここでは，画像の左上を，イメージバンクの座標(0,0)にあわせている
pyxel.image(0).set(0, 0, plane_dot)
```
![plain.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348779/7156fa17-18a1-7d5f-b844-9f53ffab8ba9.png)


### 改善策

pyxelがバージョンアップして、pyxeleditorも速くなったと思います。
また、pngファイルをつくる方法については、pyxelのサイトに以下のように説明がありました。、

> PyxelはPICO-8と同じパレットを使用しているため、Pyxel向け配色のpngファイルを作成する場合は、AsepriteをPICO-8パレット設定にして使用するのがおすすめです。

## クラス

クラスについては説明しなかったのですが、失敗でした。

* クラスなしででやりくりしようとすると、global変数が必要になりがち。
* ネットに公開されているプログラムを参考にしようとすると、はほぼ確実にクラスをつかっているので、結局避けて通れない。

### 改善策

クラスの基本的な考え方はちゃんと教えた方が良かったです。ただ、継承は省いてよいと思います。

## その他

* リストは必要なので教える必要があります。タプル、辞書、集合は、省いてよいと思います。
* while文は、ゲームではどうしても使わないといけない状況はあまりないので、簡単な説明で済ませてもよさそうです。
* ネットで公開されているコードを学生がコピペしたときインデントがおかしくなって、プログラムが動かないといったことがよくありました。ブロックを示すのにインデントを使うpython特有の問題です。IDLEより高機能なエディタを使ったら避けられたかもしれません。

# おわりに

python + pyxel は、ビギナーがプログラミングを体験するのに理想的な組み合わせです。pyxelのバージョンが1.2になって少しあった問題が解決されており、さらに魅力を増していると思います。