Processing 2.x 系のコードをブラウザで動かしたくて色々試したメモ



# TL;DR

- Procesisng 2.x 系のコードベース (.pde) が存在
- これを変換して現行の Processing 3 の p5.js モードで動かそうとした
- p5.js は IDE が自動追加してくれるものではなく, 自分で最新版をダウンロードして使うべき
- 文法は似ているので, 正規表現を使った文字列置換でなんとかなる部分が多い
- Java 依存の組み込み関数が辛い（今回は実装があって助かった）
- 結論: 完全な互換は諦めたほうがいい. 自分で javascript を書いた方が早い


# note

- 文法等を変換する。オンラインエディタを使う 
	- http://faculty.purchase.edu/joseph.mckay/p5jsconverter.html
	- このサイトがやっていること（サイトより）
		- int, float, ... などの型宣言を全て var にする
		- size() を createCanvas() にする
		- void を function にする
		- new int[] を new Array() にする
		- etc
- 新しい Sketch を作って, p5.js モードにする. さっきのサイトで出力したコードを Processing に貼り付ける
- もしも Minim を使っている場合, p.minim.js を使う
	- Minim に相当する p5.js のライブラリは存在しない. p5 標準のサウンドクラスに置き換えても良いが, Processing(Java) に存在するのかは知らない
	- オープンソースで公開されている p.minim.js を GitHub からダウンロード, またはソースコードをコピーして貼り付けする
	- https://github.com/nryota/p.minim.js/blob/master/p.minim.js
	- `Minim minim = new Minim()` を, `var minim = Minim()` に置き換える. `AudioPlayer` も同じように置き換える
	- オープンソースと著作権放棄は違う. 公開する場合は以下のクレジットをわかるところに書いておく
	- `Copyright © 2016 NISHIDA Ryota http://dev.eyln.com Distributed under the ZLIB License.`
- import を消す
- ユーザー定義クラスの変数宣言を let に置き換える
- キャストが全部 `<var>` という謎記号に変換されるので全て消す
- `stroke(#AAAAAA)` を `stroke("#AAAAAA")` にする
- `data/` 以下に保存されているファイルを, .pde などがある１つ上のフォルダに移す
- PC 内のフォントを使っている `createFont()` を全てコメントアウトする
	- data/ にフォントファイルあれば loadFont() で使えるのだが、PC内のフォントは p5.js では使えない
- `key` に入っている文字が Java モードでは lower case なのに対し p5.js では upper case になっている
	- `key == 'a'` を `key == 'A'` にする
	- または, `key` を `key.toLowerCase()` に置き換える
- `keyPressed` の仕様が全然違う
	- Java モード：キーが押されている間ずっとコールされる
	- p5.jsモード：押されたとき一度だけコールされる
	- 対処法: `setTimeout(function(){ keyIsPressed && keyPressed() }, 45);` を `keyPressed` 関数の最後に書く

# keyPressed()

`setTimeout(function(){ keyIsPressed && keyPressed() }, 45);` は, おまじないではない. 以下解説


問題: Java モードの `void keyPressed()` の仕様がリファレンスに書いてあるのと違う

公式リファレンスでは
> The keyPressed() function is called once every time a key is pressed. The key that was pressed is stored in the key variable. 
> https://processing.org/reference/keyPressed_.html


となっているが、実際には長押しすると複数回呼ばれる

<a href="https://gyazo.com/c4d24be34b8e4fa10dd9fef7fe8a7cbc"><img src="https://i.gyazo.com/c4d24be34b8e4fa10dd9fef7fe8a7cbc.gif" alt="Image from Gyazo" width="618"/></a>


これバグなのだろうか. Processing 2.x 系のリファレンスにも同じように書いてあるんだが, 闇深すぎないか？



さて, 何度もコールされることを期待してコードを書いている人は, どうしたら良いか. 
押している間ずっと呼んでくれないのであれば, 自分で呼んでやれば良い

ということで, 以下のコードを試してみた

```javascript
function keyPressed() {
	// ...
	
	requestAnimationFrame(function(){ keyIsPressed && keyPressed() });
}
```

`keyIsPressed` が `true` であれば, およそ 16ms 後くらいに `keyPressed()` が再びコールされる

実際に試してみると, Processing の時より圧倒的に `keyPressed()` が呼ばれる頻度が高くなってしまった. どうやら Java モードのキーイベントは 60fps よりも低いらしい

じゃあ Java モードのキーイベントは何 fps くらいなのか調べよう. ということで, 以下のコードを試した


```processing
int count = 0;
int start = 0;
void keyPressed() {
  if (start == 0) {
    start = millis();
  }
  int elapsed = millis() - start;
  count ++;
  String fps = "" + (float(++count) / elapsed * 1000);
  clear();
  text(fps, 0, 50);
}
```

環境にもよるだろうし `text()` とか `clear()` のオーバーヘッドで fps が若干下がっていそうではあるが, およそ 22fps くらいという結果になった

1000 / 22 ~= 45ms なので, 45ms くらい待ってから `keyPressed()` を呼んであげれば良い. というわけでこうなる


```javascript
function keyPressed() {
	// ...
	
	setTimeout(function(){ keyIsPressed && keyPressed() }, 45);
}
```

しかし, 上手くいかない. キーのリリースが行われず, `keyIsPressed` が常に `true` になってしまう. なぜか...

# p5.js

2019/01/25 現在, Processing IDE で p5.js モードを選択すると, p5.js が自動的に追加されるのだが, そのバージョンは v0.5.7 となっている. 現時点での最新版は v0.7.3 なので, かなり古い. リリース日も 9 Feb 2017 となっている 

https://github.com/processing/p5.js/releases/tag/0.5.7

結論から言うと, 問題の原因は p5.js のバージョンが古いせいである

というのも, 元々ローカルに追加された p5.js をデバッグしていて, バグの原因は突き止めたのだが, GitHub で最新のコードを見たら既に治っていたのだ. 一体いつ治ったのか. 該当するコミットを探していくと, このコミットで修正されたことが分かった
> Fixing incorrect logic for checking that all keys have been released.
https://github.com/processing/p5.js/commit/07cbfcd825942def743a856b998a7c7eb2965076

このパッチがリリースに載ったのは **v0.5.8** だ

> Switched from reqwest to fetch for loadX() methods
New signatures for httpDo()
Change loadTable() and loadStrings() to use httpDo() for consistency
Fix blendMode switching in FF
Fix mousePressed issues in Chrome
Fix for keyIsPressed() function
Fix for textToPoints() function
Fix frameRate() docs
Fix color() documentation
Fix video removeCue() function
Added docs for loading screen
Added ISSUE_TEMPLATE.md
Updated mocha-grunt and other modules to fix build errors
> https://github.com/processing/p5.js/releases/tag/0.5.8

と言う訳で, ちゃんと動かすには, 最新版の p5.js をダウンロードしてきて, ファイルを置き換えれば良い
https://github.com/processing/p5.js/releases
（色々あるが, p5.js をクリックしてダウンロードする）


# 所感

- 最初から p5.js で開発するなら, Processing IDE を使うべきではない
- 現行ブラウザでは let が使えるので、let を使うべきでは？
	- と思ったが, let を使うと Processing IDE に怒られてしまう. 泣きたい
- イベントハンドラの宣言、全部 void という前提でよかったっけ？
- new Array(length) ではなく Array.from({ length }) を使おう
- インターネットのどこかに pde2js の実装は存在するのだろうか…