diff --git a/Laundromat/Laundromat.pde b/Laundromat/Laundromat.pde index 9ad258f..334e6f4 100644 --- a/Laundromat/Laundromat.pde +++ b/Laundromat/Laundromat.pde @@ -1,10 +1,10 @@ /* - *For New Users: - *Don't forget to change your midi device. - *Eventually there will be a midi selector as part of the ui. - *Todo on github: https://github.com/teesloane/laundromat/issues/4 - *Contributions welcome! -*/ + *For New Users: + *Don't forget to change your midi device. + *Eventually there will be a midi selector as part of the ui. + *Todo on github: https://github.com/teesloane/laundromat/issues/4 + *Contributions welcome! + */ import fisica.*; import themidibus.*; @@ -35,6 +35,9 @@ float Rotation = 2; float Gravity = 5; float Friction = 0; float DeShape = 0; +float Sides = 6; +float SideLength = 100; +float oldSides = 6;//This is used to see if the slider sides value has changed. VKey[] keyboard = new VKey[12]; String[] notes = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B", }; @@ -42,7 +45,8 @@ String[] notes = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B void setup() { // init libraries / classes MidiBus.list(); - myBus = new MidiBus(this, 1, selectedMidiDevice); + myBus = new MidiBus(this, -1, selectedMidiDevice); + Fisica.init(this); world = new FWorld(); cp5 = new ControlP5(this); @@ -50,7 +54,7 @@ void setup() { size(640, 480); smooth(); - createWm(); + createWmRadius(int(Sides), 100); createInterface(); } @@ -58,19 +62,43 @@ void setup() { void draw() { background(55); - wM.adjustRotation(Rotation/150); - + wM.setRotation(wM.getRotation()+Rotation/150); world.setGravity(0, Gravity *25); world.draw(); world.step(); // check for contact / fire midi notes. - for (Ball b : balls) { - if (b != null) { - b.checkContact(b); - b.startTimer(); - b.updateFriction(); + for (int i = 0; i < maxBalls; i++) { + // for (Ball b : balls) { + if (balls[i] != null) { + balls[i].checkContact(balls[i]); + balls[i].startTimer(); + balls[i].updateFriction(); + if (balls[i].getX() < -5 || balls[i].getX() > width + 5|| balls[i].getY() > height + 5|| balls[i].getY() < 0) { + world.remove(balls[i]); + balls[i]= null; + ballCount --; + } } } - -} \ No newline at end of file +} + +//This is called when any slider is clicked. +void controlEvent(ControlEvent Event) { + String name = Event.getController().getName(); + if (name =="Sides" || name == "SideLength"|| name == "DeShape") //If it is one of the sliders + { + //floor rounds the values down to the nearest integer. This is usefull because sliders + //only output floats and we want to use ints. + if (floor(Event.getController().getValue()) != floor(oldSides)) { //And the value has changed + float angle = wM.getRotation(); + oldSides = Sides; + world.remove(wM); //remove the old washing machine + createWmRadius(int(Sides), SideLength); //create a new one in its place + wM.setRotation(angle); + } + } +} + + + \ No newline at end of file diff --git a/Laundromat/ball.pde b/Laundromat/ball.pde index ab941b1..2b0f5a0 100644 --- a/Laundromat/ball.pde +++ b/Laundromat/ball.pde @@ -3,13 +3,14 @@ class Ball extends FCircle { int midiNote; boolean inContact; int contactTimer; - + int channel = 1; + int holdTime = 100; Ball(float irad, int note) { super(irad); - + this.midiNote = note; this.setPosition(width/2, height/2); - this.setVelocity(0, 100); + this.setVelocity(0, 150); this.setBullet(true); this.setRestitution(1); this.setNoStroke(); @@ -24,32 +25,26 @@ class Ball extends FCircle { this.setDamping(Friction); } - // semi-done: time check to turn note off on wall rolling. + //time check to turn note off on wall rolling. void checkContact(Ball b) { - + if (b.isTouchingBody(wM)) { this.inContact = true; - if ((millis() - this.contactTimer) > 100) { - myBus.sendNoteOn(0, b.midiNote, 100); - } - - // necessary? - - if ((millis() - this.contactTimer) < 20){ - myBus.sendNoteOff(0, b.midiNote, 100); + if ((millis() - this.contactTimer) > 50) { + myBus.sendNoteOn(1, b.midiNote, 100); } - } else { + if ((millis() - this.contactTimer) > holdTime) { + myBus.sendNoteOff(1, b.midiNote, 100); + } + this.inContact = false; } } - - void startTimer(){ + + void startTimer() { if (this.inContact) { this.contactTimer = millis(); } - - println(this.contactTimer, millis()); // millis keeps running, contactTimer updates on contact. } - } \ No newline at end of file diff --git a/Laundromat/create_container.pde b/Laundromat/create_container.pde index 16e33f4..93107b7 100644 --- a/Laundromat/create_container.pde +++ b/Laundromat/create_container.pde @@ -1,67 +1,56 @@ void createWm() { - wM = createWashingMachine(); + wM = createNsideWashingMachine(6, 80); wM.setPosition(width/2, height/2 + height/12); wM.setBullet(true); wM.setStatic(true); world.add(wM); } +void createWm(int Nsides, float sideLength) { + wM = createNsideWashingMachine(Nsides, sideLength); + wM.setPosition(width/2, height/2 + height/12); + wM.setBullet(true); + wM.setStatic(true); + world.add(wM); +} +void createWmRadius(int Nsides, float radius) { + wM = createNsideWashingMachineByRadius(Nsides, radius); + wM.setPosition(width/2, height/2 + height/12); + wM.setBullet(true); + wM.setStatic(true); + world.add(wM); +} -/* ===== Compound Shape : wM Creation ===== */ -FCompound createWashingMachine() { + +FCompound createNsideWashingMachine(int Nsides, float sideLength) { float hexColour = 240; - float boxLong = 80; + float boxLong = sideLength; float boxThin = 5; - float dist = sqrt(3)*boxLong; - float sideShrink = dist / 40; - float diagX = dist / 4-2; - float diagY = dist / 2.35; - - FBox left = new FBox(boxThin, boxLong); - left.setPosition(-dist/2 + sideShrink, 0); - left.setFill(hexColour); - left.setNoStroke(); - - FBox right = new FBox(boxThin, boxLong); - right.setPosition(dist/2 - sideShrink, 0); - right.setFill(hexColour); - right.setNoStroke(); - FBox topRight = new FBox(boxThin, boxLong); - topRight.setPosition(0, 0); - topRight.setRotation(-45 + DeShape); - topRight.adjustPosition(diagX, -diagY); - topRight.setFill(hexColour); - topRight.setNoStroke(); - FBox topLeft = new FBox(boxThin, boxLong); - topLeft.setPosition(0, 0); - topLeft.adjustPosition(-diagX, -diagY); - topLeft.setRotation(45 + DeShape); - topLeft.setFill(hexColour); - topLeft.setNoStroke(); + /*The inradius of the polygon. This distance from the center point to the mid point of the side. + The '-(boxThin/2)' part brings all the sides in a little bit to clean up the corners. Serves the same + purpose as sideShrink in the original createWashingMachine, I think. + Does not work on triangles, the angles are too small for this method to work properly, works well + on all other regular polygons. + */ + float radius =((boxLong/2) * 1/(tan(PI/Nsides)))-(boxThin/2); - FBox bottomLeft = new FBox(boxThin, boxLong); - bottomLeft.setPosition(0, 0); - bottomLeft.adjustPosition(-diagX, diagY); - bottomLeft.setRotation(-45 + DeShape); - bottomLeft.setFill(hexColour); - bottomLeft.setNoStroke(); + FCompound wM = new FCompound(); - FBox bottomRight = new FBox(boxThin, boxLong); - bottomRight.setPosition(0, 0); - bottomRight.adjustPosition(diagX, diagY); - bottomRight.setRotation(45 + DeShape); - bottomRight.setFill(hexColour); - bottomRight.setNoStroke(); + for (int i = 0; i< Nsides; i++) { + FBox side = new FBox(boxThin, boxLong); + side.setPosition(radius * cos(2*PI*i/Nsides), radius * sin(2*PI*i/Nsides)); + side.setRotation(((TWO_PI/Nsides)*i)+ radians(-DeShape)); - FCompound wM = new FCompound(); - wM.addBody(left); - wM.addBody(right); - wM.addBody(topRight); - wM.addBody(topLeft); - wM.addBody(bottomLeft); - wM.addBody(bottomRight); + side.setFill(hexColour); + side.setNoStroke(); + wM.addBody(side); + } return wM; +} + +FCompound createNsideWashingMachineByRadius(int Nsides, float radius) { + return createNsideWashingMachine(Nsides, 2*radius*tan(PI/Nsides)); } \ No newline at end of file diff --git a/Laundromat/gui_controls.pde b/Laundromat/gui_controls.pde index f543f79..3273668 100644 --- a/Laundromat/gui_controls.pde +++ b/Laundromat/gui_controls.pde @@ -8,7 +8,7 @@ void createSlider(String knobName, float rangeA, float rangeZ, float defValue, f .setValue(defValue) .setPosition(posX, posY) .setDecimalPrecision(0) - .setSize(width/2, 15) + .setSize(width/2, 10) .setColorForeground(sliderForeground) .setColorBackground(sliderBackground) .setColorActive(sliderActive); @@ -21,14 +21,15 @@ void createInterface() { } // UI Knobs. - float sliderY = 30; + float sliderY = 15; createSlider("Rotation", -10, 10, 1.5, width/2 - width/4, sliderY); createSlider("Gravity", 0, 20, 10, width/2 - width/4, sliderY*2); createSlider("Friction", 0, 1, 0, width/2 - width/4, sliderY*3); + createSlider("Sides", 4, 10, 6, width/2 - width/4, sliderY*4); + createSlider("SideLength", 40, 100, 70, width/2 - width/4, sliderY*5); + createSlider("DeShape", 0, 90, 0, width/2 - width/4, sliderY*6); } - - /* ========= Class for creating a key in the keyboard ========== */ class VKey { @@ -74,6 +75,7 @@ class VKey { if (ballCount <= maxBalls) { balls[ballCount] = new Ball(10, midiNote); + ballCount += 1; }