Home>

・ Premises
A program is organized by processing. I am a beginner.
When I asked "I would like to add a fireworks-like diffusion to my program," I received the following program.
・ I want to realize
I want to keep drawing a circle without clicking on the execution result and let it spread wherever I click instead of clicking each circle. Also, if you click, I want to spread all the circles that are drawn.
1. Randomly colored circles continue to be drawn at random locations according to the music → 2. Click on the screen at any time to spread all the drawn circles → 3. Circles drawn when you click Only after spreading and clicking, the drawn circle remains → it becomes 1 again.

Error message
When the corresponding source code is executed, the execution result is drawn a circle once, and then the circle is clicked and diffused to draw the next circle.
I don't know why the next circle is not drawn unless I click it. In addition, the mouse click part uses various variables, and I do not know which one is linked and clicked, so I am worried about where to change it.
Applicable source code
import ddf.minim. *;
import ddf.minim.analysis. *;
import ddf.minim.effects. *;
import ddf.minim.signals. *;
import ddf.minim.spi. *;
import ddf.minim.ugens. *;
Minim minim;
AudioPlayer player;
int buffersize = 512;
class Note {
  final float x;
  final float y;
  final float w;
  final float h;
  final float r;
  final float r2;
  final color col;// HSB, alpha
  boolean isAlive = true;
  Note (final float x, final float y, final float playerIn) {
    this.x = x;
    this.y = y;
    this.w = playerIn * 2;
    this.h = playerIn * 2;
    this.r = this.w/2;
    this.r2 = this.r * this.r;
    this.col = color (random (360), 100, 100, 50);
  }
  void draw () {
    noStroke ();
    fill (col);
    ellipse (x, y, w, h);
  }
  void update () {
  }
  boolean isExpired () {
    return! isAlive;
  }
  void toggle () {
    isAlive =! isAlive;
  }
}
abstract class Effect {
  protected float time;
  protected float t = 0;
  final float dt = 1.0;
  Effect () {
  }
  abstract void draw ();
  abstract void update ();
  void dec () {
    time-= dt;
    t + = dt;
  }
  boolean isExpired () {
    return time<0;
  }
}
abstract class MultiEffect extends Effect {
  ArrayList<Effect>chidren = new ArrayList<Effect>();
  MultiEffect () {
  }
  @Override
    void draw () {
    for (Effect eff: chidren) {
      eff.draw ();
    }
  }
  @Override
    void update () {
    for (Effect eff: chidren) {
      eff.update ();
    }
  }
  @Override
    boolean isExpired () {
    for (Effect eff: chidren) {
      if (! eff.isExpired ()) return false;
    }
    return true;
  }
}
class Bakuhatu extends Effect {
  final float x;
  final float y;
  float r;
  float dr = 1;
  final float ddr = 0.5;
  final int R, G, B;
  int alpha;
  int da = 0;
  final int dda = 1;
  Bakuhatu (final float x, final float y, final float r, final color col, final float time) {
    this.x = x;
    this.y = y;
    this.r = r;
    final int mask = 0xFF;
    alpha = (col >>24)&mask;
    alpha/= 2;
    R = (col >>16)&mask;
    G = (col >>8)&mask;B = col&mask;
    this.time = time;
  }
  @Override
    void draw () {
    noStroke ();
    colorMode (RGB);
    fill (R, G, B, alpha);
    ellipse (x, y, 2 * r, 2 * r);
  }
  @Override
    void update () {
    dec ();
    r + = dr;
    dr + = ddr;
    alpha-= da;
    da + = dda;
  }
}
final float g = 0.2;
class Hinoko extends Effect {
  float x;
  float y;
  final float r = 2;
  final float v0 = 5;
  float vx;
  float vy;
  final float theta;
  final color col;
  int R, G, B;
  int alpha;
  float da = 1;
  final float dda = 0.05;
  float drx, dry;
  float ddrx, ddry;
  Hinoko (final float x, final float y, final float r, final color col, final float theta, final float time) {
    this.x = x;
    this.y = y;
    this.vx = v0 * cos (theta);
    this.vy = v0 * sin (theta);
    this.col = col;
    final int mask = 0xFF;
    alpha = (col >>24)&mask;
    R = (col >>16)&mask;
    G = (col >>8)&mask;
    B = col&mask;
    this.drx = 0.5;
    this.dry = 0.05;
    this.ddrx = 0.5;
    this.ddry = 0.05;
    this.time = time;
    this.theta = theta;
  }
  @Override
    void draw () {
    noStroke ();
    colorMode (RGB);
    fill (R, G, B, alpha);
    ellipse (x, y, r, r);
  }
  @Override
    void update () {
    dec ();
    alpha-= da;
    da + = dda;
    x + = vx;
    y + = vy;
    y + = g * t;
    drx + = ddrx;
    dry + = ddry;
  }
}
class Hanabi extends MultiEffect {
  Hanabi (final float x, final float y, final float r, final color col) {
    super ();
    final float timeB = 30;
    chidren.add (new Bakuhatu (x, y, r, col, timeB));
    final float timeH = 50;
    final int max = 32;
    final float dtheta = TWO_PI/max;
    for (int i = 0;i<max;i ++) {
      chidren.add (new Hinoko (x, y, r, col, dtheta * i, timeH));
    }
  }
}
class Effects extends ArrayList<Effect>{
  Effects () {
    // do nothing
  }
  void add (Effects temp) {
    this.addAll (temp);
  }
  void draw () {
    for (Effect eff: this) {
      eff.draw ();
    }
  }
  void update () {
    ArrayList<Effect>temp = new ArrayList<Effect>();
    for (Effect eff: this) {
      eff.update ();
      if (! eff.isExpired ()) temp.add (eff);
    }
    this.clear ();
    this.addAll (temp);
  }
}
class NoteController {
  ArrayList<Note>notes = new ArrayList<Note>();
  ;
  final float margin = 100;final float xmin = margin;
  final float xmax = width-margin;
  final float ymin = margin;
  final float ymax = height-margin;
  NoteController () {
    //
  }
  void add (final float playerIn) {
    if (notes.size ()>10) return;// check
    if (playerIn<20) return;
    final float x = random (xmin, xmax);
    final float y = random (ymin, ymax);
    notes.add (new Note (x, y, playerIn));
  }
  void draw () {
    for (Note note: notes) {
      note.draw ();
    }
  }
  ArrayList<Note>update () {
    ArrayList<Note>next = new ArrayList<Note>();
    ArrayList<Note>del = new ArrayList<Note>();
    for (Note note: notes) {
      note.update ();
      if (note.isExpired ()) {
        del.add (note);
      } else {
        next.add (note);
      }
    }
    notes.clear ();
    notes.addAll (next);
    return del;
  }
  boolean isHit (final Note note) {
    if (mouseX<note.x-note.r) return false;
    if (mouseX>note.x + note.r) return false;
    if (mouseY<note.y-note.r) return false;
    if (mouseY>note.y + note.r) return false;
    return true;
  }
  int find () {
    int i = 0;
    for (Note note: notes) {
      if (isHit (note)) {
        return i;
      }
      i ++;
    }
    return -1;
  }
  void mouseClicked () {
    final int index = find ();
    if (index == -1) return;
    notes.get (index) .toggle ();
  }
}
class Converter {
  Effects makeHanabis (ArrayList<Note>notes) {
    Effects temp = new Effects ();
    for (Note note: notes) {
      temp.add (makeHanabi (note));
    }
    return temp;
  }
  Hanabi makeHanabi (Note note) {
    Hanabi temp = new Hanabi (note.x, note.y, note.r, note.col);
    return temp;
  }
}
NoteController controller;
Effects effects;
Converter converter;
void setup () {
  fullScreen ();
  frameRate (60);
  colorMode (HSB, 360, 100, 100, 100);
  controller = new NoteController ();
  effects = new Effects ();
  converter = new Converter ();
  minim = new Minim (this);
  / *
Free Fantasy BGM Music Material Page 0/Demon Soul
   https://maoudamashii.jokersounds.com/list/bgm10.html
   * /
  final String fn = "bgm_maoudamashii_fantasy10.mp3";
  // final int bpm = 110;
  player = minim.loadFile (fn);
  player.loop ();
}
void draw () {
  background (0);
  final float playerIn = player.mix.level () * 200;
  controller.add (playerIn);
  controller.draw ();
  ArrayList<Note>temp = controller.update ();
  effects.add (converter.makeHanabis (temp));
  effects.draw ();
  effects.update ();
}
void stop () {
  minim.stop ();
  super.stop ();
}
void mouseClicked () {
  controller.mouseClicked ();
}

I left the mouse click once and tried to extract only the part that spreads like fireworks, but I got an error that it was linked with the mouse click program or the variable was not used. Oops. So I tried to modify the mouse click part, but I could only decipher what I was doing using truth, and I didn't know where it was connected and how it was processed.

Supplemental information (FW/tool version etc.)

Use Processing 3.5.3

  • Answer # 1

    It's very nice code, but because there are so many classes and the processing modifier is an internal class, the access modifier is meaningless, so it's hard to follow the code.
    However, as I calmed down and read it, I suddenly came to the target.

    To summarize the requirements,

    Diffuse wherever you click

    Click to spread all drawn circles

    Random colored circles continue to be drawn in random places without clicking


    [Caution]
    Since there are many methods with the same name after this, the main body? PApplet? Let's say that setup () and draw () placed directly are written as App.setup () and draw () of class Note is written as Note.draw ().


    2. will be related to clicks, so look atApp.mouseClicked ().
    NoteController.mouseClicked ().
    You can read it properly, but I'll be sure to find the index of the note withfind (), otherwise it will beNote.toggle ().

    First of all, it's all diffuse here, so you don't have to find it.

    void mouseClicked () {
      for (Note note: notes) {
        note.toggle ();
      }
    }


    I will do it.
    Yes, I've finished 1.2.

    The problem is actually 3.
    I think that a parallax and 10 yen came out instantly after spreading, but if the additional pace is slow, it will be lonely after it disappears, and if it is too early, it will be covered in the screen in no time.
    I don't know what the image looks like, so hold down the adjustment point and
    I will leave fine adjustments to msw.

    Let's look at the additional part in

    .

    The starting point iscontroller.add (playerIn);in App.draw ().
    Look atNoteController.add ().
    if (notes.size ()>10) return;The maximum number of circles.
    if (playerIn<20) return;It seems to be ignored if the volume is too low.
    notes.add (new Note (x, y, playerIn));You're adding a circle.

    I see. This is called every frame, so after spreading, it suddenly increased.

    so as not to increase at once
    void add (final float playerIn) {
      if (notes.size ()>100) return;// check
      if (playerIn<20) return;
      if (frameCount% 30! = 0) return;
      final float x = random (xmin, xmax);
      final float y = random (ymin, ymax);
      notes.add (new Note (x, y, playerIn));
    }


    I tried to do it, but it shouldn't be too regular.
    if (frameCount% (int) random (10, 30)! = 0) return;I thought I was like this, but there are various ways to change it depending on the number of existing circles That's right. Adjust as you like.

    I noticed while I was doing it, but after spreading once, would the circle be only a light blue system?
    It would be nice if it was that kind of specification, but it was lonely because the color was reduced, so when I tried and tried to find out what would happen,Note.draw ()

    void draw () {
      noStroke ();
      colorMode (HSB, 360, 100, 100, 100);
      fill (col);
      ellipse (x, y, w, h);
    }


    The color returned. I'm not sure if it's okay here.