• fullscreen
  • ballUndKlassen3.pde
  • keyboad.pde
  • klasse.pde
  • timestamp.pde
  • /*
    Code by Diana Lange
    www.diana-lange.de
    
    This is an exercise to teach myself how to write a class. 
    
    You can grab a ball and shoot with it.
    
    Controls:
    
    1 / 2 / 3 = toggle between color sets
    Space = change background color
    M = show / hide connections
    N = show / hide crash location
    B = create new set of balls
    Right = add new ball
    Left = remove a ball
    Any key = pause
    
    http://www.vimeo.com/19564417
    
    */
    
    import processing.video.*;
    
    MovieMaker mm;
    
    boolean saveMov = false, showConnections = false, showCrashPoint = false, colorSetOne = true, colorSetTwo = false, colorSetThree = false, whiteBG = true, newColors = false;
    int frameCounter = 0, movieLength = 1200;
    
    float minS = 0.4, maxS = 1.5;
    int amount = 30, numOfRecursition = 0;
    
    ArrayList ballsList;
    
    void setup ()
    {
      size (800, 600);
      smooth();
      frameRate (25);
      
      ballsList = new ArrayList (amount);
    
      createBalls();
      checkOverLay();
    }
    
    void draw ()
    {
      if (whiteBG) background (247);
      else background (5);
    
      moveBalls ();
    
      if (saveMov == true)
      {
        mm.addFrame();
        frameCounter++;
      }
    
      if (frameCounter >= movieLength)
      {
        saveMov = false;
        mm.finish();
        exit();
      }
    }
    
    
    void moveBalls ()
    {
      for (int i = 0; i < amount; i++)
      {
        Ball checkBall = (Ball) ballsList.get(i);
    
        PVector mp = new PVector (mouseX, mouseY);
        boolean mouseisOverEllipse = checkBall.mouseDistance(mp.x, mp.y);
        boolean mouseIsPressed = checkBall.checkMousePress (mouseisOverEllipse, mousePressed);
        boolean mouseIsReleased_ = checkBall.checkMouseRelease (mouseisOverEllipse, mouseIsReleased);
        if (newColors) checkBall.createColorList();
    
        checkBall.shootWithMouse (mouseisOverEllipse, mouseIsPressed, mouseIsReleased_);
        checkBall.checkDistance (i, mouseIsPressed);
        if(keyPressed == false) checkBall.move(mouseIsPressed, mp);
        checkBall.display(mouseisOverEllipse, mouseIsPressed);
      }
      mouseIsReleased = false;
      newColors = false;
    }
    
    void createBalls()
    {
    
      for (int i = 0; i < amount; i++)
      {
        float maxEllipseSize = (width+height) / 20;
        int ellipseSize = (int) random (50, maxEllipseSize);
        PVector startPoint = new PVector (random (ellipseSize/2, width-ellipseSize/2), random (ellipseSize/2, height-ellipseSize/2));
        PVector startSpeed = new PVector (random (-maxS, maxS), random (-maxS, maxS));
    
        float s = minS;
    
        if (startSpeed.x <= s && startSpeed.x >= 0) startSpeed.x = s+0.01;
        if (startSpeed.x < 0 && startSpeed.x >= -s) startSpeed.x = -s-0.01;
        if (startSpeed.y <= s && startSpeed.y >= 0) startSpeed.y = s+0.01;
        if (startSpeed.y < 0 && startSpeed.y >= -s) startSpeed.y = -s-0.01;
    
        int ellipseNum = (int) random (4, 10);
        ballsList. add ( new Ball (startPoint, startSpeed, ellipseNum, ellipseSize));
      }
    }
    
    void checkOverLay ()
    {
      boolean overLayFound = false;
      for (int i = 0; i < amount; i++)
      {
        Ball checkBall = (Ball) ballsList.get(i);
        
        PVector cb =  checkBall.location;
        for (int j = 0; j < amount; j++)
        {
          Ball nextBall = (Ball) ballsList.get(j);
          
          PVector nb = nextBall.location;
    
          float distance = PVector.dist(cb, nb);
          float overLaydistance = checkBall.ellipseSize/2 + nextBall.ellipseSize/2;
          if (distance < overLaydistance && i != j)
          {
            float maxEllipseSize = (width+height) / 20;
            int ellipseSize = (int) random (50, maxEllipseSize);
            PVector startPoint = new PVector (random (ellipseSize/2, width-ellipseSize/2), random (ellipseSize/2, height-ellipseSize/2));
            PVector startSpeed = new PVector (random (-maxS, maxS), random (-maxS, maxS));
    
            float s = minS;
    
            if (startSpeed.x <= s && startSpeed.x >= 0) startSpeed.x = s+0.01;
            if (startSpeed.x < 0 && startSpeed.x >= -s) startSpeed.x = -s-0.01;
            if (startSpeed.y <= s && startSpeed.y >= 0) startSpeed.y = s+0.01;
            if (startSpeed.y < 0 && startSpeed.y >= -s) startSpeed.y = -s-0.01;
    
            int ellipseNum = (int) random (4, 10);
            ballsList. add ( new Ball (startPoint, startSpeed, ellipseNum, ellipseSize));
            numOfRecursition ++;
            overLayFound = true;
          }
        }
      }
    
      if (overLayFound == true && numOfRecursition < 40) checkOverLay ();
    }
    
    
    boolean mouseIsReleased = false;
    
    void keyPressed ()
    {
    
      if (keyCode == KeyEvent.VK_SPACE) whiteBG = !whiteBG;
      if (keyCode == KeyEvent.VK_1) {
        colorSetOne = !colorSetOne;
        colorSetTwo = false;
        colorSetThree = false;
        newColors = true;
      }
      if (keyCode == KeyEvent.VK_2) {
        colorSetTwo = !colorSetTwo;
        colorSetOne = false;
        colorSetThree = false;
        newColors = true;
      }
      if (keyCode == KeyEvent.VK_3) {
        colorSetThree = !colorSetThree;
        colorSetOne = false;
        colorSetTwo = false;
        newColors = true;
      }
      if (keyCode == KeyEvent.VK_CONTROL)
      {
        if (saveMov == false)
        {
          frameCounter = 0;
          saveMov = true;
          mm = new MovieMaker (this, width, height, "export/" + timeStamp () + ".mov", 25, MovieMaker.ANIMATION, MovieMaker.HIGH);
        }
    
        else 
        {
          saveMov = false;
          mm.finish();
        }
      }
    
      if (keyCode == KeyEvent.VK_ALT) saveFrame ("export/" + timeStamp () + ".png)");
    
      if (keyCode == KeyEvent.VK_M) showConnections = !showConnections;
      if (keyCode == KeyEvent.VK_N) showCrashPoint = !showCrashPoint;
      if (keyCode == KeyEvent.VK_B)
      {
        ballsList = new ArrayList (amount);
        numOfRecursition = 0;
    
        createBalls();
        checkOverLay();
      }
      
      if (keyCode == KeyEvent.VK_RIGHT)
      {
        amount++;
        
        float maxEllipseSize = (width+height) / 20;
        int ellipseSize = (int) random (50, maxEllipseSize);
        PVector startPoint = new PVector (random (ellipseSize/2, width-ellipseSize/2), random (ellipseSize/2, height-ellipseSize/2));
        PVector startSpeed = new PVector (random (-maxS, maxS), random (-maxS, maxS));
    
        float s = minS;
    
        if (startSpeed.x <= s && startSpeed.x >= 0) startSpeed.x = s+0.01;
        if (startSpeed.x < 0 && startSpeed.x >= -s) startSpeed.x = -s-0.01;
        if (startSpeed.y <= s && startSpeed.y >= 0) startSpeed.y = s+0.01;
        if (startSpeed.y < 0 && startSpeed.y >= -s) startSpeed.y = -s-0.01;
    
        int ellipseNum = (int) random (4, 10);
        ballsList. add (amount-1,  new Ball (startPoint, startSpeed, ellipseNum, ellipseSize));
        
        Ball checkBall = (Ball) ballsList.get (amount-1);
        checkBall.createColorList();
      }
      
       if (keyCode == KeyEvent.VK_LEFT)
      {
        amount -= 1;
        
        amount = constrain (amount, 1,200);
        
        float maxEllipseSize = (width+height) / 20;
        int ellipseSize = (int) random (50, maxEllipseSize);
        PVector startPoint = new PVector (random (ellipseSize/2, width-ellipseSize/2), random (ellipseSize/2, height-ellipseSize/2));
        PVector startSpeed = new PVector (random (-maxS, maxS), random (-maxS, maxS));
    
        float s = minS;
    
        if (startSpeed.x <= s && startSpeed.x >= 0) startSpeed.x = s+0.01;
        if (startSpeed.x < 0 && startSpeed.x >= -s) startSpeed.x = -s-0.01;
        if (startSpeed.y <= s && startSpeed.y >= 0) startSpeed.y = s+0.01;
        if (startSpeed.y < 0 && startSpeed.y >= -s) startSpeed.y = -s-0.01;
    
        int ellipseNum = (int) random (4, 10);
        ballsList. add ( new Ball (startPoint, startSpeed, ellipseNum, ellipseSize));
      }
    }
    
    
    void mouseReleased ()
    {
      mouseIsReleased = true;
    }
    
    
    class Ball 
    {
      PVector location, lastLocation, speed, speedUp, cm;
      int numberOfEllipse, ellipseSize;
      color [] colorList;
      float [] ellipseSizeList;
      color strokeColor, shootColor, dotColor, hoverColor;
      float connectionWeight, shootWeight, dotWeight, hoverWeight;
    
    
      Ball (PVector location_, PVector speed_, int numberOfEllipse_, int ellipseSize_)
      {
        location = location_;
        lastLocation = location;
        speed = speed_;
        numberOfEllipse = numberOfEllipse_;
        ellipseSize = ellipseSize_;
        colorList = new color [numberOfEllipse+1];
        ellipseSizeList = new float [numberOfEllipse];
        createColorList ();
        createEllipseSize ();
        speedUp = new PVector (0, 0);
        cm = speedUp;
    
        strokeColor = color (0,50);
        dotColor = strokeColor;
        shootColor = strokeColor;
        hoverColor = color (0,120);
        connectionWeight = 0.5;
        shootWeight = 0.75;
        dotWeight = 10;
        hoverWeight = 3.0;
      }
    
      void createEllipseSize ()
      {
        float startEllipseSize = (float) ellipseSize;
        for (int i = 0; i < numberOfEllipse; i++)
        {
          float ce = random (ellipseSize*0.2, ellipseSize*0.9);
          ellipseSizeList [i] = ce;
        }
      }
    
      void createColorList ()
      {
        for (int i = 0; i < numberOfEllipse+1; i++)
        {
          float maxA = 10+i*numberOfEllipse;
          float minA = 8+i*2;
    
          if (colorSetOne) colorList [i] = color (random (10,80), random (10,80), random (10,80), random (minA,maxA));
    
          if (colorSetTwo)
          {
            maxA = 255;
            minA = 120;
    
            colorList [i] = color ( random (5, 247+i*numberOfEllipse*5), random (minA,maxA));
          }
    
    
          if (colorSetThree)
          {
            minA = 240-i*numberOfEllipse*5;
            maxA = 247-i*3;
    
            colorList [i] = color (random (50,230), random (50,230), random (50,120), random (minA,maxA));
          }
        }
      }
    
      void createStrokeColorsAndWeights ()
      {
        if (colorSetOne)
        {
          if (whiteBG)
          {
            strokeColor = color (0,50);
            dotColor = strokeColor;
            shootColor  = color (0,150);
            hoverColor = color (0,120);
            connectionWeight = 0.5;
            shootWeight = 1.0;
            dotWeight = 10;
            hoverWeight = 3.0;
          }
          else
          {
            strokeColor = color (255,80);
            dotColor = color (255,120);
            hoverColor = color (255,150);
            shootColor = color (255, 180);
            connectionWeight = 0.75;
            dotWeight = 10;
            shootWeight = 1.25;
            hoverWeight = 3.0;
          }
        }
    
        if (colorSetTwo)
        {
          if (whiteBG)
          {
            strokeColor = color (0,20);
            dotColor = color (180,0,0,180);
            shootColor = color (180,0,0,180);
            hoverColor = color (180,0,0,180);
            connectionWeight = 3.0;
            shootWeight = 3;
            dotWeight = 10;
            hoverWeight = 4.0;
          }
          else
          {
            strokeColor = color (255,80);
            dotColor = color (180,0,0,150);
            shootColor = color (180,0,0,150);
            hoverColor = color (180,0,0,150);
            connectionWeight = 3.0;
            dotWeight = 10;
            shootWeight = 3.0;
            hoverWeight = 4.0;
          }
        }
    
        if (colorSetThree)
        {
          if (whiteBG)
          {
            strokeColor = color (colorList[0]);
            dotColor = color (0,200);
            shootColor = color (0,200);
            hoverColor = color (0,200);
            connectionWeight = 1.0;
            shootWeight = 2.0;
            dotWeight = 10;
            hoverWeight = 4.0;
          }
          else
          {
            strokeColor = color (colorList[0]);
            dotColor = color (255,200);
            shootColor = color (255,180);
            hoverColor = color (255,180);
            connectionWeight = 1.5;
            dotWeight = 10;
            shootWeight = 2.0;
            hoverWeight = 4.0;
          }
        }
      }
    
    
      void display(boolean mouseIsOverEllipse, boolean mouseIsPressed)
      {
        createStrokeColorsAndWeights ();
    
        if (mouseIsPressed)
        {
          strokeWeight(shootWeight);
          stroke(shootColor);
          line (location.x, location.y, lastLocation.x, lastLocation.y);
        }
    
        if (mouseIsOverEllipse == false) noStroke ();
        else {
          strokeWeight (hoverWeight);
          stroke (hoverColor);
        }
    
        color cc = colorList [0];
        if (!whiteBG && colorSetOne) cc = color (red (cc)+60, green (cc)+60, blue (cc)+60, alpha (cc) + 40);
        if (!whiteBG && colorSetThree) cc = color (red (cc), green (cc), blue (cc), alpha (cc) - 60);
    
        fill (cc);
        ellipse (location.x, location.y, ellipseSize, ellipseSize);
        noStroke();
    
        for (int i = 0; i < numberOfEllipse; i++)
        {
          cc = colorList [i+1];
          if (!whiteBG && colorSetOne) cc = color (red (cc)+60, green (cc)+60, blue (cc)+60, alpha (cc) + 20);
          if (!whiteBG && colorSetThree) cc = color (red (cc), green (cc), blue (cc), alpha (cc) - 40);
    
          fill (cc);
          float currentEllipseSize = ellipseSizeList [i];
          ellipse (location.x, location.y, currentEllipseSize, currentEllipseSize);
        }
      }
    
      void move(boolean mouseIsPressed, PVector mp)
      {
        if (mouseIsPressed == false)
        {
          location.x += speed.x+speedUp.x;
          location.y += speed.y+speedUp.y;
    
          speedUp.x *= 0.97;
          speedUp.y *= 0.97;
        }
        else
        {
          location = mp;
        }
    
        keepInWinodow();
      }
    
    
      void keepInWinodow()
      {
        if (location.x >= (width-ellipseSize/2) || location.x <= ellipseSize/2) {
          speed.x *= -1;
          speedUp.x *= -1;
          if (location.x >= (width-ellipseSize/2)) location.x = width-ellipseSize/2;
          if (location.x <= ellipseSize/2) location.x = ellipseSize/2;
        }
        if (location.y >= (height-ellipseSize/2)|| location.y <= ellipseSize/2) 
        {
          speed.y *= -1;
          speedUp.y *= -1;
          if (location.y >= (height-ellipseSize/2)) location.y = height-ellipseSize/2;
          if (location.y <= ellipseSize/2) location.y = ellipseSize/2;
        }
      }
    
      // colliding balls ---------------------------------------
    
      void checkDistance (int i, boolean mouseIsPressed_)
      {   
        for (int j = 0; j < amount; j++)
        {
          Ball nextBall = (Ball) ballsList.get (j);
          float distance = PVector.dist (location, nextBall.location);
    
          float crashDistance = ellipseSize / 2.0 + nextBall.ellipseSize / 2.0;
    
          if (showConnections && distance <= width/8)
          {
            strokeWeight (connectionWeight);
            stroke (strokeColor);
            line(location.x, location.y, nextBall.location.x, nextBall.location.y);
          }
    
          if (distance <= crashDistance && i != j) createCrashReaction ( nextBall, j);
        }
      }
    
      void createCrashReaction (Ball nextBall, int j)
      {
        float crashAngle = createCrashAngle (nextBall.location);
        PVector crashLocation = createCrashLocation (nextBall.location, crashAngle);
    
        float einfallsWinkel = createEinfallsWinkelCurrentBall ();
        float einfallsWinkelNB = createEinfallsWinkelNextBall (nextBall);
    
        float ausfallsWinkel = PI-(crashAngle+einfallsWinkel);
        float ausfallsWinkelNB = PI-(crashAngle+einfallsWinkelNB);
    
        float distance = dist (location.x, location.y, location.x+speed.x, location.y+speed.y);
        float distanceNB = dist (nextBall.location.x, nextBall.location.y, nextBall.location.x+nextBall.speed.x, nextBall.location.y+nextBall.speed.y);
    
        float mx = 1, my = 1, mxNB = 1, myNB = 1;
    
        if (location.x < crashLocation.x) mx = -1;
        if (location.y < crashLocation.y) my = -1;
    
        if (nextBall.location.x < crashLocation.x) mxNB = -1;
        if (nextBall.location.y < crashLocation.y) myNB = -1;
    
        PVector newSpeed = new PVector (mx* cos (ausfallsWinkel) * distance, my* sin (ausfallsWinkel) * distance );
        PVector newSpeedNB = new PVector (mxNB* cos (ausfallsWinkelNB) * distanceNB, myNB* sin (ausfallsWinkelNB) * distanceNB);    
    
        float speedUpValue = (abs (einfallsWinkel) + abs (einfallsWinkelNB) + abs(speed.x)*2 + abs (speed.y)*2 + abs(speedUp.x) + abs(speedUp.y) + abs (nextBall.speed.x) + abs (nextBall.speed.y)) * 0.25;
        float speedUpValueNB = (abs (einfallsWinkel) + abs (einfallsWinkelNB) + abs(speed.x) + abs (speed.y) + abs (nextBall.speed.x)*2 + abs (nextBall.speed.y)*2 + abs(nextBall.speedUp.x) + abs(nextBall.speedUp.y)) * 0.25;
    
        PVector newSpeedUp = new PVector (speedUpValue * newSpeed.x, speedUpValue * newSpeed.y);
        PVector newSpeedUpNB = new PVector (speedUpValueNB * newSpeedNB.x, speedUpValueNB * newSpeedNB.y);
    
        newSpeedUp.x = constrain (newSpeedUp.x, -30,30);
        newSpeedUp.y = constrain (newSpeedUp.y, -30,30);
        newSpeedUpNB.x = constrain (newSpeedUpNB.x, -30,30);
        newSpeedUpNB.y = constrain (newSpeedUpNB.y, -30,30);
    
        speed = newSpeed;
        speedUp = newSpeedUp;
    
        nextBall.speed = newSpeedNB;
        nextBall.speedUp = newSpeedUpNB;
    
    
        if (showCrashPoint)
        {
          strokeWeight (connectionWeight);
          stroke (strokeColor);
          line(location.x, location.y, nextBall.location.x, nextBall.location.y);
          strokeWeight (dotWeight);
          stroke (dotColor);
          point (crashLocation.x, crashLocation.y);
        }
      }
    
      float createCrashAngle (PVector nextBall)
      {
        PVector p1 = location;
        PVector p2 = nextBall;
    
        float a = PVector.dist (p1, p2);
        float b = dist (p1.x, p1.y, p2.x, p1.y);
    
        float angle = acos (b/a);
    
        return angle;
      }
    
      float createEinfallsWinkelNextBall (Ball nextBall)
      {
        PVector cl = nextBall.location;
        PVector ll = new PVector (abs(cl.x-nextBall.speed.x), abs (cl.y-nextBall.speed.y) ); 
    
        float b = dist (ll.x, ll.y, cl.x, ll.y);
        float c = PVector.dist (cl, ll);
    
        float angle = acos (b/c);
    
        return angle;
      }
    
      float createEinfallsWinkelCurrentBall ()
      {
        PVector cl = location;
        PVector ll = new PVector (abs(cl.x-speed.x), abs (cl.y-speed.y) ); 
    
        float b = dist (ll.x, ll.y, cl.x, ll.y);
        float c = PVector.dist (cl, ll);
    
        float angle = acos (b/c);
        return angle;
      }
    
      PVector createCrashLocation (PVector nextBall, float angle)
      {
        PVector p1 = location;
        PVector p2 = nextBall;
    
        float a_ = ellipseSize/2;
        float b_ = cos (angle) * a_;
        float c_ = sin (angle) * a_;
    
        float mx = 1, my = 1;
    
        if (p1.x > p2.x) mx = -1;
        if (p1.y > p2.y) my = -1;
    
    
        PVector crashLocation = new PVector (p1.x + mx * b_, p1.y + my * c_);
    
        return crashLocation;
      }
    
      // shoot with a ball --------------------------------------------------
    
      boolean mouseDistance (float mouseX_, float mouseY_)
      {
        boolean mouseIsOverEllipse = false;
        PVector mousePosition = new PVector (mouseX_, mouseY_);
        float distance = PVector.dist (mousePosition, location);
        if (distance <= ellipseSize/2) mouseIsOverEllipse = true;
        return mouseIsOverEllipse;
      }
    
      boolean checkMousePress (boolean mouseisOverEllipse_, boolean mouseIsPressed_)
      {
        boolean mouseIsPressed = false;
        if (mouseisOverEllipse_ &&  mouseIsPressed_) mouseIsPressed = true;
        return mouseIsPressed;
      }
    
      boolean checkMouseRelease (boolean mouseisOverEllipse_, boolean mouseIsReleased_)
      {
        boolean mouseIsReleasedTemp = false;
        if (mouseisOverEllipse_ &&  mouseIsReleased_) mouseIsReleasedTemp = true;
        return mouseIsReleasedTemp;
      }
    
      void shootWithMouse (boolean mouseIsOverEllipse_, boolean mouseIsPressed_, boolean mouseIsReleased_)
      {
        if (mouseIsPressed_ == false && mouseIsReleased_ == false) saveLastPos();
        if (mouseIsReleased_ == true&& mouseIsOverEllipse_ == true) createShootReaction ();
      }
    
      void createShootReaction ()
      {
    
        float angle = createShoothAngle ();
        float distance = dist (location.x, location.y,location.x+speed.x, location.y+speed.y);
    
        float x = cos (angle) * distance, y = sin (angle) * distance;
        int mx = 1, my = 1;
    
        if (lastLocation.x < location.x) mx = -1;
        if (lastLocation.y < location.y) my = -1;
    
        PVector newSpeed = new PVector (mx*x,my*y );
    
        speed = newSpeed;
    
        speedUPerDistance ();
    
        mouseIsReleased = false;
      }
    
      float createShoothAngle ()
      {
        PVector p1 = lastLocation;
        PVector p2 = location;
    
        float a = PVector.dist (p1, p2);
        float b = dist (p1.x, p1.y, p2.x, p1.y);
    
        float angle = acos (b/a);
    
        return angle;
      }
    
      void speedUPerDistance ()
      {
    
        float distance = PVector.dist (location, lastLocation);
    
        speedUp.x = speed.x*distance/4;
        speedUp.x = constrain (speedUp.x, -40,40);
        speedUp.y = speed.y*distance/4;
        speedUp.y = constrain (speedUp.y, -40,40);
      }
    
      void saveLastPos ()
      {
        lastLocation = location;
      }
    }
    
    
    String timeStamp ()
    {
      String ct = nf (year(), 4,0) + "_" + nf (month (), 2, 0) + "_" + nf (day (), 2, 0) + "__" + nf (hour (), 2, 0) + "_" + nf (minute (), 2, 0) + "_" + nf (second(), 2, 0);
      return ct;
    } 
    

    code

    tweaks (0)

    about this sketch

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

    license

    advertisement

    Diana Lange

    Colliding balls

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

    This is an exercise to teach myself how to write a class.

    You can grab a ball and shoot with it.

    Controls:

    1 / 2 / 3 = toggle between color sets
    Space = change background color
    M = show / hide connections
    N = show / hide crash location
    B = create new set of balls
    Right = add new ball
    Left = remove a ball
    Any key = pause

    http://www.vimeo.com/19564417

    You need to login/register to comment.