Processingにも実はマルチスレッドを扱う機能がある、というのはすでにいくつか記事がありますよね。RunnableインターフェイスをimplementしたクラスをThreadコンストラクタの引数にしてインスタンス化してstart()
を呼び出す...というやつです。言葉にするとわかりづらいですね。それなら関数作ってthread("funcName")
ってやった方が楽ですね。
なぜこれがダメなのかというと、今回は"常に"動き続けるスレッドがほしかったのです。上の方法で呼び出されたものは与えた処理を実行するとスレッドが終了してしまうので、常に別スレッドで計算したいなどとなると別の方法が必要でした。(Threadクラスを用いる方法があればぜひ教えてください)
ここからが今回の内容になります。
boolean isCollided;
void setup(){
size(400,400);
new Thread(new Calculator());
}
void draw(){
background(255);
if(isCollided){
fill(255,0,0);
} else {
fill(0,0,255);
}
ellipse(200,200,100,100);
}
class Calculator{
void run(){
if(dist(mouseX,mouseY,200,200)<50){
isCollided = true;
} else {
isCollided = false;
}
}
}
class Thread extends PApplet{
Calculator c;
Thread(Calculator c) {
this.c = c;
PSurface surface = super.initSurface();
surface.startThread(); // これか
this.startSurface(); // これのどっちか
// this.startSurface()を使用した場合は上のsurfaceがnever usedと警告出ますが気にしなくていいです。
}
void draw(){
r.run();
}
}
このプログラムでは、カーソルが直径100の円の中にあれば円が赤色に、外なら円が青色になります。
本来であればdist()
を用いた内外判定はdraw()
の中に書きますが、Calculatorクラスを用意し、そのrun()
内の処理として実装します。
new Thread(new Calculator());
いきなり見づらい書き方ですみません。丁寧に書くと下のようになります
Calculator c = new Calculator();
Thread thread = new Thread(c);
ではなんで先のような書き方をしていたのかというと、CalculatorクラスにせよThreadクラスにせよオブジェクトに触れる必要がないからです。(インスタンス化した時点でメモリ上に用意され、使っているうちは存在し続けます。使われなくなったらいつかメモリが解放されます(このことをガベージコレクタとかなんとか...))
Calculatorクラスについては大丈夫ですね。クラス名も適当です。この中に用意した関数をのちに呼び出します。
次はThreadクラスについてです。(Threadクラスというのがもともと用意されていて文字に色が付きますが問題ないです)
PAppletというのはおそらくウィンドウの作成・描画に関するクラスで、複数のウィンドウを作ったりできます。その作られたウィンドウ達はそれぞれ別に処理されることを利用したのが今回の記事です。
※複数ウィンドウについては3846masaさんのサイトをどうぞ
クラス内部の記述はほとんどコピペで構いません。先ほどの3846masaさんのサイトで紹介されていたものから必要なものだけを書きだしました。
あとは通常のメインループと同じようにdraw()が呼び出されるので、用意したクラスの関数を呼び出してください。
作られるウィンドウはデフォルトでは非表示なので何もしていませんが、ちゃんと動いているかを確認する場合は、コンストラクタの内部のinitSurface()
が呼び出された後で
surface.setVisible(true);
もしくは
this.showSurface();
と記述してください。
###経緯
東方Projectという有名な弾幕シューティングゲームに魅了されて、当時勉強していたProcessingの練習もかねて弾幕シューティングゲームを作っていたのですが、大量の弾幕を描画すると重いんですよねやっぱり。だから当たり判定を別スレッドに渡したりと、少しでも処理が軽くできないかなと思い今回の方法を調べるに至りました。
まあ元がJavaの言語でやるものじゃないと思いますけど()