Change Color Moving

It is possible but the implementation will take a bit of design.
Here I have done the demonstration. I hope you can use it and you can gain something for duture demos.

Kf


//INSTRUCTIONS:
// * Drag any static color box into inside the resizing colored areas and experience 
//   the coupling between static and dynamic figures:
//   - Orange couples with yellow
//   - Green couples with red
//   - Violet couples with blue

color red = #FF0004;
color yellow = #F2F700;
color blue = #0A30FF;
color black = #000000;
color white = #FFFFFF;
color green = #08FF79;
color purple = #E108FF;
color orange = #FFA908;

Oscillator2D randomPosition;

StaticSquare sq1;
StaticSquare sq2;
StaticSquare sq3;

DynamicSquare dynamicSq1;
DynamicSquare dynamicSq2;
DynamicSquare dynamicSq3;

void settings() {
  size(600, 600);
}
void setup() {
  background(black);
  //frameRate(50);
  surface.setTitle("Mondrian");

  randomPosition=new Oscillator2D();
  float rx=randomPosition.getX();
  float ry=randomPosition.getY();

// * Normal Squares are defined by top left corner's position, width and height
// * Static and dynamic squares follow this internally. 
// * However, dynamic squares are constructed using the top left corner and bottom 
//   right corner and internalized to top left corner, witdth and height

  dynamicSq3=new DynamicSquare(yellow);
  dynamicSq3.setCorners(0, 120, rx, ry);  
  dynamicSq1=new DynamicSquare(red);  
  dynamicSq1.setCorners(0, ry, rx, height); 
  dynamicSq2=new DynamicSquare(blue); 
  dynamicSq2.setCorners(rx, ry, width, height); 

  sq1=new StaticSquare(160, 20, 80, 80, green);
  sq2=new StaticSquare(260, 20, 80, 80, purple);
  sq3=new StaticSquare(360, 20, 80, 80, orange);
}

void draw() {
  background(black); 
  randomPosition.update();
  float rx=randomPosition.getX();
  float ry=randomPosition.getY();

  dynamicSq3.updateX2(rx);
  dynamicSq3.updateY2(ry);

  dynamicSq1.updateX2(rx);
  dynamicSq1.updateY1(ry);

  dynamicSq2.updateX1(rx);
  dynamicSq2.updateY1(ry);

  dynamicSq1.draw(sq1);
  dynamicSq2.draw(sq2);
  dynamicSq3.draw(sq3);

  sq1.draw();
  sq2.draw();
  sq3.draw();
}

void mouseReleased() {
  sq1.releaseLock();
  sq2.releaseLock();
  sq3.releaseLock();
}

//================================================
//
//================================================
class NormalSquare {
  float px;
  float py;
  float w;
  float h;
  color c;

  NormalSquare(float px, float py, float width, float height, color c) {
    this.px=px;
    this.py=py;
    this.w=width;
    this.h=height;
    this.c=c;
  }

  void draw() {
    draw(c);
  }

  void draw(color thisColor) {
    fill(thisColor);
    noStroke();
    rect(px, py, w, h);
  }

  void printObj() {
    println(px, py, w, h, c);
  }
}

//================================================
//
//================================================
class DynamicSquare extends NormalSquare {

  DynamicSquare(color c) {
    super(0, 0, 0, 0, c);
  }

  void setCorners(float px1, float py1, float px2, float py2) {
    this.px=px1;
    this.py=py1;
    this.w=px2-px1;  //Calculates width
    this.h=py2-py1;  //Calculates height
  }

  void updateX1(float val) {
    px=val;
    w=width-px;
  }

  void updateY1(float val) {
    py=val;
    h=height-py;
  }

  void updateX2(float val) {
    w=val-px;
  }

  void updateY2(float val) {
    h=val-py;
  }

  void draw(NormalSquare other) {
    if (isOnTop(other))
      draw(other.c);
    else
      draw();
  }

  boolean isOnTop(NormalSquare other) {    
    return px<other.px && px+w>other.px+other.w && py<other.py  && py+h>other.py+other.h;
  }
}

//================================================
//
//================================================
class StaticSquare extends NormalSquare {

  final float INVALID=-1;
  boolean mouseLockOn;

  float mx=INVALID;  //Offset for mouse, negative means not valid
  float my=INVALID;
  float initX;
  float initY;

  StaticSquare(float px, float py, float width, float height, color c) {
    super(px, py, width, height, c);
    initX=px;
    initY=py;
    mouseLockOn=false;
  }

  //@Override
  //  void draw() {
  //  draw(c);
  //}

  @Override
  void draw(color thisColor) {
    if (!mouseLockOn && mousePressed && mouseIsOnTop()) {
      mouseLockOn=true;

      if (mx==INVALID) {
        //Calculate offsets
        mx=mouseX-px;
        my=mouseY-py;
      }
    }

    if (mouseLockOn) {
      px=mouseX-mx;
      py=mouseY-my;
    } 

    fill(thisColor);
    noStroke();
    rect(px, py, w, h);
  }

  boolean mouseIsOnTop(float cornerX1, float cornerX2, float cornerY1, float cornerY2) {
    return mouseX>cornerX1 && mouseX < cornerX2 && mouseY>cornerY1  && mouseY < cornerY2;
  } 

  boolean mouseIsOnTop() {
    return mouseIsOnTop(px, px+w, py, py+h);
  } 
  
  void releaseLock() {
    mouseLockOn=false; 
    px=initX;
    py=initY;
    mx=INVALID;
    my=INVALID;
  }
}

//================================================
//
//================================================
class Oscillator2D {

  class OscillatorEngine {

    float minAbsoluteVal;
    float maxAbsoluteVal;
    float targetPosMin;
    float targetPosMax;
    float vel;
    float cp;  //current pos
    float cv; //current vel


    OscillatorEngine(float min, float max, float vel) {
      minAbsoluteVal=min;
      maxAbsoluteVal=max;
      this.vel=vel;
      initOscillator();
    }

    //Returns random 1 or -1 for direction
    float randomLeftOrRight() {
      return random(1) > 0.5 ? 1.0 : -1.0;
    }

    void initOscillator() {
      cp=random(minAbsoluteVal, maxAbsoluteVal);
      cv=vel*randomLeftOrRight();

      targetPosMin=floor(random(minAbsoluteVal, cp));
      targetPosMax=ceil(random(cp, maxAbsoluteVal));
    }

    void updatePosition() {
      cp = cp + cv;

      if (cp<targetPosMin) {
        cp=targetPosMin; 
        cv=random(vel, 2*vel)*cv/abs(cv)*(-1);
        //Re-caulculate next limit for bounce
        targetPosMax=ceil(random(cp, maxAbsoluteVal));
      }

      if (cp>targetPosMax) {
        cp=targetPosMax; 
        cv=random(vel, 2*vel)*cv/abs(cv)*(-1);
        //Re-caulculate next limit for bounce
        targetPosMin=floor(random(minAbsoluteVal, cp));
      }
    }
  }

  protected OscillatorEngine xOscillator;
  protected OscillatorEngine yOscillator;

  Oscillator2D() {
    xOscillator=new OscillatorEngine(0, width, 1.5);
    yOscillator=new OscillatorEngine(120, height, 1.5);
  }

  void updateX() {
    xOscillator.updatePosition();
  }

  void updateY() {
    yOscillator.updatePosition();
  }

  void update() {
    updateX();
    updateY();
  }

  float getX() {
    return xOscillator.cp;
  }

  float getY() {
    return yOscillator.cp;
  }
}
2 Likes