Say you have two objects on the canvas element and you want to find out how far apart they are. This is the most common use of the Pythagorean Theorem when programming animation.
What do you have to work with? You have the x and y positions of each object. Let’s call the position of one x1, y1, and the other x2, y2. This is a situation like the one illustrated in Figure 3-22.
x1, y1
x2, y2
dist
?
Figure 3-22. What is the distance between the two objects?
If you have been following this chapter closely, you see a right-angle triangle forming in the diagram in Figure 3-22, with the distance line as the hypotenuse. In Figure 3-23, we finish and add some actual numbers.
63
x2, y2(58, 50)
x1, y1 (50, 56)
dx = 8
dy = –6 dist
?
Figure 3-23. Turn it into a right-angle triangle.
Here,
dx
is the distance between the two objects on the x axis, anddy
is the distance on the y axis. You can now finddx
by subtracting x1 from x2: 58 - 50 = 8. Similarly, you subtract y1 from y2 to getdy
, which is −6. Now, using the Pythagorean Theorem, if you square both of these and add them together, you get the square of the distance. In other words −62 + 82 = dist2. Breaking that down, you get 36 + 64, or 100 = dist2. With some basic algebra, you can reduce that to.100 = dist
. And from that, you can easily figure out that the distance between the two objects is 10.Let’s abstract that a bit so you have a formula that you can use in any situation. Given two points, x1, y1 and x2, y2, you figure the x distance and y distance, square them, sum them, and take the square root.
Here it is in JavaScript:
var dx = x2 – x1, dy = y2 – y1,
dist = Math.sqrt(dx * dx + dy * dy);
Pay particular attention to these lines because they make up the next big tool in your toolbox. The first two lines get the distances on each axis. If you are interested in the distance and won’t use
dx
anddy
to calculate any angles, it doesn’t matter whether you subtract x1 from x2 or vice versa. The final result fordist
is always positive. The last line performs three steps in one shot: It squares each of the values, adds them, and finds the square root. For clarity, you can break down the steps into separate statements. After you are familiar with that single line, it will be clear to you. You see it and think “Pythagorean Theorem.”Let’s try it in a real world example. The next example,
10-distance.html
, creates a couple of rectangles, randomly positions them, and then calculates and prints the distance between them.<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Distance</title>
<link rel="stylesheet" href="style.css">
</head>
64
<body><canvas id="canvas" width="400" height="400"></canvas>
<textarea id="log"></textarea>
<script src="utils.js"></script>
<script>
window.onload = function () {
var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'),
log = document.getElementById('log');
//Create a black square, assign random position.
var rect1 = {
x: Math.random() * canvas.width, y: Math.random() * canvas.height };
context.fillStyle = "#000000";
context.fillRect(rect1.x - 2, rect1.y - 2, 4, 4);
//Create a red square, assign random position.
var rect2 = {
x: Math.random() * canvas.width, y: Math.random() * canvas.height };
context.fillStyle = "#ff0000";
context.fillRect(rect2.x - 2, rect2.y - 2, 4, 4);
//Calculate the distance between the two squares.
var dx = rect1.x - rect2.x,
Run this file in your web browser and you will see the distance between the two rectangles printed out to the
textarea
element in our document. Each time you run it, the two rectangles will be in different positions. It shouldn’t matter if one is to the right, left, top, or bottom of the other, you’ll always get a positive value for the distance.Well that’s interesting, but not dynamic. Just to show you that you can do this in real time, try the next example,
11-mouse-distance.html
:<link rel="stylesheet" href="style.css">
</head>
65
<body><canvas id="canvas" width="400" height="400"></canvas>
<textarea id="log"></textarea>
<script src="utils.js"></script>
<script>
window.onload = function () {
var canvas = document.getElementById('canvas'), context = canvas.getContext('2d'),
mouse = utils.captureMouse(canvas), log = document.getElementById('log'),
rect = {x: canvas.width / 2, y: canvas.height / 2};
(function drawFrame () {
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
var dx = rect.x - mouse.x, dy = rect.y - mouse.y,
dist = Math.sqrt(dx * dx + dy * dy);
//draw square
context.fillStyle = "#000000";
context.fillRect(rect.x - 2, rect.y - 2, 4, 4);
//draw line
context.beginPath();
context.moveTo(rect.x, rect.y);
context.lineTo(mouse.x, mouse.y);
context.closePath();
context.stroke();
//log output of distance value to screen log.value = "distance: " + dist;
}());
};
</script>
</body>
</html>
Here,
dx
anddy
are calculated by subtracting the current mouse position fromrect
’s position. Thedist
value is displayed in the textarea element, and a line is drawn from the rectangle to the mouse location (you find more on the canvas drawing API in Chapter 4).Test the file and move your mouse around. A line connects it to the rectangle, and you get a constant readout of the length of that line.
In later chapters when discussing collision detection, we mention some weaknesses with the generic testing functions, and see how you can use the Pythagorean Theorem formula to create a distance-based method of collision detection. This theorem is also useful in calculating forces such as gravity or springs, where the force between two objects is proportional to the distance between them.