Shape vibration

Can anyone suggest how to get the shapes to vibrate on the x axis, once they've been drawn, for the duration of the timer ?

int timer;

PShape[] he = new PShape[4];
PShape[] ha = new PShape[11];
PShape[] m = new PShape[16];

void setup() {
  size(900, 1000, P2D);
  smooth(4);
  noStroke();
  colorMode(HSB, 360, 100, 100, 255);

  for (int i = 0; i < he.length; i++) {  
    he[i] = loadShape("he" + (i+1) + ".svg");
    he[i].disableStyle();
  }
  for (int i = 0; i < ha.length; i++) {  
    ha[i] = loadShape("ha" + (i+1) + ".svg");
    ha[i].disableStyle();
  }
  for (int i = 0; i < m.length; i++) {  
    m[i] = loadShape("m" + (i+1) + ".svg");
    m[i].disableStyle();
  }
}

float b = 360; 
float c = 95;
float d = 100;
float e = 225;

void draw() { 

  if (millis() - timer >= 4000) {
    timer = millis();

    //frameRate(0.2);

    background(random(b), random(c), random(d)); 

    fill(random(b), random(c), random(d), random(e)); 
    shape(he[(int)random(he.length)], random(50, 70), 40, 800, 800);

    fill(random(b), random(c), random(d), random(e));
    shape(ha[(int)random(ha.length)], -70, 0, 800, 860);

    fill(random(b), random(c), random(d)); 
    shape(m[(int)random(m.length)], 200, 440, 300, 300);
  }
}

Answers

  • Perhaps noise()

    like:

    float a = 0.0;
    float noiseScale = 10;
    void setup(){
      size(400,400);
    
    }
    
    void draw(){
      background(200,200,80);
      a+=0.6;
      float x = noise(a)*noiseScale;
      rect(200+x, 100, 50,50);
    
    }
    
  • Thank you for your suggestion - it works nicely on its own, but doesn't, when included with my code below. The shape needs to vibrate inside the timer's 4 second loop ?

    int timer;
    
    PShape[] he = new PShape[4];
    PShape[] ha = new PShape[11];
    PShape[] m = new PShape[16];
    
    float a = 0.0;
    float noiseScale = 10;
    
    void setup() {
      size(900, 1000, P2D);
      smooth(4);
      noStroke();
      colorMode(HSB, 360, 100, 100, 255);
    
      for (int i = 0; i < he.length; i++) {  
        he[i] = loadShape("he" + (i+1) + ".svg");
        he[i].disableStyle();
      }
      for (int i = 0; i < ha.length; i++) {  
        ha[i] = loadShape("ha" + (i+1) + ".svg");
        ha[i].disableStyle();
      }
      for (int i = 0; i < m.length; i++) {  
        m[i] = loadShape("m" + (i+1) + ".svg");
        m[i].disableStyle();
      }
    }
    
    float b = 360; 
    float c = 95;
    float d = 100;
    float e = 225;
    
    void draw() { 
    
      if (millis() - timer >= 4000) {
        timer = millis();
    
        //frameRate(0.2);
    
        background(random(b), random(c), random(d)); 
    
        a+=0.6;
        float x = noise(a)*noiseScale;
    
        fill(random(b), random(c), random(d), random(e)); 
        shape(he[(int)random(he.length)], 20+x, 40, 800, 800);
    
        fill(random(b), random(c), random(d), random(e));
        shape(ha[(int)random(ha.length)], -70, 0, 800, 860);
    
        fill(random(b), random(c), random(d)); 
        shape(m[(int)random(m.length)], 200, 440, 300, 300);
      }
    }
    
  • you aren't adding the noise to the second and third shapes. is that deliberate? just what doesn't work?

    we can't run your example - we don't have the 31 svg files you use - so we are guessing what it does and also guessing what you want it to do.

  • I'd only started with one, to see if it works and would have then applied it to the others. Every 4 seconds a composition of 4 layers of svgs is randomly selected and presented. What i'd like, is to get each shape to move/vibrate on the x axis, all the while, within the 4 seconds of the timer. A shaky picture, if you like...

  • _vk_vk
    edited September 2014

    Looks like your timer logic need an adjust. The way it is, code inside if (millis() - timer >= 4000) will run only once every 4 secs. But the shapes needs to be redrawn every frame to vibrate, also the background so they get erased.

    I believe what you want is one change of set of shapes plus bg, every 4 seconds, and also that shapes vibrate during … well not clear how long the shapes should vibrate.

    I think I would have 4 colors vars, one for each shape and one for bg colour, and then every 4 secs I would pick a new set of shapes and colour for each and bg, and persist with it during 4 secs. This way the actual draw of the shape would be outside timer, being repeated every frame and they would be able to vibrate.

    You might want to experiment with the timer and the shake in a simpler code (like mine) before put it in the main code.

    Also this looks like a call for OOP approach. Maybe a VibratingPShape class… But it can be done the way you are doing also...

    hth

  • Thank you for your comments - you're right about a change of shapes and bg every 4 seconds, with them shaking/vibrating throughout. It's all fairly new to me, so before attempting anything like OOP I wondered about using a function - simplified version below, but when I add the coordinates to drawComp() it says it's " not applicable for the argument "...

    int timer;
    
    PShape[] he = new PShape[4];
    
    float a = 0.0;
    float noiseScale = 10;
    
    void setup() {
      size(900, 1000, P2D);
      smooth(4);
      noStroke();
      colorMode(HSB, 360, 100, 100, 255);
    
      for (int i = 0; i < he.length; i++) {  
        he[i] = loadShape("he" + (i+1) + ".svg");
        he[i].disableStyle();
      }
    
    }
    
    float b = 360; 
    float c = 95;
    float d = 100;
    float e = 225;
    
    void draw() { 
    
      a+=0.6;
      float x = noise(a)*noiseScale;
    
      // ( 20+x, 40); 
      // shape x coordinates needs to be redrawn 60 fps to shake...
    
      drawComp();
    
      //frameRate(0.2);
    }
    
    
    void drawComp() { 
    
      if (millis() - timer >= 4000) {
        timer = millis();
    
        background(random(b), random(c), random(d)); 
    
        fill(random(b), random(c), random(d), random(e)); 
        shape(he[(int)random(he.length)], 20, 40, 800, 800);
      }
    }
    
  • _vk_vk
    edited September 2014

    You see without OOP it goes more complicated actually...

    So, here is the idea. Now they are shaking together, not really cool, to avoid that you will need one different noise for each shape, or... OOP. I let that for u (edited the code) :) Also my color approach is lazy, again OOP would make this much easier.

    The makeShape function is only to replace the sgvs i don't have...

    EDIT: changed code to make noise individual, kind of hackish ... in this procedural way...

    int timer;
    
    PShape[] he = new PShape[20];
    PShape[] displayShapes = new PShape[3];
    color[] colors = new color[3];
    int index;
    
    float[] a = new float[3];
    float[] noise = new float[3];
    float noiseScale = 25;
    
    
    void setup() {
      size(900, 1000, P2D);
      smooth(4);
      noStroke();
      colorMode(HSB, 360, 100, 100, 255);
    
      for (int i = 0; i < he.length; i++) {  
        he[i] = makeShape(int(random(3, 18)), 200);
      }
    
      for (int i = 0; i < a.length; i++) {  
        a[i] = random(0.12, 0.22);
      }
      displayShapes = pickShapes();
      noStroke();
      smooth();
    }
    
    void draw() { 
      background(0, 0, 100, 255);
    
    
      if (millis() - timer >= 4000) {
        displayShapes = pickShapes();
        timer = millis();
      }
    
      for (int i = 0; i < displayShapes.length; i++) { 
        noise[i]+=a[i];
        float x = noise(noise[i])*a[i]*300;
        displayShapes[i].setFill(colors[i]);
        shape(displayShapes[i], 100+ i*300 + x, height/2);
      }
    }
    
    
    
    
    PShape[] pickShapes() {
      int index = int(random(he.length-4));
      PShape[] ss = new PShape[3];
      for (int i = 0; i < ss.length; i++) {
        colors[i] = color(random(360), random(100), random(10, 100), 255);
        ss[i] = he[index+i];
      }
    
      return ss;
    }
    
    
    
    PShape makeShape(int sides, int maxSize) {
      sides = sides >= 2? sides:2;
      float  a, b, c, d;
      float slice = TWO_PI/(float) sides;
    
      float[] angles = new float [sides];
    
      for (int i = 0; i < angles.length; i++ ) {
        angles[i] =  random(slice*i, slice * (i+1));
      }  
    
      float[] mags = new float [sides];
      for (int i = 0; i < mags.length; i++ ) {
    
        mags[i] = random(15, maxSize);
      }
    
      PVector[] vtx = new PVector[sides];
      for (int i = 0; i < vtx.length; i++ ) {
        vtx[i] = new PVector(cos(angles[i])*mags[i], sin(angles[i])*mags[i]);
      }
    
    
      PShape p =  createShape();
      p.beginShape();
    
      for (int i = 0; i < vtx.length; i++ ) {
        p.vertex(vtx[i].x, vtx[i].y);
      }
    
      p.endShape(CLOSE);
      return p;
    }
    
  • Thank you, that's very good - it should be under the 'examples ' ! I've tried adapting your original code but can only get one of the layers to draw ( "he") and I want "ha" and "m" at the same time. ( Independently coloured and vibrating ). I'd also like the background to change every 4 seconds too, though it doesn't need to vibrate - here's what I have so far:

    int timer;
    
    PShape[] he = new PShape[4];
    PShape[] ha = new PShape[11];
    PShape[] m = new PShape[16];
    
    PShape[] displayShapes = new PShape[3];
    color[] colors = new color[3];
    int index;
    
    float a = 0.0;
    float noiseScale = 10;
    
    void setup() {
      size(900, 1000, P2D);
      smooth(4);
      noStroke();
      colorMode(HSB, 360, 100, 100, 255);
    
      for (int i = 0; i < he.length; i++) { 
        he[i] = loadShape("he" + (i+1) + ".svg");
      }
      for (int i = 0; i < ha.length; i++) {  
        ha[i] = loadShape("ha" + (i+1) + ".svg");
      }
      for (int i = 0; i < m.length; i++) {  
        m[i] = loadShape("m" + (i+1) + ".svg");
      }
    
      displayShapes = pickShapes();
      noStroke();
      smooth();
    }
    
    float b = random(360);
    float c = random(95);
    float d = random(100);
    float e = random(225);
    
    void draw() {
      background(b, c, d, e);
      a+=0.6;
      float x = noise(a)*noiseScale;
    
      if (millis() - timer >= 4000) {
        displayShapes = pickShapes();
        timer = millis();
      }
    
      for (int i = 0; i < displayShapes.length; i++) {
        displayShapes[i].setFill(colors[i]);
        shape(displayShapes[i], 100+ i*300 + x, 100);
      }
    }
    
    
    PShape[] pickShapes() {
      int index = int(random(he.length));
    
      PShape[] ss = new PShape[1];
      for (int i = 0; i < ss.length; i++) {
        colors[i] = color(random(360), random(100), random(100), random(255));
        ss[i] = he[index+i];
      }
    
      return ss;
    }
    
  • As you can see, it's getting boring to have all this array holding every variable. A class ShakingShape would make things easier.

    Anyway, here the tweaked code:

    int timer;
    
    PShape[] he = new PShape[4];
    PShape[] ha = new PShape[11];
    PShape[] m = new PShape[16];
    
    PShape[] displayShapes = new PShape[3];
    color[] colors = new color[4];
    float[] noise = new float[3];
    float[] incr = new float[3];
    
    int index;
    
    float noiseScale = 10;
    
    void setup() {
      size(900, 1000, P2D);
      smooth(4);
      noStroke();
      colorMode(HSB, 360, 100, 100, 255);
    
      for (int i = 0; i < he.length; i++) { 
        he[i] = makeShape(int(random(4, 18)), 200);
      }
      for (int i = 0; i < ha.length; i++) {  
        ha[i] = makeShape(int(random(14, 28)), 200);
      }
      for (int i = 0; i < m.length; i++) {  
        m[i] = makeShape(int(random(30, 40)), 200);
      }
    
      for (int i = 0; i < incr.length; i++) {  
        incr[i] = random(0.12, 0.22);
      }
      pickColors();
      displayShapes = pickShapes();
      noStroke();
      smooth();
    }
    
    void draw() {
      background(colors[3]);
    
      if (millis() - timer >= 4000) {
        displayShapes = pickShapes();
        pickColors();
        timer = millis();
      }
    
    
      for (int i = 0; i < displayShapes.length; i++) {
        displayShapes[i].setFill(colors[i]);
        noise[i]+=incr[i];
        float x = noise(noise[i])*incr[i]*300;
        shape(displayShapes[i], 100+ i*300 + x, height/2);
      }
    }
    
    
    PShape[] pickShapes() {
      PShape[] ss = new PShape[3];
      ss[0] = he[int(random(he.length))];
      ss[1] = ha[int(random(ha.length))];
      ss[2] = m[int(random(m.length))];
      return ss;
    }
    
    void pickColors() {
      for (int i = 0; i < colors.length; i++) {  
        colors[i] = color(random(360), random(100), random(10, 100), 255);
      }
    }
    
    
    PShape makeShape(int sides, int maxSize) {
      sides = sides >= 2? sides:2;
      float  a, b, c, d;
      float slice = TWO_PI/(float) sides;
    
      float[] angles = new float [sides];
    
      for (int i = 0; i < angles.length; i++ ) {
        angles[i] =  random(slice*i, slice * (i+1));
      }  
    
      float[] mags = new float [sides];
      for (int i = 0; i < mags.length; i++ ) {
    
        mags[i] = random(15, maxSize);
      }
    
      PVector[] vtx = new PVector[sides];
      for (int i = 0; i < vtx.length; i++ ) {
        vtx[i] = new PVector(cos(angles[i])*mags[i], sin(angles[i])*mags[i]);
      }
    
    
      PShape p =  createShape();
      p.beginShape();
    
      for (int i = 0; i < vtx.length; i++ ) {
        p.vertex(vtx[i].x, vtx[i].y);
      }
    
      p.endShape(CLOSE);
      return p;
    }
    
  • Until I get more proficient with classes and OOP, that's working very well, thank you. Two small queries - I can't find where to put the coordinates and sizes for each shape when it's drawn and it's doing strange things with the transparency of the svg's (showing the under drawing) ?

    int timer;
    
    PShape[] bk = new PShape[8];
    PShape[] he = new PShape[4];
    PShape[] ha = new PShape[11];
    PShape[] m = new PShape[16];
    
    
    PShape[] displayShapes = new PShape[4];
    color[] colors = new color[4]; //?
    float[] noise = new float[4];
    float[] incr = new float[4];
    
    int index;
    
    float noiseScale = 10;
    
    void setup() {
      size(900, 1000, P2D);
      smooth(4);
      noStroke();
      colorMode(HSB, 360, 100, 100, 255);
    
      for (int i = 0; i < bk.length; i++) { 
        bk[i] = loadShape("bk" + (i+1) + ".svg");
        //bk[i].disableStyle();
      } 
      for (int i = 0; i < he.length; i++) { 
        he[i] = loadShape("he" + (i+1) + ".svg");
       // he[i] = makeShape(int(random(4, 18)), 200);
      }
      for (int i = 0; i < ha.length; i++) {  
        ha[i] = loadShape("ha" + (i+1) + ".svg");
      }
      for (int i = 0; i < m.length; i++) {  
        m[i] = loadShape("m" + (i+1) + ".svg");
      }
    
      for (int i = 0; i < incr.length; i++) {  
        incr[i] = random(0.12, 0.22);  // ?
      }
    
      pickColors();
      displayShapes = pickShapes();
      noStroke();
      smooth();
    }
    
    void draw() {
      background(colors[3]);
    
      if (millis() - timer >= 4000) {
        displayShapes = pickShapes();
        pickColors();
        timer = millis();
      }
    
      for (int i = 0; i < displayShapes.length; i++) {
        displayShapes[i].setFill(colors[i]);
        noise[i]+=incr[i];
        float x = noise(noise[i])*incr[i]*60;
        shape(displayShapes[i], 10+ i*30 + x, 100);
      }
    }
    
    PShape[] pickShapes() {
    
      PShape[] ss = new PShape[4];
    
      ss[0] = bk[int(random(bk.length))];
      ss[1] = he[int(random(he.length))];
      ss[2] = ha[int(random(ha.length))];
      ss[3] = m[int(random(m.length))];
    
    return ss;
    }
    
    void pickColors() {
      for (int i = 0; i < colors.length; i++) {  
        colors[i] = color(random(360), random(100), random(10, 90), random(230, 255));
      }
    }
    
  • It's really easy to see where the placement is done. Line 55 in my last code. You need to work how your display logic is going to be. I', using shape(), the version with only 2 parameters.

    Remember We don't have yours svgs...

    I can't help with the transparency. Try to isolate the problem in a simpler code. Perhaps make a new question with that, some one may be able to help. If possible, link to an online shape so people car run the code and see the error.

    I really would encourage you to go for OOP. IMHO it is "THE" thing that gives you the power :). And is just more of the same you already have learned. Not a big deal. It will make all you are looking for, much easier... Have you seen this?

    http://processing.org/tutorials/objects/

  • I'd tried line 55 (yours) but couldn't set the individual shape parameters - it seems to take all four pickShapes together and they won't accept nested parameters ? Thanks for the other advice about svgs and OOP tutorial...

Sign In or Register to comment.