・ 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.
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 at
App.mouseClicked ()
.NoteController.mouseClicked ()
.You can read it properly, but I'll be sure to find the index of the note with
find ()
, otherwise it will beNote.toggle ()
.First of all, it's all diffuse here, so you don't have to find it.
I will do it.
Yes, I've finished 1.2.
The problem is actually 3.
Let's look at the additional part inI 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.
.
The starting point is
controller.add (playerIn);
in App.draw ().Look at
NoteController.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 onceI 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 ()
The color returned. I'm not sure if it's okay here.