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