Now that we have gravity we’re really seeing some natural looking movement. Yet, it’s still missing something. In the real world we have friction or drag (or even air resistance) on everything. Without this friction it’s like these balls are moving in space. Even when they bounce on the walls they don’t loose any velocity, it’s just reversed. Typically, there should be a dampening effect that lessens the velocity by a fraction because it looses some speed in turning around on the wall. In this step we’re decreasing the velocity of x and y slightly every frame with a friction variable we’ve set to .98. Over time we see the velocity lessen and the dots move slower and slower until they come to a stop. e’re also updating the bounce variable from -1 to -.96, just to give a sense that changing direction lessens the velocity. interactive physics animations via javascript & canvas | 13.

[cc lang=”javascript”]

$(function () {

var canvas, context, width, height, x, y, radius = 25, clickX, clickY, drag = false;

var total_dots = 25;

var fps = 24;

var bounce = -.96;

var gravity = 2;

var friction = .98;

canvas = $(“#canvas”)[0];

context = canvas.getContext(“2d”);

var dots = new Array();

var drag_i = -1;

var this_dot = {};

for (var i=0; i < total_dots; i++){
var this_dot = {
x: Math.random()*canvas.width,
y: Math.random()*canvas.height,
vx: Math.random()*30-10,
vy: Math.random()*30-10,
width:canvas.width,
height: canvas.height,
radius:Math.random()*20+10
};
dots.push(this_dot);
}
draw();
$("#canvas").mousedown(function (event) {
var dx, dy, dist;
for (var i=0; i < dots.length; i++){
dx = event.pageX - this.offsetLeft - dots[i].x;
dy = event.pageY - this.offsetTop - dots[i].y;
dist = Math.sqrt(dx * dx + dy * dy);
if(dist < radius) {
drag = true;
drag_i = i
clickX = dx;
clickY = dy;
continue;
}
}
});
$("#canvas").mouseup(function (event) {
drag = false;
drag_i = -1;
});
$("#canvas").mousemove(function (event) {
if(drag) {
dots[drag_i].x = event.pageX - this.offsetLeft - clickX;
dots[drag_i].y = event.pageY - this.offsetTop - clickY;
draw();
}
});
function update(){
for (var i=0; i < dots.length; i++){
if (drag_i != i){
var this_dot = dots[i];
this_dot.vx *= friction;
this_dot.vy = this_dot.vy * friction + gravity;
this_dot.x += this_dot.vx;
this_dot.y += this_dot.vy;
if (this_dot.x > canvas.width – this_dot.radius){

this_dot.x = canvas.width – this_dot.radius;

this_dot.vx = this_dot.vx * bounce;

}

else if(this_dot.x < 0 + this_dot.radius){
this_dot.x = this_dot.radius;
this_dot.vx = this_dot.vx * bounce;
}
if (this_dot.y > canvas.height – this_dot.radius){

this_dot.y = canvas.height – this_dot.radius;

this_dot.vy = this_dot.vy * bounce;

}

else if(this_dot.y < 0 + this_dot.radius){
this_dot.y = this_dot.radius;
this_dot.vy = this_dot.vy * bounce;
}
}
}
}
function draw() {
context.clearRect(0, 0, canvas.width, canvas.height);
for (var i=0; i < dots.length; i++){
context.beginPath();
context.arc(dots[i].x, dots[i].y, dots[i].radius, 0, Math.PI * 2, false);
context.fill();
context.closePath();
}
}
setInterval(function() {
update();
draw();
}, 1000/fps);$("#gravity").click(function(){
if($("#gravity").is(':checked')){
gravity = 2;
}
else{
gravity = 0;
}
});
});
[/cc]Follow the whole Interactive Physics Animations via Javascript & Canvas series.