/*Basic Javascript Physics simulator... 2x balls launched from different positions in different directions. NB: the reality is flawed - the balls will only stop if both gravity and friction reach 0. They never will unless you hard set them. Even then, they'll drop and 'roll' til settling against an edge. The balls also don't have a diameter. The collision point is their centre. TO DO: At the moment, collision detection is just between each object and the bounds of "the world". Need to add collision detection between objects. TO DO: Presently a 2D simulation. Needs the point and vector classes adapting to 3D, and then the math updating as necessary to account for Z plane. */ function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { relative: function(to) { return new Vector(to.x - this.x, to.y - this.y); }, distance: function(to) { return Math.sqrt(Math.pow(this.x - to.x, 2) + Math.pow(this.y - to.y, 2)); } }; function Vector(x1, x2) { this.x1 = x1; this.x2 = x2; } Vector.prototype = { add: function(other) { return new Vector(this.x1 + other.x1, this.x2 + other.x2); }, scale: function(by) { return new Vector(this.x1 * by, this.x2 * by); }, normalize: function() { function norm(value) { return value > 0 ? 1 : value < 0 ? -1 : 0; } return new Vector(norm(this.x1), norm(this.x2)); } }; var GRAVITY = new Vector(0, 9.81); var FRICTION = 0.8; var world = { x1: 0, y1: 0 }; world.x2 = 100; world.y2 = 100; var data=[]; function Ball(data) { this.position = new Point(200, 200); this.velocity = new Vector(-5, 0); } Ball.prototype = { move: function() { // apply gravity this.velocity = this.velocity.add(GRAVITY.scale(0.1)); // collision detection against world if ((this.position.y > world.y2)) { this.velocity.x2 = -this.velocity.x2 * FRICTION; this.position.y = world.y2; } else if ((this.position.y < world.y1)) { this.velocity.x2 = -this.velocity.x2 * FRICTION; this.position.y = world.y1; } if ((this.position.x < world.x1)) { this.velocity.x1 = -this.velocity.x1 * FRICTION; this.position.x = world.x1; } else { if ((this.position.x > world.x2)) { this.velocity.x1 = -this.velocity.x1 * FRICTION; this.position.x = world.x2; } } // update position this.position.x += this.velocity.x1; this.position.y += this.velocity.x2; } }; var balls = []; // add first ball... var start = new Point(0, 0); var end = new Point(2, 2); var ball = new Ball(); ball.position = end; ball.velocity = start.relative(end).scale(0.2); ball.move(); balls.push(ball); //add 2nd ball... var start2 = new Point(90, 10); var end2 = new Point(100, 100); var ball2 = new Ball(); ball2.position = end2; ball2.velocity = start2.relative(end2).scale(0.2); ball2.move(); balls.push(ball2); //if adding more balls, don't forget to add another pair of outputs! function main(){ GRAVITY = new Vector(0,arguments[1]); FRICTION = arguments[2]; var i=0, d1=0, d2=1; if (arguments[0]=true) { balls.forEach(function(aball) { aball.move(); data[d1]=aball.position.x - 50; data[d2]=aball.position.y - 50; i++; d1 = d1+2; d2 = d2+2; }); return data; } }