• fullscreen
  • BallClass.pde
  • NodeGardenPlus.pde
  • checkCollision.pde
  • menu.pde
  • class Ball {// I'm not going to comment on all of this
      float x, y;
      float diameter;
      float vx = 0;
      float vy = 0;
      float lastX;
      float lastY;
      int id;
      Ball[] others;
    
      Boolean canGrab=true;
    
      Ball(float xin, float yin, float din, int idin, Ball[] oin) {
        x = xin;
        y = yin;
        diameter = din;
        id = idin;
        others = oin;
      } 
    
      void update() {
      }
    
      void collide() {//the first way of checking collison
        for (int i = id + 1; i < currBallNum; i++) {
          float dx = others[i].x - x;
          float dy = others[i].y - y;
          float distance = sqrt(dx*dx + dy*dy);
          float minDist = others[i].diameter/2 + diameter/2;
          if (distance <= minDist) { 
            float angle = atan2(dy, dx);
            float targetX = x + cos(angle) * minDist;
            float targetY = y + sin(angle) * minDist;
            float ax = (targetX - others[i].x) * spring;
            float ay = (targetY - others[i].y) * spring;
            vx -= ax;
            vy -= ay;
            others[i].vx += ax;
            others[i].vy += ay;
          }
        }
      }
    
      void colorize() {
        float dx=others[2].x - x;
        float dy=others[2].y - y;
        for (int i = id + 1; i < currBallNum; i++) {
          dx = others[i].x - x;
          dy = others[i].y - y;
        }
        float distance = sqrt(dx*dx + dy*dy);
        
        if(keyPressed && key!=' ') numbs=key;
        
        switch(numbs){// create more colors for keybord numbers
          case('1')://done
          fill(255-distance,255,distance-255, 255-ballFade);
          break;
          case('2')://done
          fill(255,255-distance,distance-255, 255-ballFade);
          break;
          case('3')://done
          fill(255-distance,distance-255,255, 255-ballFade);
          break;
          case('4')://done
          fill(255,255-distance,255, 255-ballFade);
          break;
          case('5')://done
          fill(distance-255,distance,255-distance, 255-ballFade);
          break;
          case('6')://done
          fill(255,distance-255,distance-255, 255-ballFade);
          break;
          case('7')://done
          fill(255-distance,distance -255,distance-255, 255-ballFade);
          break;
          case('8')://done
          fill(distance-255,255-distance,255, 255-ballFade);
          break;
          case('9')://done
          fill(0,distance-255,255-distance, 255-ballFade);
          break;
          case('0'):
          fill(255, 255-ballFade);
          break;
          default:
          fill(255-distance,255,distance-255, 255-ballFade);
          break;
        }
      }
    
    
    
      void gravitate() {
        for (int i = id + 1; i < currBallNum; i++) {
          float dx = others[i].x - x;
          float dy = others[i].y - y;
          float distance = sqrt(dx*dx + dy*dy);
    
          float rto;
          if(x <= others[i].x) rto = 180;
          else rto = 0;
    
          float rot = atan((y-others[i].y)/(x-others[i].x))+radians(rto);
    
          vx -= ((diameter*(massToScale))/(distance))*cos(rot);
          vy -= ((diameter*(massToScale))/(distance))*sin(rot);
          others[i].vx += ((diameter*(massToScale))/(distance))*cos(rot);
          others[i].vy += ((diameter*(massToScale))/(distance))*sin(rot);
        }
      }
    
      void connect() {
        for (int i = id + 1; i < currBallNum; i++) {
          float dx = others[i].x - x;
          float dy = others[i].y - y;
          float distance = sqrt(dx*dx + dy*dy);
          stroke(255-distance,distance-255,255,255-distance -lineFade +lineLength);
          strokeWeight(abs(300-distance)/20 /(lineLength*0.001+1));
          line(x,y, others[i].x,others[i].y);
        }
      }
    
      void grab() {
        float dx = mouseX - x;
        float dy = mouseY - y;
        float distance = sqrt(dx*dx + dy*dy);
        if ((distance <= diameter/2 && mousePressed && canGrab && (!isOpen || mouseX<width-150))) {
    
          lastX=x;
          lastY=y;
    
          x=mouseX-dx;
          y=mouseY-dy;
    
          vx= mouseX -lastX;
          vy= mouseY -lastY;
    
          for (int i = id + 1; i < currBallNum; i++) {
            others[i].canGrab=false;
          }
        } 
        else if(!mousePressed) {
          for (int i = id + 1; i < currBallNum; i++) {
            others[i].canGrab=true;
          }
        }
      }
    
      void applyAirFriction() {
        vx -= friction*vx;
        vy -= friction*vy;
      }
    
    
      void move() {
        vy += gravity;
        x += vx;
        y += vy;
        if (x + diameter/2 > width/theScale) {
          x = width/theScale - diameter/2;
          vx *= -wallBounce; 
          //vx=-vx;
        }
        else if (x - diameter/2 < 0) {
          x = diameter/2;
          vx *= -wallBounce;
          //vx=-vx;
        }
        if (y + diameter/2 > height/theScale) {
          y = height/theScale - diameter/2;
          vy *= -wallBounce; 
          // vy=-vy;
        } 
        else if (y - diameter/2 < 0) {
          y = diameter/2;
          vy *= -wallBounce;
          // vy=-vy;
        }
      }
    
    
      void display() {
        //  fill(255, 204);
        noStroke();
        ellipse(x, y, diameter, diameter);
      }
    }
    
    //node gardan with options!
    
    int theScale=1;//had this when trying to short cut the program into fullScreen
    
    int numBalls = 23;//variable you can edit inside the program!
    float spring = 1;
    float massToScale=0.1;
    float gravity = 0.0;
    float friction = 0.0000;
    float wallBounce = 0.9;
    Ball[] balls = new Ball[numBalls];
    
    Boolean isSmooth=false;
    Boolean tFR=false;
    int backFade=0;
    int ballFade=0;
    int lineFade=0;
    int lineLength=0;
    char numbs='1';
    
    void setup() 
    {
    //  size(screen.width/(3-theScale), screen.height/(3-theScale));//size math for easy changeing to fullscreen
      //fullScreen is very laggy though
      
      size(960,600);
      noStroke();
      for (int i = 0; i < numBalls; i++) {// here I create all the balls
        balls[i] = new Ball(random(width/theScale), random(height/theScale), random(30, 100), i, balls);
      }
    }
    
    void draw() 
    {
    //  scale(theScale);//pointless
      if(isSmooth) smooth();//alternates between smoothing and not smoothing
      else if(!isSmooth) noSmooth();
    
      blurrbackground(0,0,0,255-backFade);// creates that blurry effect
    
      for (int i = 0; i < currBallNum; i++) {//runs through all the balls
        balls[i].applyAirFriction();
        balls[i].gravitate();
        if(spring==1)//switches between two different ways of calculating collision
          for(int j=0; j<currBallNum;j++) {//depending on the spring input
            if(i!=j)
              checkCollision(balls[i],balls[j]);
          } 
        else
          balls[i].collide();
        balls[i].move();
        balls[i].grab();
        balls[i].colorize();
        balls[i].display();//then we draw the ball
      }
      for (int i = 0; i < currBallNum; i++) {
        balls[i].connect();//a seperate array for drawing lines  just because I can
      }
      menu(width/theScale-150,0);
      theFrameRate();
    }
    
    
    void checkCollision(Ball ball0, Ball ball1)// the second way of checking collision
    {
      float dx = ball1.x - ball0.x;
      float dy = ball1.y - ball0.y;
      float dist = sqrt(dx*dx + dy*dy);
    
      if(dist < ball0.diameter/2 + ball1.diameter/2)
      {
        //calculate angle, sine and cosine
        float angle = atan2(dy, dx);
        float sine = sin(angle);
        float cosine = cos(angle);
    
        //rotate ball0's position
        PVector pos0 = new PVector(0, 0);
    
        //rotate ball1's position
        PVector pos1 = rotateC(dx, dy, sine, cosine, true);
    
        //rotate ball0's velocity
        PVector vel0 = rotateC(ball0.vx, ball0.vy, sine, cosine, true);//uhhh
    
        //rotate ball1's velocity
        PVector vel1 = rotateC(ball1.vx, ball1.vy, sine, cosine, true);
    
        //collision reaction
        float vxTotal = vel0.x - vel1.x;
        vel0.x = ((ball0.diameter - ball1.diameter) * vel0.x + 2 * ball1.diameter * vel1.x) / (ball0.diameter + ball1.diameter);
        vel1.x = vxTotal + vel0.x;
    
        //update positions
        float absV = abs(vel0.x) + abs(vel1.x);
        float overlap = (ball0.diameter/2 + ball1.diameter/2) - abs(pos0.x - pos1.x);
        pos0.x += vel0.x / absV * overlap;
        pos1.x += vel1.x / absV * overlap;
    
        //rotate positions back
        PVector pos0F = rotateC(pos0.x, pos0.y, sine, cosine, false);
        PVector pos1F = rotateC(pos1.x, pos1.y, sine, cosine, false);
    
        //adjust positions to actual screen positions
        //this stops the balls from going through each other
        ball1.x = ball0.x + pos1F.x;
        ball1.y = ball0.y + pos1F.y;
        ball0.x = ball0.x + pos0F.x;
        ball0.y = ball0.y + pos0F.y;
    
        //rotate velocties back
        PVector vel0F = rotateC(vel0.x, vel0.y, sine, cosine, false);
        PVector vel1F = rotateC(vel1.x, vel1.y, sine, cosine, false);
        //so this makes the balls bounce off each other 
        ball0.vx = vel0F.x*spring;
        ball0.vy = vel0F.y*spring;
        ball1.vx = vel1F.x*spring;
        ball1.vy = vel1F.y*spring;
      }
    }
    
    PVector rotateC(float x, float y, float sine, float cosine, boolean anticlock)
    {
      PVector result = new PVector(0, 0);
    
      if(anticlock)
      {
        result.x = x * cosine + y * sine;
        result.y = y * cosine - x * sine;
      }
      else
      {
        result.x = x * cosine - y * sine;
        result.y = y * cosine + x * sine;
      }
      return result;
    }
    
    
    Boolean isOpen=false;
    Boolean canOpen=true;
    
    //this was created for using math on making this work on fullScreen
    float mousex=mouseX;
    float mousey=mouseY;
    
    int currBallNum=10;
    
    //heightGrid
    float hg =screen.height/25;
    
    void menu(int x,int y) {
      
      hg=width/20/theScale;
      mousex=mouseX/theScale;
      mousey=mouseY/theScale;
      
      stroke(56,80,255,100);
      strokeWeight(1);
      fill(0);
      rect(x,y, 150,20);
      
      if(mousex>x && mousex<x+150 && mousey>y && mousey<y+20 && !mousePressed)fill(36,60,240,255);
      else fill(36,60,240,100);
      rect(x,y, 150,20);
      fill(255,200);
      text("Options menu",x+5,y+15);
    
      if(mousex>x && mousex<x+150 && mousey>y && mousey<y+20 && mousePressed && canOpen) {
        isOpen=!isOpen;
        canOpen=false;
        fill(0,backFade);
        noStroke();
        rect(x,y, 150,height);
      } 
      else if(!mousePressed) canOpen=true;
    
      if(isOpen) {
    
        fill(0,backFade);
        rect(x,y+20, 150,height-20);
        
        fill(36,60,240,100);
        rect(x,y, 150,height);
    
        fill(200);
        text("Number of balls",x+15,y+hg);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+140 && mousey>y+hg && mousey<y+hg+20 && mousePressed) {//number of balls
          currBallNum=constrain(int(mouseX-x-10)/5,0,23);
        }
        rect(x+10,y+hg,currBallNum*5/*(currBallNum/numBalls)*/,20);
        fill(255,200);
        text(currBallNum, x+15,y+hg +15);
    
    
        text("Air friction",x+15,y+(hg)*2);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+140 && mousey>y+(hg)*2 && mousey<y+(hg)*2+20 && mousePressed) {//friction
          friction=constrain(int(mouseX-x-10)*0.001 -0.001,0,0.118);
        }
        rect(x+10,y+(hg)*2,friction*1000/*(currBallNum/numBalls)*/,20);
        fill(255,200);
        text(friction, x+15,y+(hg)*2 +15);
    
    
        text("Earth's gravity",x+15,y+(hg)*3);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+140 && mousey>y+(hg)*3 && mousey<y+(hg)*3+20 && mousePressed) {
          gravity=constrain(int(mouseX-x-10)*0.09 -0.09,0,9.8);
        }
        rect(x+10,y+(hg)*3,gravity*11,20);
        fill(255,200);
        text(gravity, x+15,y+(hg)*3 +15);
    
    
        text("Ball buncieness",x+15,y+(hg)*4);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+140 && mousey>y+(hg)*4 && mousey<y+(hg)*4+20 && mousePressed) {
          spring=constrain(int(mouseX-x-10)*0.01 -0.01,0,1);
        }
        rect(x+10,y+(hg)*4,spring*100,20);
        fill(255,200);
        text(spring, x+15,y+(hg)*4 +15);
    
    
        text("Ball attraction",x+15,y+(hg)*5);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+140 && mousey>y+(hg)*5 && mousey<y+(hg)*5+20 && mousePressed) {
          massToScale=constrain(int(mouseX-x-10)*0.01 -0.01,0,1);
        }
        rect(x+10,y+(hg)*5,massToScale*100,20);
        fill(255,200);
        text(massToScale, x+15,y+(hg)*5 +15);
    
    
        text("Boundery bouncieness",x+15,y+(hg)*6);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+140 && mousey>y+(hg)*6 && mousey<y+(hg)*6+20 && mousePressed) {
          wallBounce=constrain(int(mouseX-x-10)*0.0085 -0.0085,0,1);
        }
        rect(x+10,y+(hg)*6,wallBounce*117.5,20);
        fill(255,200);
        text(wallBounce, x+15,y+(hg)*6 +15);
    
    
        text("Blurr effect",x+15,y+(hg)*7);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+150 && mousey>y+(hg)*7 && mousey<y+(hg)*7+20 && mousePressed) {//Blurr effect
          backFade=constrain(int(mouseX-x-10)*2 -2,0,255);
        }
        rect(x+10,y+(hg)*7,backFade*0.5,20);
        fill(255,200);
        text(backFade, x+15,y+(hg)*7 +15);
    
    
        text("Ball fade",x+15,y+(hg)*8);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+150 && mousey>y+(hg)*8 && mousey<y+(hg)*8+20 && mousePressed) {//ball transparance
          ballFade=constrain(int(mouseX-x-10)*2 -2,0,255);
        }
        rect(x+10,y+(hg)*8,ballFade*0.5,20);
        fill(255,200);
        text(ballFade, x+15,y+(hg)*8 +15);
    
    
        text("line fade",x+15,y+(hg)*9);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+150 && mousey>y+(hg)*9 && mousey<y+(hg)*9+20 && mousePressed) {//line transparance
          lineFade=constrain(int(mouseX-x-10)*2 -2,0,255);
        }
        rect(x+10,y+(hg)*9,lineFade*0.5,20);
        fill(255,200);
        text(lineFade, x+15,y+(hg)*9 +15);
    
    
        text("Line Length",x+15,y+(hg)*10);
        fill(36,60,240,100);
        if(mousex>x-10 && mousex<x+150 && mousey>y+(hg)*10 && mousey<y+(hg)*10+20 && mousePressed) {//line visible length
          lineLength=constrain(int(mouseX-x-10)*10 -2,0,255*4);
        }
        rect(x+10,y+(hg)*10,lineLength*0.1,20);
        fill(255,200);
        text(lineLength, x+15,y+(hg)*10 +15);
    
    
    
        text("Smooth",x+15,y+(hg)*11);
        fill(36,60,240,100);
        if(mousex>x+80 && mousex<x+100 && mousey>y+(hg)*11 -15 && mousey<y+(hg)*11+5 && mousePressed
          && canOpen) {//smoothness
          isSmooth=!isSmooth;
          canOpen=false;
        }
        rect(x+80,y+(hg)*11 -15,20,20);
        stroke(255);
        if(isSmooth) {
          strokeWeight(5);
          line(x+80,y+hg*11 -15, x+95,y+hg*11);
          line(x+95,y+hg*11, x+105,y+hg*11 -25);
        }
        strokeWeight(1);
        
        
        fill(255,200);
        stroke(36,60,240,200);
        text("Show frameRate",x+15,y+(hg)*12);
        fill(36,60,240,100);
        if(mousex>x+120 && mousex<x+140 && mousey>y+(hg)*12 -15 && mousey<y+(hg)*12 +5 && mousePressed
          && canOpen) {//show the frameRate
          tFR=!tFR;
          fill(0);
          noStroke();
          rect(0,0,50,12);
          canOpen=false;
        }
        rect(x+120,y+(hg)*12 -15,20,20);
        stroke(255);
        if(tFR) {
          strokeWeight(5);
          line(x+120,y+hg*12 -15, x+135,y+hg*12);
          line(x+135,y+hg*12, x+145,y+hg*12 -25);
        }
      }
    }
    
    
    void blurrbackground(int r, int g, int b, int transparancy) {
      if(keyPressed && key ==' ') fill(r,g,b);
      else fill(r,g,b,transparancy);
      noStroke();
      rect(0,0, width,height);
      fill(255);
      noStroke();
    }
    
    void theFrameRate() {
      if(tFR) {
        noStroke();
        fill(0);
        rect(0,0,50,12);
        fill(255);
        text(frameRate,0,10);
      }
    }
    
    

    code

    tweaks (0)

    about this sketch

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

    license

    advertisement

    Jeremy Green

    nodeGarden plus Options menu

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

    nodeGarden, with an options menu so you can play with physics.

    have fun.

    You need to login/register to comment.