HTML and CSS Reference
In-Depth Information
}());
};
</script>
</body>
</html>
Here, you are simply using the double-nested iteration to perform collision detection. In this case, the
reaction might need some additional explanation. Here's the collision reaction code located in the
checkCollision
function:
if (dist < min_dist) {
var angle = Math.atan2(dy, dx),
tx = ballA.x + Math.cos(angle) * min_dist,
ty = ballA.y + Math.sin(angle) * min_dist,
ax = (tx - ballB.x) * spring * 0.5,
ay = (ty - ballB.y) * spring * 0.5;
ballA.vx -= ax;
ballA.vy -= ay;
ballB.vx += ax;
ballB.vy += ay;
}
Remember that this occurs once a collision is found between
ballA
and
ballB
. Essentially, it starts out
the same as the earlier example with the unmoving center ball. For now, let
ballA
take the place of that
center ball. You find the angle between the two, and get a target x and y. This is the point that you would
need to place
ballB
so that the two balls would not be touching. Based on that, you get the x and y
acceleration that would cause
ballB
to spring to that point, then we cut it in half (which I explain next).
These are
ax
and
ay
.
But then you do something a little tricky. In this case, not only does
ballB
need to spring away from
ballA
, but
ballA
must spring away from
ballB
. The acceleration would be the same force and exactly
the opposite direction. So rather than calculate it twice, you just add
ax
and
ay
to
ballB
's velocity, and
subtract them from
ballA
's velocity! You get the same result, and you just saved a bunch of calculation.
You might be thinking that this doubles the final acceleration, as it's being applied twice; and that's true. To
compensate, we cut the the
spring
product in half, multiplying it by 0.5, when we calculated
ax
and
ay
.
You can remove these two multiplication operations by halving the
spring
variable when you declare it,
to 0.015.
While we're discussing optimization tricks, here's another one here. The preceding code calculates the
angle using
Math.atan2
, and then uses
Math.cos
and
Math.sin
to find the target point:
var angle = Math.atan2(dy, dx),
tx = ballA.x + Math.cos(angle) * min_dist,
ty = ballA.y + Math.sin(angle) * min_dist;
But remember that sine is opposite over hypotenuse, and cosine is adjacent over hypotenuse. And since
the opposite side of the angle is
dy
, the adjacent side is
dx
, and the hypotenuse is
dist
. Thus, you could
actually shorten these three lines to just two: