topical media & game development

talk show tell print

#javascript-processing-example-topic-motion-reflection2.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>Reflection2</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/reflection2.html"><b>Original Processing.org Example:</b> Reflection2</a><br>
  <script type="application/processing">
  Orb orb;
  Vect2D velocity;
  float gravity = .05, damping = 0.8;
  int segments = 40;
  Ground[] ground = new Ground[segments];
  float[] peakHeights = new float[segments+1];
  
  void setup(){
    size(200, 200);
    smooth();
    orb = new Orb(50, 50, 3);
    velocity = new Vect2D(.5, 0);
  
    // calculate ground peak heights 
    for (int i=0; i<peakHeights.length; i++){
      peakHeights[i] = random(height-40, height-30);
    }
  
    /* float value required for segment width (segs)
     calculations so the ground spans the entire 
     display window, regardless of segment number. */
    float segs = segments;
    for (int i=0; i<segments; i++){
      ground[i]  = new Ground(width/segs*i, peakHeights[i],
      width/segs*(i+1), peakHeights[i+1]);
    }
  }
  
  void draw(){
    // background
    noStroke();
    fill(0, 15);
    rect(0, 0, width, height);
  
    // move orb
    orb.x += velocity.vx;
    velocity.vy += gravity;
    orb.y += velocity.vy;
  
    // draw ground
    fill(127);
    beginShape();
    for (int i=0; i<segments; i++){
      vertex(ground[i].x1, ground[i].y1);
      vertex(ground[i].x2, ground[i].y2);
    }
    vertex(ground[segments-1].x2, height);
    vertex(ground[0].x1, height);
    endShape(CLOSE);
  
    // draw orb
    noStroke();
    fill(200);
    ellipse(orb.x, orb.y, orb.r*2, orb.r*2);
  
    // collision detection
    checkWallCollision();
    for (int i=0; i<segments; i++){
      checkGroundCollision(ground[i]);
    }
  }
  
  void checkWallCollision(){
    if (orb.x > width-orb.r){
      orb.x = width-orb.r;
      velocity.vx *= -1;
      velocity.vx *= damping;
    } 
    else if (orb.x < orb.r){
      orb.x = orb.r;
      velocity.vx *= -1;
      velocity.vx *= damping;
    }
  }
  
  void checkGroundCollision(Ground groundSegment) {
  
    // get difference between orb and ground
    float deltaX = orb.x - groundSegment.x;
    float deltaY = orb.y - groundSegment.y;
  
    // precalculate trig values
    float cosine = cos(groundSegment.rot);
    float sine = sin(groundSegment.rot);
  
    /* rotate ground and velocity to allow 
     orthogonal collision calculations */
    float groundXTemp = cosine * deltaX + sine * deltaY;
    float groundYTemp = cosine * deltaY - sine * deltaX;
    float velocityXTemp = cosine * velocity.vx + sine * velocity.vy;
    float velocityYTemp = cosine * velocity.vy - sine * velocity.vx;
  
    /* ground collision - check for surface 
     collision and also that orb is within 
     left/rights bounds of ground segment */
    if (groundYTemp > -orb.r &&
      orb.x > groundSegment.x1 &&
      orb.x < groundSegment.x2 ){
      // keep orb from going into ground
      groundYTemp = -orb.r;
      // bounce and slow down orb
      velocityYTemp *= -1.0;
      velocityYTemp *= damping;
    }
  
    // reset ground, velocity and orb
    deltaX = cosine * groundXTemp - sine * groundYTemp;
    deltaY = cosine * groundYTemp + sine * groundXTemp;
    velocity.vx = cosine * velocityXTemp - sine * velocityYTemp;
    velocity.vy = cosine * velocityYTemp + sine * velocityXTemp;
    orb.x = groundSegment.x + deltaX;
    orb.y = groundSegment.y + deltaY;
  }
  
  class Ground {
    float x1, y1, x2, y2;  
    float x, y, len, rot;
  
    // default constructor
    Ground(){
    }
  
    // constructor
    Ground(float x1, float y1, float x2, float y2) {
      this.x1 = x1;
      this.y1 = y1;
      this.x2 = x2;
      this.y2 = y2;
      x = (x1+x2)/2;
      y = (y1+y2)/2;
      len = dist(x1, y1, x2, y2);
      rot = atan2((y2-y1), (x2-x1));
    }
  }
  
  class Orb{
    float x, y, r;
  
    // default constructor
    Orb() {
    }
  
    Orb(float x, float y, float r) {
      this.x = x;
      this.y = y;
      this.r = r;
    }
  }
  
  class Vect2D{
    float vx, vy;
  
    // default constructor
    Vect2D() {
    }
  
    Vect2D(float vx, float vy) {
      this.vx = vx;
      this.vy = vy;
    }
  }
  </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>
  Orb orb;
  Vect2D velocity;
  float gravity = .05, damping = 0.8;
  int segments = 40;
  Ground[] ground = new Ground[segments];
  float[] peakHeights = new float[segments+1];
  
  void setup(){
    size(200, 200);
    smooth();
    orb = new Orb(50, 50, 3);
    velocity = new Vect2D(.5, 0);
  
    // calculate ground peak heights 
    for (int i=0; i&lt;peakHeights.length; i++){
      peakHeights[i] = random(height-40, height-30);
    }
  
    /* float value required for segment width (segs)
     calculations so the ground spans the entire 
     display window, regardless of segment number. */
    float segs = segments;
    for (int i=0; i&lt;segments; i++){
      ground[i]  = new Ground(width/segs*i, peakHeights[i],
      width/segs*(i+1), peakHeights[i+1]);
    }
  }
  
  void draw(){
    // background
    noStroke();
    fill(0, 15);
    rect(0, 0, width, height);
  
    // move orb
    orb.x += velocity.vx;
    velocity.vy += gravity;
    orb.y += velocity.vy;
  
    // draw ground
    fill(127);
    beginShape();
    for (int i=0; i&lt;segments; i++){
      vertex(ground[i].x1, ground[i].y1);
      vertex(ground[i].x2, ground[i].y2);
    }
    vertex(ground[segments-1].x2, height);
    vertex(ground[0].x1, height);
    endShape(CLOSE);
  
    // draw orb
    noStroke();
    fill(200);
    ellipse(orb.x, orb.y, orb.r*2, orb.r*2);
  
    // collision detection
    checkWallCollision();
    for (int i=0; i&lt;segments; i++){
      checkGroundCollision(ground[i]);
    }
  }
  
  void checkWallCollision(){
    if (orb.x &gt; width-orb.r){
      orb.x = width-orb.r;
      velocity.vx *= -1;
      velocity.vx *= damping;
    } 
    else if (orb.x &lt; orb.r){
      orb.x = orb.r;
      velocity.vx *= -1;
      velocity.vx *= damping;
    }
  }
  
  void checkGroundCollision(Ground groundSegment) {
  
    // get difference between orb and ground
    float deltaX = orb.x - groundSegment.x;
    float deltaY = orb.y - groundSegment.y;
  
    // precalculate trig values
    float cosine = cos(groundSegment.rot);
    float sine = sin(groundSegment.rot);
  
    /* rotate ground and velocity to allow 
     orthogonal collision calculations */
    float groundXTemp = cosine * deltaX + sine * deltaY;
    float groundYTemp = cosine * deltaY - sine * deltaX;
    float velocityXTemp = cosine * velocity.vx + sine * velocity.vy;
    float velocityYTemp = cosine * velocity.vy - sine * velocity.vx;
  
    /* ground collision - check for surface 
     collision and also that orb is within 
     left/rights bounds of ground segment */
    if (groundYTemp &gt; -orb.r &amp;&amp;
      orb.x &gt; groundSegment.x1 &amp;&amp;
      orb.x &lt; groundSegment.x2 ){
      // keep orb from going into ground
      groundYTemp = -orb.r;
      // bounce and slow down orb
      velocityYTemp *= -1.0;
      velocityYTemp *= damping;
    }
  
    // reset ground, velocity and orb
    deltaX = cosine * groundXTemp - sine * groundYTemp;
    deltaY = cosine * groundYTemp + sine * groundXTemp;
    velocity.vx = cosine * velocityXTemp - sine * velocityYTemp;
    velocity.vy = cosine * velocityYTemp + sine * velocityXTemp;
    orb.x = groundSegment.x + deltaX;
    orb.y = groundSegment.y + deltaY;
  }
  
  class Ground {
    float x1, y1, x2, y2;  
    float x, y, len, rot;
  
    // default constructor
    Ground(){
    }
  
    // constructor
    Ground(float x1, float y1, float x2, float y2) {
      this.x1 = x1;
      this.y1 = y1;
      this.x2 = x2;
      this.y2 = y2;
      x = (x1+x2)/2;
      y = (y1+y2)/2;
      len = dist(x1, y1, x2, y2);
      rot = atan2((y2-y1), (x2-x1));
    }
  }
  
  class Orb{
    float x, y, r;
  
    // default constructor
    Orb() {
    }
  
    Orb(float x, float y, float r) {
      this.x = x;
      this.y = y;
      this.r = r;
    }
  }
  
  class Vect2D{
    float vx, vy;
  
    // default constructor
    Vect2D() {
    }
  
    Vect2D(float vx, float vy) {
      this.vx = vx;
      this.vy = vy;
    }
  }</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.