Taking Advantage of Canvas Rotations

Properly applied, canvas rotations can help simplify code and make your game run much more smoothly. Take as an example our Rocket Racers game, in which two cars race around a circular racetrack. Rather than draw the cars at each location, which we deemed to be too cumbersome, we decided to rotate the canvas and simply draw the car at the same location relative to the canvas. This technique is showcased in the following video:

The process for this simple technique was as follows:

  • Translate the context to the center of the canvas.
  • Rotate the context by the car's current angle around the track.
  • Translate the context back to the top left corner of the canvas.

Note that since the car was moving in a circle around the center of the canvas, the center of the canvas marks the axis of our rotation, i.e. the point that we are rotating about. Whenever rotating the context, we should always first translate to the axis of rotation; after rotating, we should always translate to the top-left corner of the object image.

As an example, let's say that we wish to draw an object whose center is located at point (x,y), rotated by angle θ about the axis point (u,v). The object we wish to draw is an image of width w and height h.

First we find the distance from the object's center to the axis of rotation, which we will call r:

var r = Math.sqrt((u-x)*(u-x) + (v-y)*(v-y));

Next we translate to the axis of rotation, rotate by θ and translate back to the center of the object (which is a distance r above the axis of rotation in our new coordinate system).

context.translate(u,v);
context.rotate(θ);
context.translate(0,-r);

Remember that we have only translated to the center of the image, so we need to translate again to the top-left corner. We then draw the image at this location.

context.translate(-w/2.-h/2);
context.drawImage(objectImage,0,0);

Remember that you still need to use your context for drawing other things, so it is smart to save and restore your context. Combining some steps, altogether this looks as follows:

context.save();
context.translate(u,v);
context.rotate(θ);
context.drawImage(objectImage,-w/2,-h/2-r);
context.restore();

In addition to Rocket Racers, we have also used this technique to make the cue follow the mouse around in our pool games, and we similarly used it to make the bubble canon follow the cursor in Bubble Shooter. In pool, the axis of rotation was simply the tip of the cue and in Bubble Shooter it was the center of the canon. In both cases the angle was determined by the angle from the cursor's location to the axis of rotation.

2 thoughts on “Taking Advantage of Canvas Rotations”

Leave a Reply

Your email address will not be published. Required fields are marked *