topical media & game development

talk show tell print

lib-js-animation-js-ball.js / js



  

author: alex

  
  var model = {
          "walls" : {"left":0, "top":0, "right": 500, "bottom": 300},
          "elastity" : -0.2,
          "ballRadius" : 26,
          "maxSpeed" : 3.0 
  };
  
  // helper
  var extend = function(subClass, baseClass)
  {
          // Create a new class that has an empty constructor
          // with the members of the baseClass
          function inheritance() {};
          inheritance.prototype = baseClass.prototype;
          
          // set prototype to new instance of baseClass
          // _without_ the constructor
          subClass.prototype = new inheritance();
          subClass.prototype.constructor = subClass;
          subClass.baseConstructor = baseClass;
          
          // enable multiple inheritance
          if (baseClass.base)
          {
                  baseClass.prototype.base = baseClass.base;
          }
          subClass.base = baseClass.prototype;
  }
  
  
Base "platform-independent" class representing ball
parameter: {Object} x
parameter: {Object} y
parameter: {Object} vx
parameter: {Object} vy

  
  function Ball(x, y, vx, vy) {
          // default provisioning
          if (x == undefined) {
                  x = (model.walls.right - model.walls.left - 2*model.ballRadius)*Math.random(); 
                  y = (model.walls.bottom - model.walls.top - 2*model.ballRadius)*Math.random(); 
                  vx = 2*model.maxSpeed*Math.random() - model.maxSpeed;
                  vy = 2*model.maxSpeed*Math.random() - model.maxSpeed;
          }
          this._x = x;
          this._y = y;
          this._vx = vx;
          this._vy = vy;
          this._r = model.ballRadius; // d = 52 px
          this._d = 2*this._r;
          this._d2 = this._d*this._d;
  }
  
  Ball.prototype.move = function() {
          this._x += this._vx;
          this._y += this._vy;
          // walls collisons
          
          // left
          if (this._x < model.walls.left && this._vx<0) {
                  //this._vx += (this._x - walls.left)*elastity;
                  this._vx = -this._vx;
          }
          // top
          if (this._y < model.walls.top && this._vy<0) {
                  //this._vy += (this._y - walls.top)*elastity;
                  this._vy = -this._vy;
          }
          // left
          if (this._x > model.walls.right - this._d && this._vx>0) {
                  //this._vx += (this._x - walls.right + this._d)*elastity;
                  this._vx = -this._vx;
          }
          // top
          if (this._y > model.walls.bottom - this._d && this._vy>0) {
                  //this._vy += (this._y - walls.bottom + this._d)*elastity;
                  this._vy = -this._vy;
          }
  }
  
  Ball.prototype.doCollide = function(b) {
          // calculate some vectors 
          var dx = this._x - b._x;
          var dy = this._y - b._y;
          var dvx = this._vx - b._vx;
          var dvy = this._vy - b._vy;        
          var distance2 = dx*dx + dy*dy;
                  
          if (Math.abs(dx) > this._d || Math.abs(dy) > this._d) 
                  return false;
          if (distance2 > this._d2)
                  return false;
          
          // make absolutely elastic collision
          var mag = dvx*dx + dvy*dy;
          
          // test that balls move towards each other        
          if (mag > 0) 
                  return false;
  
          mag /= distance2;
          
          var delta_vx = dx*mag;
          var delta_vy = dy*mag;
          
          this._vx -= delta_vx;
          this._vy -= delta_vy;
          
          b._vx += delta_vx;
          b._vy += delta_vy;
                  
          return true;
  }
  
  
Abstract test class
parameter: {Object} N

  
  function BallsTest(N) {
          this._N = N; // number of objects
          this._ballsO = new Array();
          this._isRunning = false;
  }
  
  BallsTest.prototype._showFPS = null;
  
  BallsTest.prototype.start = function(N) {
          if (this._isRunning) return false;
          this._isRunning = true;
          
          if (N != undefined) {
                  this._N = N;
          }
          
          this._F = 0;  // frames counter for FPS
          this._lastF = 0;
          this._lastTime = new Date();
          var _this = this;
          
          var moveBalls = function() {
                  if (_this._N > _this._ballsO.length) 
                          return;
                  _this._F++;
                  // move balls
                  for (var i=0; i<_this._N; i++) {
                          _this._ballsO[i].move();
                  }
                  // process collisions
                  for (i=0; i<_this._N; i++) {
                          for (j=i+1; j<_this._N; j++) {
                                  _this._ballsO[i].doCollide(_this._ballsO[j]);
                          }
                  }
          }
          var showFps = function() {
                  if (_this._F - _this._lastF < 10) return;
                  var currTime = new Date();
                  var delta_t = (currTime.getMinutes() - _this._lastTime.getMinutes())*60 + currTime.getSeconds() - _this._lastTime.getSeconds() + (currTime.getMilliseconds() - _this._lastTime.getMilliseconds())/1000.0;
                  
                  delete currTime; 
                  
                  var fps = (_this._F - _this._lastF)/delta_t;
                  
                  _this._lastF = _this._F;
                  _this._lastTime = currTime;
                  
                  if (_this._showFPS) 
                          _this._showFPS.call(_this, Math.round(fps));
          }
  
          this._int1 = setInterval(moveBalls, 5);
          this._int2 = setInterval(showFps, 3000);
          return true;
  }
  BallsTest.prototype.stop = function(){
          if (!this._isRunning) return false;
          this._isRunning = false;
          clearInterval(this._int1);
          clearInterval(this._int2);
          return true;
  }
  


(C) Æliens 18/6/2009

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.