Rotations and translations for drawing

In document Using Games to Learn HTML5 and JavaScript (Page 119-123)

HTML5 lets us translate and rotate drawings. Take a look at the following code. I urge you to create this example and then experiment with it to improve your understanding. The code draws a large red rectangle on the canvas with the upper corner at (50,50) and a tiny blue, square on top of it.

<html>

<head>

<title>Rectangle</title>

<script type="text/javascript">

var ctx;

function init(){

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

ctx.fillStyle = "rgb(250,0,0)";

ctx.fillRect(50,50,100,200);

ctx.fillStyle = "rgb(0,0,250)";

ctx.fillRect(50,50,5,5);

}

</script>

</head>

<body onLoad="init();">

<canvas id="canvas" width="400" height="300">

Your browser doesn't support the HTML5 element canvas.

</canvas>

</body>

</html>

104

The result is shown in Figure 4-6.

Figure 4-6. Rectangle (no rotation)

In this exercise, the goal is to rotate the large rectangle, pivoting on the upper-left corner where the small blue square is. I want the rotation to be counterclockwise.

One slight complication, common to most programming languages, is that the angle input for rotations as well as the trigonometry functions must be in radians, not degrees. Radians were explained in Chapter 2, but heres a reminder. Instead of 360 degrees in a full circle, the measurement is based on two times the mathematical constant pi radians in a circle. Fortunately, we can use the built-in feature of JavaScript, Math.PI. One pi radians is equivalent to 180 degrees and pi divided by 2 is equivalent to a right angle, 90 degrees. To specify a rotation of 30 degrees, we use pi divided by 6 or, in coding, Math.PI/6. To change the init function given previously to do a rotation, I put in a rotation of negative pi divided by 6 (equivalent to 30 degrees going counterclockwise), draw the red rectangle, and then rotate back, undo the rotation, to draw the blue square:

function init(){

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

ctx.fillStyle = "rgb(250,0,0)";

ctx.rotate(-Math.PI/6);

ctx.fillRect(50,50,100,200);

ctx.rotate(Math.PI/6);

ctx.fillStyle = "rgb(0,0,250)";

ctx.fillRect(50,50,5,5);

}

Unfortunately, the drawing in Figure 4-7 is not what I wanted.

105 Figure 4-7. Drawing and rotating a rectangle

The problem is the rotation point is at the origin, (0,0) and not at the corner of the red rectangle. So, I need to write code to perform a translation, then the rotation, then a translation back in order to draw at the correct place. I can do this using features of HTML5. All drawing on the canvas is done in terms of a coordinate system, and I can use the save and restore operations to save the current coordinate system—the position and orientation of the axes—and then restore it to make follow-on drawings. Heres the code.

function init(){

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

ctx.fillStyle = "rgb(250,0,0)";

ctx.save();

ctx.translate(50,50);

ctx.rotate(-Math.PI/6);

ctx.translate(-50,-50);

ctx.fillRect(50,50,100,200);

ctx.restore();

ctx.fillStyle = "rgb(0,0,250)";

ctx.fillRect(50,50,5,5);

}

The rotate method expects an angle in radian units and clockwise is the positive direction. So my code is rotating 30 degrees counterclockwise, producing what I had in mind, as shown in Figure 4-8.

Figure 4-8. Save, translate, rotate, translate, restore

106

By the way, we can't expect our players to put in angles using radians. They, and we, are too accustomed to degrees (90 degrees is a right angle, 180 degrees is your arc when you make a u-turn, etc.). The program must do the work. The conversion from degrees to radians is to multiply by pi/180.

Note: Most programming languages use radians for angles in trig functions. Flash uses degrees in certain situations and radians in others, so in some ways JavaScript is less confusing by only using radians.

With this background, I add to the information in the everything array indications as to whether there is to be a rotation and, if so, the required translation point. This is my idea. It has nothing to do with HTML5 or JavaScript, and it could have been done differently. The underlying task is to create and maintain information on objects in the simulated scene. The canvas feature of HTML5 provides a way to draw pictures and display images, but it does not retain information on objects!

The items in the everything array for the second and third applications are themselves arrays. The first (0th index) value points to the object. The second (1st index) is true or false. A value of true means that a rotation angle value and x and y values for translation follow. In practice, this means that the inner arrays have either two values, with the last one being false, or five values.

Note: At this point, you may be thinking: she set up a general system just to rotate the cannon. Why not put in something just for the cannon? The answer is we could, but the general system does work and something just for the cannon might have had just as much coding.

The first application uses horizontal and vertical displacement values picked up from the form. The player must think of the two separate values. For the second application, the player inputs two values again, but they are different. One is the speed out of the mouth of the cannon and the other is the angle of the cannon. The program does the rest. The initial and unchanging horizontal displacement and the initial vertical displacement are calculated from the player's input: the velocity out of the cannon and an angle.

The calculation is based on standard trigonometry. Luckily, JavaScript provides the trig functions as part of the Math class of built-in methods.

Figure 4-9 shows the calculation of the displacement values from the out of cannon and angle values specified by the player. The minus sign for the vertical is due to the way JavaScript screen coordinates have y values increasing going down the screen.

107 Figure 4-9. Calculating horizontal * vertical displacements

At this point, you may want to skip ahead to read about the implementation of the cannonball applications.

You can then come back to read about what is required for the slingshot.

In document Using Games to Learn HTML5 and JavaScript (Page 119-123)