topical media & game development

talk show tell print

#javascript-processing-example-topic-motion-circlecollision.htm / htm



  <!DOCTYPE html>
  <html><head>
  <script src="javascript-processing-example-processing.js"></script>
  <script src="javascript-processing-example-init.js"></script>
  <link rel="stylesheet" href="javascript-processing-example-style.css">
  </head><body><h1><a href="http://ejohn.org/blog/processingjs/">Processing.js</a></h1>
  <h2>CircleCollision</h2>
  
  <p>by Ira Greenberg. 
  
  Based on Keith Peter's Solution in
  Foundation Actionscript Animation:
  Making Things Move!
  http://www.friendsofed.com/book.html?isbn=1590597915>
  
  <p><a href="http://processing.org/learning/topics/circlecollision.html"><b>Original Processing.org Example:</b> CircleCollision</a><br>
  <script type="application/processing">
  Ball[] balls =  { 
    new Ball(100, 400, 10), 
    new Ball(700, 400, 40) 
    };
  
  Vect2D[] vels = { 
    new Vect2D(2.15, -1.35), 
    new Vect2D(-1.65, .42) 
    };
  
  void setup(){
    size(200, 200);
    smooth();
    noStroke();
  }
  
  void draw(){
    background(51);
    fill(204);
    for (int i=0; i< 2; i++){
      balls[i].x += vels[i].vx;
      balls[i].y += vels[i].vy;
      ellipse(balls[i].x, balls[i].y, balls[i].r*2, balls[i].r*2);
      checkBoundaryCollision(balls[i], vels[i]);
    }
    checkObjectCollision(balls, vels);
  }
  
  void checkObjectCollision(Ball[] b, Vect2D[] v){
  
    // get distances between the balls components
    Vect2D bVect = new Vect2D();
    bVect.vx = b[1].x - b[0].x;
    bVect.vy = b[1].y - b[0].y;
  
    // calculate magnitude of the vector separating the balls
    float bVectMag = sqrt(bVect.vx * bVect.vx + bVect.vy * bVect.vy);
    if (bVectMag < b[0].r + b[1].r){
      // get angle of bVect
      float theta  = atan2(bVect.vy, bVect.vx);
      // precalculate trig values
      float sine = sin(theta);
      float cosine = cos(theta);
  
      /* bTemp will hold rotated ball positions. You 
       just need to worry about bTemp[1] position*/
      Ball[] bTemp = {  
        new Ball(), new Ball()      };
      /* b[1]'s position is relative to b[0]'s
       so you can use the vector between them (bVect) as the 
       reference point in the rotation expressions.
       bTemp[0].x and bTemp[0].y will initialize
       automatically to 0.0, which is what you want
       since b[1] will rotate around b[0] */
      bTemp[1].x  = cosine * bVect.vx + sine * bVect.vy;
      bTemp[1].y  = cosine * bVect.vy - sine * bVect.vx;
  
      // rotate Temporary velocities
      Vect2D[] vTemp = { 
        new Vect2D(), new Vect2D()     };
      vTemp[0].vx  = cosine * v[0].vx + sine * v[0].vy;
      vTemp[0].vy  = cosine * v[0].vy - sine * v[0].vx;
      vTemp[1].vx  = cosine * v[1].vx + sine * v[1].vy;
      vTemp[1].vy  = cosine * v[1].vy - sine * v[1].vx;
  
      /* Now that velocities are rotated, you can use 1D
       conservation of momentum equations to calculate 
       the final velocity along the x-axis. */
      Vect2D[] vFinal = {  
        new Vect2D(), new Vect2D()      };
      // final rotated velocity for b[0]
      vFinal[0].vx = ((b[0].m - b[1].m) * vTemp[0].vx + 2 * b[1].m * 
        vTemp[1].vx) / (b[0].m + b[1].m);
      vFinal[0].vy = vTemp[0].vy;
      // final rotated velocity for b[0]
      vFinal[1].vx = ((b[1].m - b[0].m) * vTemp[1].vx + 2 * b[0].m * 
        vTemp[0].vx) / (b[0].m + b[1].m);
      vFinal[1].vy = vTemp[1].vy;
  
      // hack to avoid clumping
      bTemp[0].x += vFinal[0].vx;
      bTemp[1].x += vFinal[1].vx;
  
      /* Rotate ball positions and velocities back
       Reverse signs in trig expressions to rotate 
       in the opposite direction */
      // rotate balls
      Ball[] bFinal = { 
        new Ball(), new Ball()     };
      bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
      bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
      bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
      bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
  
      // update balls to screen position
      b[1].x = b[0].x + bFinal[1].x;
      b[1].y = b[0].y + bFinal[1].y;
      b[0].x = b[0].x + bFinal[0].x;
      b[0].y = b[0].y + bFinal[0].y;
  
      // update velocities
      v[0].vx = cosine * vFinal[0].vx - sine * vFinal[0].vy;
      v[0].vy = cosine * vFinal[0].vy + sine * vFinal[0].vx;
      v[1].vx = cosine * vFinal[1].vx - sine * vFinal[1].vy;
      v[1].vy = cosine * vFinal[1].vy + sine * vFinal[1].vx;
    }
  }
  
  class Ball{
    float x, y, r, m;
  
    // default constructor
    Ball() {
    }
  
    Ball(float x, float y, float r) {
      this.x = x;
      this.y = y;
      this.r = r;
      m = r*.1;
    }
  }
  
  class Vect2D{
    float vx, vy;
  
    // default constructor
    Vect2D() {
    }
  
    Vect2D(float vx, float vy) {
      this.vx = vx;
      this.vy = vy;
    }
  }
  
  // checkBoundaryCollision() function:
  void checkBoundaryCollision(Ball ball, Vect2D vel){
    if (ball.x > width-ball.r){
      ball.x = width-ball.r;
      vel.vx *= -1;
    } 
    else if (ball.x < ball.r){
      ball.x = ball.r;
      vel.vx *= -1;
    } 
    else if (ball.y > height-ball.r){
      ball.y = height-ball.r;
      vel.vy *= -1;
    } 
    else if (ball.y < ball.r){
      ball.y = ball.r;
      vel.vy *= -1;
    }
  }
  </script><canvas width="200" height="200"></canvas></p>
  <div style="overflow: hidden; height: 0px; width: 0px;"></div>
  
  <pre><b>// All Examples Written by <a href="http://reas.com/">Casey Reas</a> and <a href="http://benfry.com/">Ben Fry</a>
  // unless otherwise stated.</b>
  Ball[] balls =  { 
    new Ball(100, 400, 10), 
    new Ball(700, 400, 40) 
    };
  
  Vect2D[] vels = { 
    new Vect2D(2.15, -1.35), 
    new Vect2D(-1.65, .42) 
    };
  
  void setup(){
    size(200, 200);
    smooth();
    noStroke();
  }
  
  void draw(){
    background(51);
    fill(204);
    for (int i=0; i&lt; 2; i++){
      balls[i].x += vels[i].vx;
      balls[i].y += vels[i].vy;
      ellipse(balls[i].x, balls[i].y, balls[i].r*2, balls[i].r*2);
      checkBoundaryCollision(balls[i], vels[i]);
    }
    checkObjectCollision(balls, vels);
  }
  
  void checkObjectCollision(Ball[] b, Vect2D[] v){
  
    // get distances between the balls components
    Vect2D bVect = new Vect2D();
    bVect.vx = b[1].x - b[0].x;
    bVect.vy = b[1].y - b[0].y;
  
    // calculate magnitude of the vector separating the balls
    float bVectMag = sqrt(bVect.vx * bVect.vx + bVect.vy * bVect.vy);
    if (bVectMag &lt; b[0].r + b[1].r){
      // get angle of bVect
      float theta  = atan2(bVect.vy, bVect.vx);
      // precalculate trig values
      float sine = sin(theta);
      float cosine = cos(theta);
  
      /* bTemp will hold rotated ball positions. You 
       just need to worry about bTemp[1] position*/
      Ball[] bTemp = {  
        new Ball(), new Ball()      };
      /* b[1]'s position is relative to b[0]'s
       so you can use the vector between them (bVect) as the 
       reference point in the rotation expressions.
       bTemp[0].x and bTemp[0].y will initialize
       automatically to 0.0, which is what you want
       since b[1] will rotate around b[0] */
      bTemp[1].x  = cosine * bVect.vx + sine * bVect.vy;
      bTemp[1].y  = cosine * bVect.vy - sine * bVect.vx;
  
      // rotate Temporary velocities
      Vect2D[] vTemp = { 
        new Vect2D(), new Vect2D()     };
      vTemp[0].vx  = cosine * v[0].vx + sine * v[0].vy;
      vTemp[0].vy  = cosine * v[0].vy - sine * v[0].vx;
      vTemp[1].vx  = cosine * v[1].vx + sine * v[1].vy;
      vTemp[1].vy  = cosine * v[1].vy - sine * v[1].vx;
  
      /* Now that velocities are rotated, you can use 1D
       conservation of momentum equations to calculate 
       the final velocity along the x-axis. */
      Vect2D[] vFinal = {  
        new Vect2D(), new Vect2D()      };
      // final rotated velocity for b[0]
      vFinal[0].vx = ((b[0].m - b[1].m) * vTemp[0].vx + 2 * b[1].m * 
        vTemp[1].vx) / (b[0].m + b[1].m);
      vFinal[0].vy = vTemp[0].vy;
      // final rotated velocity for b[0]
      vFinal[1].vx = ((b[1].m - b[0].m) * vTemp[1].vx + 2 * b[0].m * 
        vTemp[0].vx) / (b[0].m + b[1].m);
      vFinal[1].vy = vTemp[1].vy;
  
      // hack to avoid clumping
      bTemp[0].x += vFinal[0].vx;
      bTemp[1].x += vFinal[1].vx;
  
      /* Rotate ball positions and velocities back
       Reverse signs in trig expressions to rotate 
       in the opposite direction */
      // rotate balls
      Ball[] bFinal = { 
        new Ball(), new Ball()     };
      bFinal[0].x = cosine * bTemp[0].x - sine * bTemp[0].y;
      bFinal[0].y = cosine * bTemp[0].y + sine * bTemp[0].x;
      bFinal[1].x = cosine * bTemp[1].x - sine * bTemp[1].y;
      bFinal[1].y = cosine * bTemp[1].y + sine * bTemp[1].x;
  
      // update balls to screen position
      b[1].x = b[0].x + bFinal[1].x;
      b[1].y = b[0].y + bFinal[1].y;
      b[0].x = b[0].x + bFinal[0].x;
      b[0].y = b[0].y + bFinal[0].y;
  
      // update velocities
      v[0].vx = cosine * vFinal[0].vx - sine * vFinal[0].vy;
      v[0].vy = cosine * vFinal[0].vy + sine * vFinal[0].vx;
      v[1].vx = cosine * vFinal[1].vx - sine * vFinal[1].vy;
      v[1].vy = cosine * vFinal[1].vy + sine * vFinal[1].vx;
    }
  }
  
  class Ball{
    float x, y, r, m;
  
    // default constructor
    Ball() {
    }
  
    Ball(float x, float y, float r) {
      this.x = x;
      this.y = y;
      this.r = r;
      m = r*.1;
    }
  }
  
  class Vect2D{
    float vx, vy;
  
    // default constructor
    Vect2D() {
    }
  
    Vect2D(float vx, float vy) {
      this.vx = vx;
      this.vy = vy;
    }
  }
  
  // checkBoundaryCollision() function:
  void checkBoundaryCollision(Ball ball, Vect2D vel){
    if (ball.x &gt; width-ball.r){
      ball.x = width-ball.r;
      vel.vx *= -1;
    } 
    else if (ball.x &lt; ball.r){
      ball.x = ball.r;
      vel.vx *= -1;
    } 
    else if (ball.y &gt; height-ball.r){
      ball.y = height-ball.r;
      vel.vy *= -1;
    } 
    else if (ball.y &lt; ball.r){
      ball.y = ball.r;
      vel.vy *= -1;
    }
  }</pre>
  </body></html>
  


(C) Æliens 20/2/2008

You may not copy or print any of this material without explicit permission of the author or the publisher. In case of other copyright issues, contact the author.