• fullscreen
  • Ball.pde
  • Hungry.pde
  • World_of_Colorfulness.pde
  • drawVector.pde
  • class Ball {
      int camp = 0;
      int state = 0;
      boolean dead = false;
      boolean colliding = false;
      color c;
      float cAlpha = 20;
      float r;
      float theta = 0.00;
      PVector loc = new PVector(0, 0);
      PVector vel = new PVector(0, 0);
    
      Ball(float $R) {
        r = $R/2;
        loc.x = random(r,width-(r));
        loc.y = random(r,height-(r));
        vel.x = 0.05*random(-5,5);
        vel.y = 0.05*random(-5,5);
      }
    
      Ball(float $R, int $camp) {
        r = $R/2;
        loc.x = random(r,width-(r));
        loc.y = random(r,height-(r));
        vel.x = 0.05*random(-5,5);
        vel.y = 0.05*random(-5,5);
        camp = $camp;
      }
    
      Ball(float $R, PVector $v, PVector $l) {
        r = $R/2;
        vel = $v.get();
        loc = $l.get();
      }
    
      Ball(float $R, PVector $v, PVector $l, int $camp) {
        r = $R/2;
        vel = $v.get();
        loc = $l.get();
        camp = $camp;
      }
    
      void go(float $i) {
        cAlpha = constrain(cAlpha, minAlpha, maxAlpha);
        removeDead();
        if (!pause) {
          move();
        }
        display(); 
      }
    
      void move(){
        if (dead == false) {
          border();
          loc.add(vel);
          if (gravityOn) {
            vel.add(gravity);
          }
        }
      }
    
      void moveTo(float $x, float $y){
        if (dead == false) {
          border();
          loc = new PVector($x, $y);
        }
      }
    
      private void border(){
        if (loc.y > height-r) {
          vel.y *= -bounce;
          loc.y = height-r;
        }
        else if (loc.y < r) {
          vel.y *= -bounce;
          loc.y = r;
        }
        if (loc.x > width-r) {
          vel.x *= -bounce;
          loc.x = width-r;
        }
        else if (loc.x < r) {
          vel.x *= -bounce;
          loc.x = r;
        }
      }
    
      void display(){
        if (dead == false) {
          noStroke();
          r = constrain(r, 0, width+height/8);
          fillAs();
          fill(c);
          ellipse(loc.x, loc.y, r*2, r*2);
        }
      }
    
      void fillAs() {
        switch (camp) {
        case 1:
          c = color(255, 100, 100, cAlpha);
          break;
        case 2:
          c = color(255, 240, 100, cAlpha);
          break;
        case 3:
          c = color(50, 144, 255, cAlpha);
          break;
        case 0:
          c = color(0, cAlpha);
          break;
        }
      }
    
      void removeDead() {
        if(r < 0.5) {
          dead = true;
          loc.x = -100;
          loc.y = -100;
        }
      }
    
      boolean isInRangeAndBigger(Ball $b1, Ball $b2, float range){
        if ($b1.dead == false && $b2.dead == false) {
          float distance = dist($b1.loc.x, $b1.loc.y, $b2.loc.x, $b2.loc.y);
          if (distance < $b1.r*range + $b2.r*range) {
            if($b1.r > $b2.r) {
              return true;
            }
            else return false;
          }
          else return false;
        }
        else return false;
      }
    
      boolean isInRange(Ball $b1, Ball $b2, float $range){
        if ($b1.dead == false && $b2.dead == false) {
          float distance = dist($b1.loc.x, $b1.loc.y, $b2.loc.x, $b2.loc.y);
          if (distance < $b1.r*$range + $b2.r*$range) {
            return true;
          }
          else return false;
        }
        else return false;
      }
    
      void collideEqualMass(Ball $t) {
        float d = PVector.dist(loc, $t.loc);
        float sumR = r + $t.r;
        if (!colliding && d < sumR) {
          colliding = true;
          PVector n = PVector.sub($t.loc, loc);
          n.normalize();
          PVector u = PVector.sub(vel, $t.vel);
          PVector un = componentVector(u,n);
          u.sub(un);
          vel = PVector.add(u, $t.vel);
          $t.vel = PVector.add(un, $t.vel);
        } 
        else if (d > sumR) {
          colliding = false;
        }
      }
    
    }
    
    PVector componentVector (PVector vector, PVector directionVector) {
      directionVector.normalize();
      directionVector.mult(vector.dot(directionVector));
      return directionVector;
    }
    
    class Hungry {
      float assimilation;
      float reduction;
    
      Hungry(float $tempAssimilation, float $tempReduction) {
        assimilation = $tempAssimilation;
        reduction = $tempReduction;
      } 
    
      void hunger(int $thisBall, Ball[] $tempBalls) {
        if (!pause) {
          for (int i=0; i<$tempBalls.length; i++){
            if (i != $thisBall) {
              Ball tempBallObjective = $tempBalls[i];
              if ($tempBalls[$thisBall].camp == tempBallObjective.camp) {
                if ($tempBalls[$thisBall].isInRangeAndBigger($tempBalls[$thisBall], tempBallObjective, 1)) {
                  $tempBalls[$thisBall].cAlpha += tempBallObjective.cAlpha/tempBallObjective.r/5;
                  tempBallObjective.cAlpha -= tempBallObjective.cAlpha/tempBallObjective.r/5;
                  $tempBalls[$thisBall].r += assimilation/PI/2;
                  tempBallObjective.r -= reduction/2;
                }
              }
              else if (PVector.dist($tempBalls[$thisBall].loc, tempBallObjective.loc)+tempBallObjective.r < $tempBalls[$thisBall].r) {
                tempBallObjective.r -= $tempBalls[$thisBall].r/$tempBalls[$thisBall].cAlpha;
              }
              else {
                Balls[$thisBall].collideEqualMass(Balls[i]);
              }
            }
          }
        }
      }
    
    }
    
    /*
    World of Colorfulness
     by Foo Shun @NCKU, TW on 29 May 2009
     fooshun@gmail.com
     
     code modified and combined from:
     "CollisionEqualMass" by Daniel Shiffman
     http://www.shiffman.net
     "BallWord in Grid" by pablo.vazquez
     http://www.openprocessing.org/visuals/?visualID=817
     
     click mouse: accelerate
     press [SPACE]: pause
     press [g]: gravity on/off
     press [r]: start a new world
     press [v]: show ball's vector on/off
     press [1]: background redraw on (white)
     press [2]: background redraw on (transparent white)
     press [3]: background redraw off
     
     when this apllet starts, balls are positioned in a grid or random place.
     
     there are up to 4 different camps of balls, 
     balls can be assembled to be bigger and their color would be darker, 
     and balls of different camps would collide;
     but if the ball is inside of the other, 
     the smaller one would be gradually wiped out.
     */
    
    int maxBalls = 1000;
    int camps;
    float minSize;
    float maxAlpha = 220;
    float minAlpha = 5;
    float acc = 0.03;
    float bounce = 1.0;
    float bgAlpha = 255;
    boolean showVectors = false;
    boolean pause = false;
    boolean gravityOn = false;
    PVector gravity = new PVector(0.0, 0.125);
    Ball[] Balls = new Ball[maxBalls];
    Hungry hungry = new Hungry(1.0, 1.0);
    
    void setup() {
      background(255);
      size(612, 315, P2D);
      smooth();
      setBalls();
      frameRate(30);
    }
    
    void draw() {
      if (bgAlpha != 0) {
        fill(255, bgAlpha);
        rect(0, 0, width, height);
      }
    
      for (int i=0;i < Balls.length;i++) {
        if (Balls[i].dead == false) {
          hungry.hunger(i, Balls);
          Balls[i].go(i);
        }
      }
      if (showVectors) {
        for (int i = 0; i < Balls.length; i++) {
          drawVector(Balls[i].vel, Balls[i].loc, 10);
        }
      }
      if (mousePressed) {
        for (int i=0;i < Balls.length;i++) {
          if (Balls[i].dead == false) { 
            PVector tempVector = new PVector(acc*random(-5, 5), acc*random(-5,5));
            Balls[i].vel.add(tempVector);
          }  
        }
      }
      if (pause) {
        println();
        println();
        println("paused");
      }
      else {
        println();
        println("minSize = " + minSize);
        println("camps = " + camps);
      }
    }
    
    void setBalls() {
      camps = (int)random(4)+1;
      minSize = (screen.width+screen.height)/400*(0.75+camps/4);
      for (int i=0;i < Balls.length;i++) {
        Balls[i] = new Ball(random(minSize, minSize+1), (int)random(camps));
      }
      int ballIndex = 0;
      int gridX = 12;
      int gridY = 15;
      if (random(2) < 1) {
        for (int y=1; y < height/gridY; y++){
          for (int x=1;x < width/gridX; x++){
            Balls[ballIndex].moveTo(x*gridX, y*gridY);
            if(ballIndex < maxBalls-1) { 
              ballIndex++; 
            } 
          }
        }
      }
    }
    
    void keyPressed() {
      switch(key) {
      case ' ':
        pause = !pause;
        break;
      case 'r':
        setBalls();
        break;
      case 'v':
        showVectors = !showVectors;
        break;
      case 'g':
        gravityOn = !gravityOn;
        break;
      case '1':
        bgAlpha = 255;
        break;
      case '2':
        bgAlpha = 50;
        break;
      case '3':
        bgAlpha = 0;
        break;
      }
    
    }
    
    
    void drawVector(PVector $v, PVector $loc, float $scayl) {
      pushMatrix();
      float arrowsize = 6;
      translate($loc.x, $loc.y);
      stroke(150);
      rotate($v.heading2D());
      float len = $v.mag()*$scayl;
      line(0, 0, len, 0);
      line(len, 0, len-arrowsize, +arrowsize/2);
      line(len, 0, len-arrowsize, -arrowsize/2);
      popMatrix();
    }
    

    code

    tweaks (0)

    about this sketch

    This sketch is running as Java applet, exported from Processing.

    license

    advertisement

    Foo Shun

    World of Colorfulness

    Add to Faves Me Likey@! 4
    You must login/register to add this sketch to your favorites.

    code modified and combined from:
    "CollisionEqualMass" by Daniel Shiffman
    http://www.shiffman.net
    "BallWord in Grid" by pablo.vazquez
    http://www.openprocessing.org/visuals/?visualID=817

    press mouse: accelerate
    press [SPACE]: pause
    press [g]: gravity on/off
    press [r]: start a new world
    press [v]: show ball's vector on/off
    press [1]: background redraw on (white)
    press [2]: background redraw on (transparent white)
    press [3]: background redraw off

    up to 4 colors of balls

    You need to login/register to comment.