Archive

For May, 2012

Bouncing ball simulation in JavaScript on HTML5 canvas

No Comments

This is a port of the simple bouncing ball simulation to JavaScript on the HTML5 canvas. You can view the result here.

The HTML5 code

<!doctype html>
<html>
 <head>
  <meta charset="utf-8">
  <title>Bouncing ball</title>
  <style>
	body{background-color: #666;}
	#canvas {background-color: #ccc;}
  </style>
 </head>
 <body>
  <canvas id="canvas" width="700" height="500"></canvas>
  <script src= "bouncing_ball.js"></script>
 </body>
</html>

Nothing complicated here, assuming you’re familiar with basic HTML markup. Note the ridiculously simple HTML5 doctype, and the inclusion of a canvas element, on which we’ll draw the animation. We’ve placed the JavaScript code in the file bouncing_ball.js, and it looks like this:

The JavaScript code

// initialise canvas and context
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d'); 

// physical variables
var g = 0.1; // gravity
var fac = 0.8; // velocity reduction factor per bounce
var radius = 20; // ball radius
var color = "#0000ff"; // ball color

// initialise position and velocity of ball
var x = 50;
var y = 50;
var vx = 2;
var vy = 0;

// ensure that code does not run before page has loaded
window.onload = init; 

function init() {
// set up a timer
	setInterval(update, 1000/60); // 60 frames per second
};

function update() {
  // update velocity
  vy += g; // gravity

  // update position
  x += vx;
  y += vy; 

  // handle bouncing
  if (y > canvas.height - radius){
	y = canvas.height - radius;
	vy *= -fac;
  }

  // wrap around
  if (x > canvas.width + radius){
	x = -radius;
  }

  // update the ball
  drawBall();
};

function drawBall() {
	with (context){
		clearRect(0, 0, canvas.width, canvas.height); // clear canvas
		fillStyle = color;
		beginPath();
		arc(x, y, radius, 0, 2*Math.PI, true);
		closePath();
		fill();
	};
};

The code should be self-explanatory, but here is a quick rundown. The first two lines make the canvas element accessible to the JavaScript code by means of the DOM getElementById() method and then specifies the 2D drawing API of canvas using its getContext() method.

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');

The next 4 lines of code set the values of the acceleration of the ball (due to gravity), the velocity reduction factor each time it bounces, the radius and color of the ball. Next follow 4 more lines that set the initial position and velocity of the ball.

The next 4 lines set up the animation to get the action going.

window.onload = init; 
function init() {
    setInterval(update, 1000/60); 
};

The window.onload function ensures that the init() function is called only when the document has fully loaded. The init() function does just one thing: it calls the setInterval method, which is essentially a timer that repeatedly fires the function specified as the first argument (here it’s update) after an interval specified in milliseconds as the second argument (here it’s 1000/60, or approximately 16.7 milliseconds – 60 being the frame rate per second).

The update() function, which is called 60 times per second, looks like this:

function update() {
  vy += g;
  x += vx;
  y += vy; 
 
  if (y > canvas.height - radius){
    y = canvas.height - radius;
    vy *= -fac;
  }
 
  if (x > canvas.width + radius){
    x = -radius;
  }
  drawBall();
};

The first line increments the vertical velocity by applying the acceleration due to gravity, followed by two lines that update the position of the ball by the current values of the velocity components. Next, the two if blocks of logic handle the bouncing (by reversing the vertical velocity and reducing its magnitude on each bounce) and wraps the ball around when it leaves the canvas so that it reappears from the other side. Finally, the drawBall() method is called. It looks like this:

function drawBall() {
    with (context){
        clearRect(0, 0, canvas.width, canvas.height); 
        fillStyle = color;
        beginPath();
        arc(x, y, radius, 0, 2*Math.PI, true);
        closePath();
        fill();
    };
};

This code uses methods of the 2D drawing API to first clear the canvas, then draw a filled circle using the arc() method. Recall that this is done at each time step – the animation takes place by wiping the canvas clean and redrawing the ball in a slightly different position every time step.

That’s it – not very hard, is it? There are endless ways of enhancing the realism by introducing more and more physics effects such as friction, wind and so on. We’ll look at some of these effects in future posts.

 

Blue Taste Theme created by Jabox