//Subject: A bouncing ball
//Author : Sjoerd.J.Schaper - vspickelen@zonnet.nl
//Date   : 26-01-2006
//Code   : JavaScript

// constants
var vo = 99.0;        // launching speed
var rs = -.12;        // resistance
var gv = 4.9;         // gravity
var ep = .17 - 1.0;   // rebound loss
var delay = 30;       // refresh rate in ms.

//global variables
var vx, vy, x, y;     // velocity, position
var oT, oL, cr;       // screen offset, corner array
var ball, box, stick; // object pointers
var err, roll, sw;    // switches

function animate() {
var u, v, xs, ys, dt;

   ball.style.top = Math.round(y + oT) + "px";
   ball.style.left = Math.round(x + oL) + "px";
   if(sw) clearInterval(roll);

   vx = check(vx, rs);               // deceleration
   vy = check(vy, rs);
   vy += gv;                         // vertical drop
   x += vx; y += vy;                 // update trajectory

   do {
      u = Math.abs(x) - cr[0];       // intersection trajectory-frame
      v = Math.abs(y) - cr[1];
      dt = 0;

      if(u > 0 || v > 0) {

         if(u > 0) {
            xs = cr[1 - sgn(x)];     // left/right
            dt = (xs - x) / vx;
            ys = y + vy * dt;
            dt = Math.abs(dt);
            vx *= ep;                // bounce
         }
         else {
            ys = cr[2 - sgn(y)];     // top/bottom
            dt = (ys - y) / vy;
            xs = x + vx * dt;
            dt = Math.abs(dt);
            v = gv * dt; vy -= v;
            vy *= ep; vy += v;

            if(y > cr[1]) {
               if(vy > 0) vy = 0;
               v = vx * vx + vy * vy;
               if(v < .0001) sw = -1; //motion damped?
            }
         }

         x = xs + vx * dt;           // adjust position
         y = ys + vy * dt;
         dt = -1;
      }
   } while(dt);
}

function check (a, da) {
   if(Math.abs(a) > -da) {
      (a < 0)? a -= da: a += da;
   }
   else a = 0;
   return a;
}

function getObj(a) {
   this.obj = document.getElementById(a);
   this.style = document.getElementById(a).style;
}

function initialize() {

   if(document.getElementById) {
      var a = navigator.userAgent.toLowerCase();
      if(a.indexOf('opera') > 0) {
         delay *= .3;
      }
      else if(a.indexOf('firefox') > 0) {
         delay *= 2;
      }
      box = new getObj('container');
      ball = new getObj('ball_id');
      stick = new getObj('stick_id');
      cr = new Array(3); err = 0; }
   else err = -1;
}

function kick() {
var u, v, w, xc, yc;

   if(err) return 0;                 // no W3C DOM
   clearInterval(roll);
   ball.style.visibility = "hidden";
   w = ball.obj.offsetWidth * .5;    // ball radius

   xc = box.obj.offsetWidth * .5;    // box center
   yc = box.obj.offsetHeight * .5;
   oT = yc + box.obj.offsetTop - w;  // offset
   oL = xc + box.obj.offsetLeft - w;

   u = stick.obj.offsetWidth * .2;
   v = stick.obj.offsetHeight * .9;
   y = stick.obj.offsetTop - yc + v; // put ball
   x = stick.obj.offsetLeft - xc + u;

   v = vo * (4 + Math.random()) * .2; //random launch
   u = -(.02 + Math.random() * .95);
   vx = v * u; vy = -v * Math.sqrt(1.0 - u * u);

   xc -= w; yc -= w;
   cr[0] = xc; cr[1] = yc;           // bottom right
   cr[2] = -xc; cr[3] = -yc;         // top left

   ball.style.visibility = "visible";
   sw = 0; animate();
   roll = setInterval('animate()', delay, 'javascript');
}

function sgn(a) {
   (a < 0)? a = -1: a = 1;
   return a;
}

