🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

解決済

1回答

1293閲覧

mouseClickedの処理の解読

msw

総合スコア9

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

1グッド

0クリップ

投稿2019/11/18 11:01

前提・実現したいこと

・前提
processingでプログラムを組んでいます。初心者です。
知恵袋で「自分の組んだプログラムに花火のような拡散を追加したい」と質問した所、下記のプログラムを回答頂きました。
・実現したいこと
実行結果をクリックをしなくても円は描画し続け、円一つ一つクリックではなくどこでクリックしても拡散するようにしたい。また、クリックしたら描画されている円を全て拡散させるようにしたい。
1.音楽に合わせてランダムな色の円がランダムな場所に描画され続ける→2.任意のタイミングで画面をクリックすると描画されている円が全て拡散する→3.クリックした時に描画されていた円だけが拡散しクリックした後に描画された円は残る→再び1の流れになる。

発生している問題・エラーメッセージ

該当のソースコードを実行すると、実行結果が一度だけ円が描画されその後は円を一つ一つクリックして拡散し次の円が描画されます。 何故クリックしないと次の円が描画されないのか分かりません。また、マウスクリックの部分が色々と変数を使っておりどれとリンクさせてクリックした時の処理をしているかが分からず、どこを改変すれば良いのか悩んでいます。

該当のソースコード

processing

1import ddf.minim.*; 2import ddf.minim.analysis.*; 3import ddf.minim.effects.*; 4import ddf.minim.signals.*; 5import ddf.minim.spi.*; 6import ddf.minim.ugens.*; 7Minim minim; 8AudioPlayer player; 9int buffersize = 512; 10 11class Note { 12 final float x; 13 final float y; 14 final float w; 15 final float h; 16 final float r; 17 final float r2; 18 final color col;//HSB, alpha 19 boolean isAlive = true; 20 21 Note(final float x, final float y, final float playerIn) { 22 this.x = x; 23 this.y = y; 24 this.w = playerIn * 2; 25 this.h = playerIn * 2; 26 this.r = this.w / 2; 27 this.r2 = this.r * this.r; 28 this.col = color(random(360), 100, 100, 50); 29 } 30 31 void draw() { 32 noStroke(); 33 fill(col); 34 ellipse(x, y, w, h); 35 } 36 37 void update() { 38 } 39 40 boolean isExpired() { 41 return !isAlive; 42 } 43 44 void toggle() { 45 isAlive = !isAlive; 46 } 47} 48 49abstract class Effect { 50 protected float time; 51 protected float t = 0; 52 final float dt = 1.0; 53 54 Effect() { 55 } 56 57 abstract void draw(); 58 59 abstract void update(); 60 61 void dec() { 62 time -= dt; 63 t += dt; 64 } 65 66 boolean isExpired() { 67 return time < 0; 68 } 69} 70 71abstract class MultiEffect extends Effect { 72 ArrayList<Effect> chidren = new ArrayList<Effect>(); 73 74 MultiEffect() { 75 } 76 77 @Override 78 void draw() { 79 for (Effect eff : chidren) { 80 eff.draw(); 81 } 82 } 83 84 @Override 85 void update() { 86 for (Effect eff : chidren) { 87 eff.update(); 88 } 89 } 90 91 @Override 92 boolean isExpired() { 93 for (Effect eff : chidren) { 94 if (!eff.isExpired()) return false; 95 } 96 return true; 97 } 98} 99 100class Bakuhatu extends Effect { 101 final float x; 102 final float y; 103 float r; 104 float dr = 1; 105 final float ddr = 0.5; 106 final int R, G, B; 107 int alpha; 108 int da = 0; 109 final int dda = 1; 110 111 Bakuhatu(final float x, final float y, final float r, final color col, final float time) { 112 this.x = x; 113 this.y = y; 114 this.r = r; 115 116 final int mask = 0xFF; 117 alpha = (col>>24) & mask; 118 alpha /= 2; 119 R = (col>>16) & mask; 120 G = (col>>8) & mask; 121 B = col & mask; 122 this.time = time; 123 } 124 125 @Override 126 void draw() { 127 noStroke(); 128 colorMode(RGB); 129 fill(R, G, B, alpha); 130 ellipse(x, y, 2*r, 2*r); 131 } 132 133 @Override 134 void update() { 135 dec(); 136 r += dr; 137 dr += ddr; 138 alpha -= da; 139 da += dda; 140 } 141} 142 143final float g = 0.2; 144class Hinoko extends Effect { 145 float x; 146 float y; 147 final float r = 2; 148 final float v0 = 5; 149 float vx; 150 float vy; 151 final float theta; 152 final color col; 153 int R, G, B; 154 int alpha; 155 float da = 1; 156 final float dda = 0.05; 157 float drx, dry; 158 float ddrx, ddry; 159 160 Hinoko(final float x, final float y, final float r, final color col, final float theta, final float time) { 161 this.x = x; 162 this.y = y; 163 164 this.vx = v0 * cos(theta); 165 this.vy = v0 * sin(theta); 166 this.col = col; 167 168 final int mask = 0xFF; 169 alpha = (col>>24) & mask; 170 R = (col>>16) & mask; 171 G = (col>>8) & mask; 172 B = col & mask; 173 174 this.drx = 0.5; 175 this.dry = 0.05; 176 this.ddrx = 0.5; 177 this.ddry = 0.05; 178 179 this.time = time; 180 this.theta = theta; 181 } 182 183 @Override 184 void draw() { 185 noStroke(); 186 colorMode(RGB); 187 fill(R, G, B, alpha); 188 ellipse(x, y, r, r); 189 } 190 191 @Override 192 void update() { 193 dec(); 194 alpha -= da; 195 da += dda; 196 197 x += vx; 198 y += vy; 199 y += g*t; 200 201 drx += ddrx; 202 dry += ddry; 203 } 204} 205 206class Hanabi extends MultiEffect { 207 Hanabi(final float x, final float y, final float r, final color col) { 208 super(); 209 210 final float timeB = 30; 211 chidren.add(new Bakuhatu(x, y, r, col, timeB)); 212 213 final float timeH = 50; 214 final int max = 32; 215 final float dtheta = TWO_PI / max; 216 for (int i=0; i<max; i++) { 217 chidren.add(new Hinoko(x, y, r, col, dtheta*i, timeH)); 218 } 219 } 220} 221 222class Effects extends ArrayList<Effect> { 223 Effects() { 224 //do nothing 225 } 226 227 void add(Effects temp) { 228 this.addAll(temp); 229 } 230 231 void draw() { 232 for (Effect eff : this) { 233 eff.draw(); 234 } 235 } 236 237 void update() { 238 ArrayList<Effect> temp = new ArrayList<Effect>(); 239 for (Effect eff : this) { 240 eff.update(); 241 if (!eff.isExpired()) temp.add(eff); 242 } 243 this.clear(); 244 this.addAll(temp); 245 } 246} 247 248class NoteController { 249 ArrayList<Note> notes = new ArrayList<Note>(); 250 ; 251 252 final float margin = 100; 253 final float xmin = margin; 254 final float xmax = width-margin; 255 final float ymin = margin; 256 final float ymax = height-margin; 257 258 NoteController() { 259 // 260 } 261 262 void add(final float playerIn) { 263 if (notes.size() > 10) return;//check 264 if (playerIn < 20) return; 265 266 final float x = random(xmin, xmax); 267 final float y = random(ymin, ymax); 268 notes.add(new Note(x, y, playerIn)); 269 } 270 271 void draw() { 272 for (Note note : notes) { 273 note.draw(); 274 } 275 } 276 277 ArrayList<Note> update() { 278 ArrayList<Note> next = new ArrayList<Note>(); 279 ArrayList<Note> del = new ArrayList<Note>(); 280 for (Note note : notes) { 281 note.update(); 282 if (note.isExpired()) { 283 del.add(note); 284 } else { 285 next.add(note); 286 } 287 } 288 notes.clear(); 289 notes.addAll(next); 290 return del; 291 } 292 293 boolean isHit(final Note note) { 294 295 if (mouseX < note.x-note.r) return false; 296 if (mouseX > note.x+note.r) return false; 297 if (mouseY < note.y-note.r) return false; 298 if (mouseY > note.y+note.r) return false; 299 return true; 300 } 301 302 int find() { 303 int i=0; 304 for (Note note : notes) { 305 if (isHit(note)) { 306 return i; 307 } 308 i++; 309 } 310 return -1; 311 } 312 313 void mouseClicked() { 314 final int index = find(); 315 if (index == -1) return; 316 notes.get(index).toggle(); 317 } 318} 319 320class Converter { 321 Effects makeHanabis(ArrayList<Note> notes) { 322 Effects temp = new Effects(); 323 for (Note note : notes) { 324 temp.add(makeHanabi(note)); 325 } 326 return temp; 327 } 328 329 Hanabi makeHanabi(Note note) { 330 Hanabi temp = new Hanabi(note.x, note.y, note.r, note.col); 331 return temp; 332 } 333} 334 335NoteController controller; 336Effects effects; 337Converter converter; 338 339void setup() { 340 fullScreen(); 341 frameRate(60); 342 colorMode(HSB, 360, 100, 100, 100); 343 344 controller = new NoteController(); 345 effects = new Effects(); 346 converter = new Converter(); 347 348 minim = new Minim(this); 349 /* 350ファンタジーの無料・フリーBGM音楽素材 0ページ目/魔王魂 351 https://maoudamashii.jokersounds.com/list/bgm10.html 352 */ 353 final String fn = "bgm_maoudamashii_fantasy10.mp3"; 354 //final int bpm = 110; 355 player = minim.loadFile(fn); 356 player.loop(); 357} 358 359void draw() { 360 background(0); 361 362 final float playerIn = player.mix.level()*200; 363 controller.add(playerIn); 364 controller.draw(); 365 ArrayList<Note> temp = controller.update(); 366 367 effects.add(converter.makeHanabis(temp)); 368 effects.draw(); 369 effects.update(); 370} 371 372void stop() { 373 minim.stop(); 374 super.stop(); 375} 376 377void mouseClicked() { 378 controller.mouseClicked(); 379} 380

試したこと

マウスクリックは一旦置いておき、花火のように拡散するという部分だけ抜き取れないか試したが、マウスクリックのプログラムと連携しているのか変数が使われていない等のエラーが出てしまった。そこで、マウスクリックの部分を改変しようとしたが、真偽を使って何かをやっている程度しか解読出来ず具体的にどこと繋がってどう処理しているのかが分からなかった。

補足情報(FW/ツールのバージョンなど)

Processing 3.5.3を使用

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

大変素晴らしいコードなのですが、クラスが多くProcessingは内部クラスになる仕様上アクセス修飾子が意味がなくなるので、ちょっとコードが追いにくいですね。
しかし順番に落ち着いて読んでいくと、案外すぐ目的のものに行き当たりました。

まず要件をまとめると、

  1. どこでクリックしても拡散する
  2. クリックしたら描画されている円を全て拡散する
  3. クリックをしなくてもランダムな色の円がランダムな場所に描画され続ける

ですね。


[注意]
これ以降同名のメソッドが多いので、本体?PApplet?直に置かれてるsetup()やdraw()をApp.setup()と書き、class Noteのdraw()をNote.draw() と書くこととします。


  1. 2.はクリックに関連するでしょうから、App.mouseClicked()を見ます。

NoteController.mouseClicked()に任せています。
ちゃんと読んでもいいんですが、きっとfind()でnoteのindexを探し、なければ何もせずあればNote.toggle()ってことでしょう。

まずここで全部拡散なので、findする必要はなくなります。

Processing

1void mouseClicked() { 2 for (Note note : notes) { 3 note.toggle(); 4 } 5}

実行します。
はい、もう1.2.は終わってしまいました。

実は問題は3.です。
拡散した後一瞬でパララと10個円が出たと思いますが、追加のペースが遅いと全部消えた後寂しいですし、早すぎるとあっという間に画面中覆いつくされそうです。
どういうイメージなのかがわからないので、調整ポイントを押さえて細かい調整はmswさんに任せます。

では追加部分を見てみます。

起点はApp.draw()内のcontroller.add(playerIn);です。
NoteController.add()を見ます。
if (notes.size() > 10) return; 円の最大個数ですね。
if (playerIn < 20) return; 音量が小さすぎる場合は無視するようです。
notes.add(new Note(x, y, playerIn)); 円を追加してるんでしょう。

なるほど。ここは毎フレーム呼ばれるので拡散した後、一気に増えたわけですね。
一気に増えないように、

Processing

1void add(final float playerIn) { 2 if (notes.size() > 100) return;//check 3 if (playerIn < 20) return; 4 if (frameCount % 30 != 0) return; 5 6 final float x = random(xmin, xmax); 7 final float y = random(ymin, ymax); 8 notes.add(new Note(x, y, playerIn)); 9}

としてみましたが規則的過ぎていけませんね。
if (frameCount % (int)random(10, 30) != 0) return;私はこんなもんかな?と思いましたが、今ある円の個数によって変えるとか方法はいろいろありそうです。お好きなように調整してください。

あとやってるうちに気が付いたんですが、一回拡散した後、円が水色系統だけになりませんか?
そういう仕様ならいいのですがなんか色が減って寂しいので、どうにかならないかと試行錯誤したところ、Note.draw()

Processing

1void draw() { 2 noStroke(); 3 colorMode(HSB, 360, 100, 100, 100); 4 fill(col); 5 ellipse(x, y, w, h); 6}

で色が戻りました。ここはそれでよいのか自信ありません。

投稿2019/11/24 01:38

編集2024/03/04 09:30
TN8001

総合スコア9855

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

msw

2019/11/26 14:06

返信が遅れてしまい申し訳ございません。回答がとても分かり易く、本当に助かりました! 足し算する事ばかり考えていたので、真偽の判定がいらないなどの引き算を試すのを忘れていました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問