Using sound and mouse interaction

Hi, Im currently working on this sketch. Overall, whenever i overlap the mouse on any ellipse, i get a color fill and a piece of sound that start playing. The problem was the sound started looping insanely fast (partly because it was on void draw, i guess) so I use the millis() function to avoid that former issue but now i have a delay on the sound when overlaping from one ellipse to another. That being said, what i really want is to whenever the mouse overlaps the ellipse, both the sound and color fill happens only once and the same thing for every ellipse. I believe i have to put that code on a event but im not sure.

Particle p1;
Particle p2;
Particle p3;
Particle p4;
Particle p5;
Particle p6;
Particle p7;

int lastTimeCheck;
int timeIntervalFlag = 1000;

import ddf.minim.*;
Minim minim;
AudioSample sound1;
AudioSample sound2;
AudioSample sound3;
AudioSample sound4;
AudioSample sound5;
AudioSample sound6;

import spout.*;
Spout spout;

void setup() {
 size(600,400, P2D);
 p1 = new Particle(100,100,10);//mouse
 p2 = new Particle(120,100,50);
 p3 = new Particle(120,250,50);
 p4 = new Particle(400,250,50);
 p5 = new Particle(400,100,50);
 p6 = new Particle(255,100,50);
 p7 = new Particle(255,250,50);
  
 lastTimeCheck = millis();
 minim = new Minim(this);
 sound1 = minim.loadSample("do.wav", 512);
 sound2 = minim.loadSample("re.wav", 512);
 sound3 = minim.loadSample("mi.wav", 512);
 sound4 = minim.loadSample("fa.wav", 512);
 sound5 = minim.loadSample("sol.wav", 512);
 sound6 = minim.loadSample("la.wav", 512);
 
 spout = new Spout(this);
  spout.createSender("Spout Processing");
}

void draw() {
 background(0);
 
 if (p1.overlaps(p2)) {
   p2.displayP2();
   if ( millis() > lastTimeCheck + timeIntervalFlag ) {
        lastTimeCheck = millis();
        sound1.trigger();
     }
 }
   
 if (p1.overlaps(p3)) {
   p3.displayP3();
     if ( millis() > lastTimeCheck + timeIntervalFlag ) {
        lastTimeCheck = millis();
        sound2.trigger();
     }
 }
 
 if (p1.overlaps(p4)) {
   p4.displayP4();
   if ( millis() > lastTimeCheck + timeIntervalFlag ) {
        lastTimeCheck = millis();
        sound3.trigger();
     }
 }
 
 if (p1.overlaps(p5)) {
   p5.displayP5();
   if ( millis() > lastTimeCheck + timeIntervalFlag ) {
        lastTimeCheck = millis();
        sound4.trigger();
     }
 }
     
  if (p1.overlaps(p6)) {
   p6.displayP6();
   if ( millis() > lastTimeCheck + timeIntervalFlag ) {
        lastTimeCheck = millis();
        sound5.trigger();
     }
  }
     
   if (p1.overlaps(p7)) {
   p7.displayP7();
   if ( millis() > lastTimeCheck + timeIntervalFlag ) {
        lastTimeCheck = millis();
        sound6.trigger();
     }
   }
 
 
 p1.x = mouseX;
 p1.y = mouseY;
 
 p1.display(); //colocar marco de demas pelotas
 
 spout.sendTexture();
}

Here goes my class

class Particle {
  float x;
  float y;
  float r;
  
  Particle (float tempX, float tempY, float tempR) {
    x = tempX;
    y = tempY;
    r = tempR;
  }
  
  boolean overlaps (Particle other) {
    float d = dist(x, y, other.x, other.y);
    if (d < r + other.r) {
      return true;
    } else {
      return false;
    }
  }
  
  void display() {
   noStroke();
   noFill();
   ellipse(x, y, r*2, r*2);
   stroke(255);
   ellipse(120,100,100,100);//izq
   ellipse(120,250,100,100);//izq
   ellipse(400,250,100,100);//der
   ellipse(400,100,100,100);//der
   ellipse(255,100,100,100);//en medio
   ellipse(255,250,100,100);//en medio
  }
  
  void displayP2() {
   stroke(255);
   fill(0,150,0);
   ellipse(x, y, r*2, r*2);
  }
  
  void displayP3() {
   stroke(255);
   fill(150,0,0);
   ellipse(x, y, r*2, r*2);
  }
  
  void displayP4() {
   stroke(255);
   fill(0,0,150);
   ellipse(x, y, r*2, r*2);
  }
  
  void displayP5() {
   stroke(255);
   fill(100,0,150);
   ellipse(x, y, r*2, r*2);
  }
  
  void displayP6() {
   stroke(255);
   fill(150,50,100);
   ellipse(x, y, r*2, r*2);
  }
  
  void displayP7() {
   stroke(255);
   fill(100,150,50);
   ellipse(x, y, r*2, r*2);
  }
}
1 Like

There are many things you should change.

•Arrays! You should really use arrays. Would save you a lot of repetitive Code.

•For Loops! Again, would save a lot of repetition.

•Have the overlap() function start the sound would be good, but you can leave it how it is now.

•Set a bool in the Particle to true if the sound is started and only set it back to false once the overlap is done :

if (overlap() == true && p5.isStillOverlapping == false) { 
   sound.start; 
   p5.isStillOverlapping = true; 
} else if (overlap() == false && p5.isStillOverlapping == true) { //checking wether p5 bool is still true is unneccessary, but better than always setting the p5 if itā€˜s not overlapping
   p5.isStillOverlapping = false;
}
2 Likes

Hi, thanks for your reply. So ā€œisStillOverlappingā€ is going to be another bool, inst it?

Yes, just add that bool to your class and set it true if there is an overlap.

Note, that with this there won’t be another sound if another shape overlaps if there already is an overlap going on.

For that youā€˜d have to change the way you check for overlaps (not only checking if p1 overlaps any other, but if any p overlaps another p). For that an array and a for loop are pretty much essential (or youā€˜ll have to write 7^2 checks for overlaps…)

1 Like

Yes i’ ve noticed i’m missing the arrays as it’s getting confusing without them, so that’s the first thing i’m going to implement. Thanks and i’ll keep you update with my sketch!.

1 Like

Hi! i’ve changed my code significantly! Now it’s much clearer than before. Also, i’ve decided to only trigger a event when my mouse is overlapping any of the following ellipses. Based on this new sketch, how can i implement the sound event that we were talking about?(to sound only once whenever the mouse overlap any ellipse). I’d appreciate your advice. and thanks cause’ now my code looks decent haha.

RE-edit: It’s working partly now. It only triggers with one ellipse. Idk why. I added a mousePressed event to active the sound.

import ddf.minim.*;
Minim minim;
AudioPlayer sound1;

ArrayList<Particle> particles; //gonna have arraylist. full of Particle objects. named particles
boolean playFile = false;

void setup() {
 size(640,360);
 
 minim = new Minim(this);
 sound1 = minim.loadFile("do.wav");
 
 particles = new ArrayList<Particle>();
 for (int i = 0; i < 4; i++) {
   particles.add(new Particle(100*i+100,height/2,50)); 
   particles.add(new Particle(100*i+100,height/2-100,50)); 
   }
}

void draw() {
  background(200);

  for (Particle p : particles) {
    p.display();
    p.update(mouseX, mouseY);
  }
}

void mousePressed() {
if (playFile) {
    sound1.play();
    sound1.rewind();
  }
}

here’s the new class

class Particle {
  int x;
  int y;
  int diameter;
  int relleno;
  
  Particle (int tempX, int tempY, int tempR) {
    x = tempX;
    y = tempY;
    diameter = tempR;
  }
  
  boolean overCircle(int x, int y, int diameter) {
    if (dist(mouseX, mouseY, x, y) < diameter/2) {
      return true;
    } else {
      return false;
    }
  }
  
void update(int mouseXin, int mouseYin) {
 if (overCircle( x, y, diameter)) {
   playFile = true;
 } else {
   playFile = false;
 }
}

  void display() {
    noStroke();
    if (dist(mouseX, mouseY, x, y) < diameter/2) {
      fill(x,y,150);
      sound1.play();
    } else {
      stroke(1);
      noFill();
   }
    ellipse(x,y,diameter,diameter); 
  }  
}

When i execute it with a single ellipse on void draw() it works well.

  Particle p = particles.get(0);
  p.update(mouseX, mouseY);
  p.display();

Excuse if my code changed a lot, it is just that it works fine to me in this way despite that fact that i cannot still find a way to trigger the sound with every ellipse displayed.

1 Like

at first want to say that the concept
to play one sound ?one time? when mouse ( enters ) over circle
is a unusual operation concept,
usually use one mouse CLICK for one sound…

OOPS now newer version do that


you use the circles ?button? in a array,
so it makes sense to use as array for the sound too.

you play sound from a update() function AND a display() function???
making and using a over() function in the update function BUT not in the display function.
so i play little bit with your FIRST version code to give you idea about different style…

import ddf.minim.*;
Minim minim;
AudioPlayer[] sound = new AudioPlayer[8];


ArrayList<Particle> particles; 

void setup() {
  size(640, 360);

  minim = new Minim(this);
  sound[0] = minim.loadFile("data/blip.mp3");
  sound[1] = minim.loadFile("data/blop.mp3");
  sound[2] = minim.loadFile("data/blip.mp3");
  sound[3] = minim.loadFile("data/blop.mp3");
  sound[4] = minim.loadFile("data/blip.mp3");
  sound[5] = minim.loadFile("data/blop.mp3");
  sound[6] = minim.loadFile("data/blip.mp3");
  sound[7] = minim.loadFile("data/blop.mp3");

  particles = new ArrayList<Particle>();
  for (int i = 0; i < 8; i++)
    particles.add(new Particle(100+100*(i%4), height/2-50+100*(floor(i/4)), 50, i ) );
}

void play(int i ) {
  if ( ! sound[i].isPlaying() ) {
    sound[i].rewind();
    sound[i].play();
    println("start play ", i);
  }
}

void draw() {
  background(200,0,200);
  for (Particle p : particles)  p.display();
}

class Particle {
  int x, y, d, idx;
  boolean onlyonce=true;

  Particle (int _x, int _y, int _d, int _idx) {
    x = _x;
    y = _y;
    d = _d;
    idx=_idx;
  }

  boolean over() {
    return ( dist(mouseX, mouseY, x, y) < d/2 );
  }

  void display() {
    stroke(0);
    strokeWeight(1);
    fill(x,y,150);
    if ( over() ) {
      strokeWeight(5);
      if ( onlyonce ) play(idx); //___________________ call global sound handler
      onlyonce = false;
    } else {
      onlyonce = true; //_ only first time
    }    
    ellipse(x, y, d, d);
  }
}

1 Like