Cool DHTML: Animating Objects Within Irregular Shapes

Some years ago I was faced with a very interesting and unusual problem: how to describe the infinite movement of a ball within an arbitrary closed area. The problem seemed intractable, because it involved calculating the reflection angle and speed of the ball (a bounce) whenever it encountered any arbitrary point on an arbitrary border. Unfortunately, performing those calculations involved rather complex calculations and would have slowed the code down so much that it would become infeasible. In addition, the solution for the ball’s reflection from any sharp corner would become undefined.Finally, I realized that I could solve the problem using a completely opposite approach?rather than describing the reflection of the ball from the border, you can describe the reflection of the border from the ball!
Consider a ball moving in a certain direction. By tracking down the points on the front side of the ball, and finding out which one of them leaves the area first, you can then consider that point approximately as the point of the next collision. Therefore, the direction of the ball’s movement after the collision may be calculated from that rather easily (see Figure 1).

Step 1. Drawing the Area
First, select and draw an area. For this example, use an area that is symmetric along its vertical axis (see Figure 2).

You add the ball in three steps. First of all, you add an image to the body of the document that refers to a small red circle, seven pixels in diameter:

Next, you add an object-oriented reference to the ball. The reference consists of:

1. Two new variables:
``   var colBalls;   var iBalls = 0;``
1. Two dummy functions (you’ll see the implementation later in this article):
``   function MoveBall(){}   function CalculateDirection (){}``
1. Two constructors. The first one is for the balls collection:
``   function clsBallsCollection()       {       this.Balls = new Array();       this.length = this.Balls.length;       }``

The second one is for the ball object (see the clsBall function in Listing 2).

Finally, you initialize the balls collection and the ball within the InitBall function, adding the following code to it:

``   colBalls = new clsBallsCollection();   for (var i = 0; i<=iBalls; i++)       {       var objBall = new clsBall(-1, -1);       objBall.Index = colBalls.length++;       colBalls.Balls[objBall.Index] = objBall;       }``

Listing 2 shows the the HTML document at this point.. Nothing moves yet,?everything’s static?but you’re ready to add the movement.

To implement the ball’s movement, you need to add five new functions to the page, plus one new line of code within the InitBall function that starts calling the MoveBalls function in a repetitive manner. Listing 3 contains the complete version of the HTML document, including the functions listed below. The five new functions are:

IsWithinShape(X, Y). This decision-maker function tests whether the dot with co-ordinates (X,Y) is contained within the shape defined by the GetShape function;

MoveBalls(). Loops through the collection of the balls on the page and for each ball calls its Move method that points to the MoveBall function. Then loops through each pair of balls and takes care their collisions;

MoveBall(). This is one of the three major functions on the page. First, the method gets a reference from the script ball object to the appropriate HTML ball object on the page. Then it increases the properties of both the script object and the HTML object depending on their direction and speed. Finally, it analyzes for exceptional conditions such as the center of the ball moving outside the defined shape (that happens once in a while with certain types of shapes because of approximations that may lead to such errors). In that case it moves the ball back into the shape. If IsWithinShape(iCenterX, iCenterY) returns 1 (true), which is almost always the case, then it calls the ball’s CalcDirection method. That, in turn, points to the CalculateDirection method, which performs the rest of the work.

CalculateDirection(iCenterX, iCenterY). This method loops through the points around the center of the ball on the side of the ball that faces the direction of movement. For each point, the function calls the FindPreciseAngle method, which analyzes whether the point is within the shape. If not, it finds the point where the ball touches the shape’s border with the predefined precision, and returns the angle between the direction of the ball’s movement and the direction from the ball’s center towards the point of touch. Then CalculateDirection calculates the new direction for the ball based on the idea that it should be changed on the angle opposite the angle towards the point of touch. Finally, it reassigns all the properties of the ball script object.

FindPreciseAngle(iBigRadius, nDirection, iCenterX, iCenterY, iGrad, iPrecision). This method works in conjunction with the previous function but is separate to make the code more readable. You use the iPrecision parameter to tune it up; there is an obvious trade off between performance and precision.

Figure 3 shows the completed animation in action.

Figure 3: The Completed Animation. The animation shows the result of animating a small ball within an arbitrary closed figure, where the collision of a ball with the border produces a reflection (a bounce) angled appropriately.

2. Save the Ball Image (Ball1.gif) to a folder on your machine.
3. Copy the code from Listing 3 into a new text document, and save it with an HTM extension into the same folder as the Ball Image
4. Open the file with Internet Explorer, and enjoy the result.

To see more examples of this approach, visit http://www.extraidea.com/ and browse the various examples there by clicking on each main area of the site.

The technique discussed in this article represents an application that starts with certain known conditions but then may branch off in defined but unpredictable directions. This approach may become a basis for the new types of games, because it makes the computer behave more like a human?independently from the application creator.

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.