Mirror effect by mouse movement


#1

Hi, guys,
I have a question how can I mirror my mouse event?
At the moment I have a growing lightningbolt while moving my mouse and I need it mirrored now.
Here is the code

int width = 250;
int height = 250;


//angle of the parts of the bolt
float maxDTheta = PI/10;
float minDTheta = PI/20;
float maxTheta = PI/2;

//CHANCE OF HAVING A CHILD STRIKE 
float childGenOdds = .01;



float minBoltWidth = 1;
float maxBoltWidth = 1;

 float boltLen= 10;


//lenght of the parts of the bolt
float minJumpLength = 1;
float maxJumpLength = 10;

boolean stormMode = true;
boolean fadeStrikes = true;
boolean randomColors = false;
float maxTimeBetweenStrikes = 300;


color boltColor;
color bolt2Color;
color skyColor;

lightningBolt bolt;
lightningBolt2 bolt2;



float lastStrike = 0;
float nextStrikeInNms = 0;



//distance, in milliseconds, of the storm.
float meanDistance = 0;
//if the current time matches the time in this arraylist, it should fire!
ArrayList thunderTimes = new ArrayList();



int value = 0;
int dir = 0;



void setup(){
  colorMode(HSB,100);
  smooth();
  size(600, 800);

  noFill();
  meanDistance = 1000*.5;
  

   background(skyColor);

 



}

void draw(){

  
    boltColor = color(200,200,99);
    bolt2Color = color(80,200,99);


  int maxMouseX= 0;
  float boltLen= 0;
  float boltAdd=0; 
  

  if(mouseX > maxMouseX){
    maxMouseX = mouseX;
    boltLen = boltLen + boltAdd;
    boltAdd = boltAdd+0.01;
  }
  
  else if (mouseX < maxMouseX){
  maxMouseX = mouseX;
 // boltLen = boltLen + boltAdd;
  boltLen = -boltAdd;  
  }
  

  
  if(stormMode && millis()-lastStrike>nextStrikeInNms){//time for a new bolt?
    lastStrike = millis();
    nextStrikeInNms = random(0,maxTimeBetweenStrikes);
    
    //parameters are starting (startung x, startuíng y, thickness, angle of part, minlenght, max lenght, color)  
    

    bolt = new lightningBolt(100,100,random(minBoltWidth,maxBoltWidth),0,minJumpLength,maxJumpLength,mouseX, boltColor);
    bolt.draw();
    
    
    

    
  }
  else{
    if(fadeStrikes){
      noStroke();
      //fill(skyColor);
      rect(0,0,width,height);
      noFill();
    }
  }
}



void stop(){
  //thunderSound.close();
  //minim.stop(); 
  super.stop();
}

int randomSign() //returns +1 or -1
{
  float num = random(-1,1);
  if(num==0)
    return -1;
  else
    return (int)(num/abs(num));
}

color randomColor(){
  return color(random(0,100),99,99);
}

color slightlyRandomColor(color inputCol,float length){
  float h = hue(inputCol);
  h = (h+random(-length,length))%100;
  return color(h,99,99);
}

And also the lightningbolt

class lightningBolt{
  float lineWidth0,theta,x0,y0,x1,y1,x2,y2,straightJump,straightJumpMax,straightJumpMin,lineWidth, btLen;
  color myColor;
  //parameters are starting 
  lightningBolt(float x0I, float y0I, float width0, float theta0, float jumpMin, float jumpMax, float boltLen, color inputColor){

    lineWidth0 = width0;
    lineWidth = width0;
    theta = theta0;
    x0 = x0I;
    y0 = y0I;
    x1 = x0I;
    y1 = y0I;
    x2 = x0I;
    y2 = y0I;
    straightJumpMin = jumpMin;
    straightJumpMax = jumpMax;
    myColor = inputColor;
    btLen = boltLen;
    //it's a wandering line that goes straight for a while,
    //then does a jagged jump (large dTheta), repeats.
    //it does not aim higher than thetaMax
    //(where theta= 0 is down)
    straightJump = random(straightJumpMin,straightJumpMax);
  }

  //tells when the thunder should sound.
  float getThunderTime(){
    return (millis()+meanDistance*(1+random(-.1,.1)));
  }

  void draw()
  {
    //this where you can control the min and max lenght and x y 
    while((y2>0 && y2<200) && (x2>0 && x2<btLen))
    {
      strokeWeight(1);
      
      theta += randomSign()*random(minDTheta, maxDTheta);
      if(theta>maxTheta)
        theta = maxTheta;
      if(theta<-maxTheta)
        theta = -maxTheta;
        
      straightJump = random(straightJumpMin,straightJumpMax);
      x2 = x1-straightJump*sin(theta-HALF_PI);
      y2 = y1-straightJump*cos(theta-HALF_PI);
      
      if(randomColors)
        myColor = slightlyRandomColor(myColor,straightJump);
      
      lineWidth = map(y2, height,y0, 1,lineWidth0);
      if(lineWidth<0)
        lineWidth = 0;
      stroke(myColor);
      strokeWeight(lineWidth);
      line(x1,y1,x2,y2);
      x1=x2;
      y1=y2;
      
      //think about making a fork
      if(random(0,1)<childGenOdds){//if yes, have a baby!
        float newTheta = theta;
        newTheta += randomSign()*random(minDTheta, maxDTheta);
        if(theta>maxTheta)
          theta = maxTheta;
        if(theta<-maxTheta)
          theta = -maxTheta;
//        nForks++;
        (new lightningBolt(x2, y2, lineWidth, newTheta, straightJumpMin, straightJumpMax, btLen, boltColor)).draw();
        //it draws the whole limb before continuing.
      }
    }
  }
}

thank you in advance!


#2

Is this kind of mirroring what you mean?

Horizontal, vertical, or both mirrors
https://editor.p5js.org/abe/sketches/Bya0rYI14
canvas

Mirror with a random angle through the center of the screen
https://editor.p5js.org/abe/sketches/ByPE8YUJN
canvas2


#3

yes the first link is what i need! thanks.
but I don’t know how to link it to the lightningBold.


#4

So drawing something deterministic (non random) twice with vertical symmetry is easy:

void setup() {
  size(600, 600);
  background(255);
  
  // draw something
  drawThing();
  
  // flip the coordinates horizontally
  translate(width, 0);
  scale(-1, 1);
  
  // draw the same thing again
  drawThing();
}
void draw() {}

void drawThing() {
  for(int i=0; i<100; i++) {
    line((i * 7) % 250, 50+i*3,
         (i * 13) % 300, height-50);
  }
}

The difficulty in your case is that it is random, so you need a way to reproduce the same random thing twice.

There’s two approaches I can think of:

  1. You draw the random thing to a PGraphics (it’s like an image) and then you draw that PGraphics two times on the screen, the second time flipped.

  2. You use randomSeed() and noiseSeed() (if you use noise) to reproduce the collection of random numbers you get (so the sequence of random numbers is repeated).

The first option may be faster, because you don’t need to repeat all the calculations to draw the lightning.

It works like this:

PGraphics canvas;
void setup() {
  size(600, 600);
  canvas = createGraphics(width, height);
}
void draw() {
  background(255);

  // Draw everything to the canvas PGraphics
  // instead of drawing to the default window.
  // Every drawing instruction like fill, stroke, line, etc. 
  // must be prepended with "canvas."
  canvas.beginDraw();
  canvas.clear();
  for (int i=0; i<100; i++) {
    canvas.line((i * 7 + frameCount) % 250, 50+i*3, 
      (i * 13) % 300, height-50);
  }
  canvas.endDraw();

  // draw the canvas to the window
  image(canvas, 0, 0);

  // flip coordinate system
  translate(width, 0);
  scale(-1, 1);

  // draw the canvas again, flipped
  image(canvas, 0, 0);
}