Daily Creative Coding

元「30 min. Processing」。毎日、Creative Codingします。

球の上を動く円

/**
* circles moving on sphere
*
* @author aa_debdeb
* @date 2017/01/15
*/

ArrayList<Circle> circles;

void setup(){
  size(640, 640); 
  circles = new ArrayList<Circle>();
  for(int i = 0; i < 30; i++){
    circles.add(new Circle());
  }
}

void draw(){
  background(255);
  translate(width / 2, height / 2);
  for(Circle circle: circles){
    circle.update();
  }
  circles = sortByZ(circles);
  for(Circle circle: circles){
    circle.render();
  }
}

ArrayList<Circle> sortByZ(ArrayList<Circle> circles){
  ArrayList<Circle> sorted = new ArrayList<Circle>();
  while(!circles.isEmpty()){
    Circle minC = circles.get(0);
    for(Circle c: circles){
      if(c.getZ() < minC.getZ()){
        minC = c;
      }
    }
    sorted.add(minC);
    circles.remove(minC);
  }
  return sorted;
}

class Circle {

  float angle1, angle2;
  float angleSpeed1, angleSpeed2;
  
  Circle(){
    angle1 = random(TWO_PI);
    angle2 = random(TWO_PI);
    PVector angleSpeed = new PVector(random(-1, 1), random(-1, 1), random(-1, 1));
    angleSpeed.normalize(); 
    angleSpeed1 = atan(sqrt(sq(angleSpeed.x) + sq(angleSpeed.y)) / angleSpeed.z) * 0.03;
    angleSpeed2 = atan(angleSpeed.y / angleSpeed.x) * 0.03;
  }
  
  void update(){
    angle1 += angleSpeed1;
    angle2 += angleSpeed2;  
  }
  
  float getZ(){
    return cos(angle1);
  }
  
  void render(){
    float radius = 200;
    float x = radius * sin(angle1) * cos(angle2);
    float y = radius * sin(angle1) * sin(angle2);
    float z = radius * cos(angle1);
    float sizeX = map(abs(x), 0, radius, 40, 10) * map(z, -radius, radius, 0.5, 1);
    float sizeY = map(abs(y), 0, radius, 40, 10) * map(z, -radius, radius, 0.5, 1);
    stroke(255);
    strokeWeight(3);
    fill(lerpColor(color(#CAE7F2), color(#007FB1), map(z, -radius, radius, 0, 1)));
    pushMatrix();
    translate(x, y);
    ellipse(0, 0, sizeX, sizeY);
    popMatrix();
  }
  
}
f:id:aa_debdeb:20170110211333j:plain