Processing風のPythonライブラリ（Python Mode for Processing に変わるCPythonのライブラリ)

# 概要
Processing は、導入が簡単でグラフィカルなアプリを簡単に作れるなど、初学者のプログラミング習得に向いた環境であるが、文法などはJavaベースである。今時のAIやデータサイエンスなどと組み合わせるためのPythonでやりたい。

ProcessingをPython言語で書くためのPython mode for ProcessingもあるもののJythonベースであるためPython2系となりPython3系は使えない。また外部ライブラリもProcessing専用のライブラリを使う必要があるが、最新のProcessing4用のPython Modeでは外部ライブラリが使えないという問題がある。

そこで、Python mode for Processingに変わる、Pythonでお手軽にGUIプログラミングができる初学者向けの環境を探してみた。条件としては次の通り

- Python3系であること、できればCPython環境
- Processing以外の外部ライブラリを簡単に使えること
- 最近までメンテナンスされていて、今後もメンテナンスされる、または自力でメンテナンスが簡単であること
- Processing風に、余計なボイラープレート不要で、簡単にグラフィカルなプログラムができ、簡単なゲームなどを作れること
- 導入が簡単であること

これらの条件に当てはまるものを探したところ、Py5, p5, PyGameZeroの３種類のライブラリが見つかった。これらとPython mode for Processingを比較してみた。

例としてProcessingの[チュートリアルの Your First Program](https://processing.org/tutorials/gettingstarted/#your-first-program)にある以下のスケッチ（≒プログラム）と同等の機能を作ってみる。
```java
void setup() {
  size(480, 120);
}

void draw() {
  if (mousePressed) {
    fill(0);
  } else {
    fill(255);
  }
  ellipse(mouseX, mouseY, 80, 80);
}
```
Javaのようにクラスなどは必要なくsetupとdrawという関数を定義すれば良い。これらを実行すると、最初に一回setup関数が呼ばれ、その後draw関数が繰り返し呼ばれる。sizeはウィンドウのサイズを決めてfillはそれ以降の描画コマンドで図形を塗りつぶす色を決める。ellipseは楕円を描画する関数である。またmouseX, mouseYはマウスポインタの座標があらかじめ設定されmousePressedはマウスのボタンをクリックしていればTrueがセットされている。

これを実行すると次のようなウィンドウが現れ、クリックしていれば黒色でクリックしていなければ白色で塗りつぶさた円がマウスポインタの位置に描画される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71087/346596ca-324c-8b07-879e-12c7a887a950.png)



# [Python mode for Processing](https://py.processing.org/)

Python mode for Processingとは、ProcessingのModesという拡張機能の一つでPythonでスケッチを書けるようにしたものである。もともとJavaの文法のProcessingのスケッチを、Pythonの文法で書けるようにしたものである。例題のスケッチは次のように書ける。

```python
def setup():
    size(480, 120)

def draw():
  if mousePressed:
    fill(0)
  else:
    fill(255)
  ellipse(mouseX, mouseY, 80, 80)
```
ご覧のようにもともとのProcessingのスケッチをそのままPythonの文法で書き直したものです。書き換えが簡単なので、Processing(Java)の書籍やウェブ上の解説を参考にできます。

ただ、PythonとしてみるとPython2系で、現在主流のPython３系とは書き方が違う部分も出てきます。また、  Jythonベースであり既存のpythonのライブラリを使用できません。さらにProcessing4への対応が不十分で、Processingの外部ライブラリも使用できなくなっています。もともとProcessing3のPython modeでは外部ライブラリの読み込みは、リフレクションを使って無理やりSystemClassloaderにjarファイルを指定するという手法が取られていて、Java9以降この方法が使えなくなった（それ以前から非推奨の手法であった）ので、これを修正するのは簡単ではなさそうです。開発も活発ではないようです。

# [Py5](https://py5coding.org/index.html)

Py5は、Processing for Pythonの新しいバージョンを目指したもので、Python３系のCPythonで動いています。JPypeを使ってPythonのプログラムからprocessing.jarのクラスを呼び出すことでCPythonでありながらProcessingを動かすことができます。

基本的な書き方は以下の通りです。
```python
import py5

def setup():
    py5.size(480, 120)

def draw():
  if py5.is_mouse_pressed:
    py5.fill(0)
  else:
    py5.fill(255)
  py5.ellipse(py5.mouse_x, py5.mouse_y, 80, 80)

py5.run_sketch()
```
setup関数とdraw関数は同じですが、py5モジュール以下の関数を使うようになっています。また、py5.run_sketch()でコードが動作します。これはモジュールモードと呼ばれます。他にImported Modeと呼ばれるモードがあり、IDEのサポートが必要ですが、次のようにimport py5や関数のプレフィックスのpy5., コードを実行するpy5.run_sketch()が不要になります。
```python
def setup():
    size(480, 120)

def draw():
  if is_mouse_pressed:
    fill(0)
  else:
    fill(255)
  ellipse(mouse_x, mouse_y, 80, 80)
```
Imported Modeに対応したIDEとしては[Thonny](https://thonny.org/)のthonny-py5modeなどがあります。このモードにすると、ほとんどPython Modeと同じようにプログラムを書くことができます。違いは、キャメルケースの関数名がスネークケースになる、mousePressedがis_mouse_pressedになるなどです。

インタープリタ自体はCPythonなので、pythonの外部ライブラリを合わせて使用することができます。

# [P5](https://p5.readthedocs.io/en/latest/index.html)
P5は、ProcessingのAPIをPythonで実装したライブラリで、py5と違ってprocessing.jarを使わずに完全にPythonのライブラリで同等の機能を実装しています。
インタープリタはPy5と同様python3系のCPythonです。

基本的な書き方は次の通り。
```python
from p5 import *

def setup():
    size(480, 120)

def draw():
  if mouse_is_pressed:
    fill(0)
  else:
    fill(255)
  ellipse(mouse_x, mouse_y, 80, 80)

run()
```
最初に　from p5 import *をつけて最後のrun()でコードを実行します。py5のimported modeのようにライブラリの読み込みやrun()を隠すIDEのモードなどはないようです。

それ以外の部分は、py5と似ていてキャメルケースがスネークケースに変わります。mousePressedがmouse_is_pressedになるなど多少py5と違う部分もありますが、基本的にはほぼ同等です。

py5同様、Pythonのライブラリとして実装してあるので、pythonの外部ライブラリを使用することができます。

# [PyGameZero](https://pygame-zero.readthedocs.io/ja/latest/index.html)
PyGame Zeroは、上二つと違って、Processing由来ではなく、pythonで主に２Dゲームを作るための描画ライブラリであるpygameを、初心者でも使いやすく簡易なプログラムでかけるようにするライブラリです。インタープリタはPy5, P5と同様python3系のCPythonです。

基本的な書き方は以下の通り。
```python
import pgzrun

WIDTH,HEIGHT=480, 120

mpos=(0,0)
mbuttons=set()

def on_mouse_move(pos,rel,buttons):
    global mpos,mbuttons
    mpos = pos
    mbuttons = buttons

def draw():
    if len(mbuttons)==0:
        screen.draw.filled_circle(mpos,40,'white')
        screen.draw.circle(mpos,40,'black')
    else:
        screen.draw.filled_circle(mpos,40,'black')

pgzrun.go()
```
Processing由来ではないので、使う関数が結構違いますが、基本的にはpgzrun().go()で実行開始で、draw関数に書いた内容を繰り返し実行するという点は似ています。また、py5と同様に最初のimport pgzrunや最後のpgzrun.go()を隠すPyGameZeroモードもあり、それを使うと次のように書けます。
```python
def on_mouse_move(pos,rel,buttons):
    global mpos,mbuttons
    mpos = pos
    mbuttons = buttons

def draw():
    if len(mbuttons)==0:
        screen.draw.filled_circle(mpos,40,'white')
        screen.draw.circle(mpos,40,'black')
    else:
        screen.draw.filled_circle(mpos,40,'black')
```
PyGameZeroモードは、[Thonny](https://thonny.org/)や[Mu Editor (Code with Mu)](https://codewith.mu/)などに標準機能として備わっています。

Processingでsize()関数でウィンドウサイズを決めていたのが、WIDTH,HEIGHTに値をセットすることでウィンドウサイズが決まります。また、マウスの位置などを取得する変数などはなく、on_mouse_moveという関数を定義するとマウスポインタが動作するたびに呼ばれるようになり、この関数内でマウスポインタの位置やボタンの状態を取得できます。

図形を描画する関数はscreen.draw.図形という形式で呼び出すようになっています。

Py5やP5と同様、Pythonのライブラリとして実装してあるので、CPythonの外部ライブラリを使用することができます。また、PyGameの上に薄いラッパーとして実装してあるため、PyGame Zeroにない高度な機能を使いたい時にPyGameライブラリの機能を使うことができます

# 最後に
Python Mode for Processingの代わりになるPythonライブラリについて紹介してきました。Processingをjar経由でそのまま使えるPy5, 同等機能をCPythonで実装し直したP5, pygameの簡易版ラッパーであるPyGame Zeroと三者三様です。

おすすめはというと、Processingの使い勝手を引き継ぎたいならP5, 将来的に高度なゲームを実装したいならPyGame Zeroがおすすめです。

Py5については本物のProcessing.jarを呼び出せますがPython経由でJavaを呼び出すという複雑なことをしているので、特に理由がなければ同等機能のP5で十分だと思います。
本物のprocessing.jarにこだわりがある場合やどうしてもimport文やコードを実行するrun()などのお決まりを書きたくなければPy5も選択肢になるかと思います。

他にもProcessingの機能をJavaScriptで実装してWeb上で使えるようにしたP5.jsをPythonでプログラミングできるようするPyp5jsなどもあります。