Home>

-I want to add a Tree function to draw a tree using recursion in the following code.
・ The source code is long, but I put it all in order to make it easy to understand. I'm sorry.
The problem part is the Tree function at the end. Thank you.

Error message If i call the Tree function in
setup (), it will be drawn only once and then disappear.
Also, when you call it inside draw (), the line is drawn many times, and the eyes are flickering.
I think that it is because the screen is updated every second in the Note, but it is not possible to prevent the drawing once being affected by other programs, right?
Is there a way to add it somehow?
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;
// AudioInput in;
AudioPlayer player;
// float volumeIn;
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 = random (700, 1200);
    this.y = random (400, 500);
    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 () {
    colorMode (HSB, 360, 100, 100, 100);
    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;
  // color col;
  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 ();
    // fill (col);
    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;
  // final float start;
  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;
    //this.col = color (h, s, b, alpha);
    final int mask = 0xFF;
    alpha = (col >>24)&mask;
    // alpha/= 2;
    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.start = time;
    this.theta = theta;
  }
  @Override
    void draw () {
    noStroke ();
    colorMode (RGB);
    fill (R, G, B, alpha);
    // fill (col);
    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 () {
    //
  }
  // Circle control
  void add (final float playerIn) {
    if (notes.size ()>100) return;// check
    if (playerIn<20) return;
    if (frameCount% 40! = 0) return;
    // if (frameCount% (int) random (10, 40)! = 0) 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;
  }
  // Judgment using authenticity
  boolean isHit (final Note note) {
    return true;
  }
  // all specified
  void mouseClicked () {
    for (Note note: notes) {
      note.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);
  / * Tree (30, width/2, height, PI, width/8);
  fill (# 8B7250);
  rect (0, 1030, 2000, 50);* /
  colorMode (HSB, 360, 100, 100, 100);
  controller = new NoteController ();
  effects = new Effects ();
  converter = new Converter ();
  minim = new Minim (this);
  // in = minim.getLineIn (Minim.STEREO, buffersize);
  final String fn = "Mountain.mp3";
  player = minim.loadFile (fn);
  player.loop ();
}
void draw () {
  background (200);
 Tree (30, width/2, height, PI, width/8);
 noStroke ();
  fill (# 8B7250);
  rect (0, 1030, 2000, 50);
  // volumeIn = in.mix.level () * 200;
  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 ();
}
// tree generation
void Tree (float strokeWeight, float x, float y, float rotate, float length) {
  pushMatrix ();// save coordinates temporarily
  translate (x, y);// coordinate translation
  rotate (rotate);// coordinate rotation
  strokeWeight (strokeWeight);// line outline thickness
  stroke (50, 0, 0);// line color
  line (0, 0, 0, length);// line drawing, array length
  popMatrix ();// Undo the changed coordinates
  if (strokeWeight<2) return;
  if (random (0, 4)>3&&strokeWeight<3) return;
  Tree (strokeWeight * 2/3, x-sin (rotate) * length, y + cos (rotate) * length, rotate-PI/10, length * 2/3);
  Tree (strokeWeight * 2/3, x-sin (rotate) * length, y + cos (rotate) * length, rotate + PI/10, length * 2/3);
}
void stop () {
  minim.stop ();
  super.stop ();
}
void mouseClicked () {
  controller.mouseClicked ();
}

The Tree function was put in setup () and draw (), respectively, and the results were confirmed.
Only the Tree function can be made independent.

Supplemental information (FW/tool version etc.)

Processing3.5.3