As shown in the preceding code example, we use the SVG Dom script style (for details about this style, see Basic SVG animation ).
The basic concept is very simple-every 16 milliseconds (that is,delay
), We move the center of the circle a little. For example, in pseudo code, we use:
<x-coordinate of circle> = <x-coordinate of circle> + 0.5<y-coordinate of circle> = <y-coordinate of circle> + 0.2
Instead of hard coding the values of delta x (0.5) and Delta y (0.2), We append two new custom attributes to the circular element, specify a velocity vector for the circle:
circle0.vx = 50; // Move the circle at a velocity of 50 pixels per second in the x-direction.circle0.vy = 20; // Move the circle at a velocity of 20 pixels per second in the y-direction.
This speed vector can be expressed graphically.V, As shown below:
Figure 1
Therefore,circle0.vx
Is the x-axis component of the circular velocity vector (measured in bytes per second), whilecircle0.vy
It is the y-axis component of the velocity vector, in the unit of bytes per second ). Note that the XY coordinate system above indicates that the origin is located in the SVG area in the upper left corner of the screen.
Now we need a function to translate a component of the velocity vector to the corresponding displacement for animation purposes. You can uses2d(v)
Function to complete this operation. For example, if
v
The parameter is 50 pixels per second anddelay
If the value is 16 ms, the displacement result obtained through dimension analysis is (50 pixels/s) • (1 S/1000 ms) • (16 ms) = 0.8 pixels.
In the end, when the circle hits the right or bottom of the SVG area, the animation stops. That is to say, we need a simple form of Collision Detection:
Javascript
if ( (circle0.cx.baseVal.value > (boxWidth - r)) || (circle0.cy.baseVal.value > (boxHeight - r)) ) clearInterval(timer);
Because we need to determine when the side of the circle hits the wall (relative to the center of the circle), we must subtract the radius of the circle, as shown in the code segment above (that isboxWidth – r
And
boxHeight – r
).
Using the above collision detection technology, the following example shows the trajectory of the ball (that is, the circle) moving from the wall:
Example 2-one wall bounce
Activity link:Example 2
<!DOCTYPE html>
The key concept of ball bounce is vector reflection, as shown in the following simplified figure:
Figure 2
In Figure 2, the black dotted line on the right shows the wall,VIn indicates the speed vector before the ball hits the wall,VOut indicates the velocity vector after the ball hits the wall. As you can see (in this particular case), the only difference is the symbol of the x-axis component of the outward velocity vector amplitude. Therefore, to let the ball bounce off the right wall, you only need to change the x-axis component symbol of the ball's velocity vector:
Javascript
if ( circle0.cx.baseVal.value > (boxWidth - r) ) circle0.vx *= -1;
Please note that we have decided to stop the animation when the ball hits the wall:
Javascript
if ( circle0.cy.baseVal.value > (boxHeight - r) ) clearInterval(timer);
In the above example, there is a set factor. The Code takes effect only when the ball is initially completely moved in the correct direction. The following example eliminates the manual setting. But before you proceed, let's take another 2. Imagine a blue vector bounce from the left wall. Obviously, depending on the right wall, you only need to change the x-axis component symbol of the velocity vector to get the correct behavior. By using the same parameters for the top wall and the bottom wall, you can see that you only need to change the symbol of the Y axis component to get the correct result. This is the logic used in the following example:
Example 3-four sides bounce
Activity link:Example 3
<!DOCTYPE html>
Example 2-one wall bounce and Example 3-Four Wall bounce
verticalWallCollision(r, width)
AndhorizontalWallCollision(r, height)
These two functions. The latter function only contains the following code line:
Javascript
return ( (circle0.cy.baseVal.value <= r) || (circle0.cy.baseVal.value >= (height - r)) );
This line of seemingly mysterious code can be easily understood:
Figure 3
As shown in 3, when the Y coordinate of the ball center is greater than or equal to the distance from the base wall r, it indicates that the ball has collided with the base wall. The distance is expressedHeight-R. Therefore, our tests on the base wall will become:
Javascript
circle0.cy.baseVal.value >= (height - r)
Similarly, when the Y coordinate of the ball center is less than or equal to the distance R, it indicates that the ball has collided with the top wall. Again, the distance is represented as R-0 = R. Therefore, the test on the top wall is as follows:
Javascript
circle0.cy.baseVal.value <= r
Merge the two tests to generate the preceding return statement.
Example 4-two-ball collision
Activity link:Example 4
Watching a ball bounce back and forth in the box can be entertaining for several minutes. However, adding another ball to the box in the next step will add some fun. To perform this operation, the ball-to-ball collision and related mathematical operations are required. Example 4 is provided below to help you start the operation. Note that the sample code is not displayed due to the length.View SourceFunction to view associated code. For convenience, the following is an example
4 screens:
First, we create an object that represents the generic vectors and functions of four common vector operations:
- Vector Addition.
- Vector subtraction.
- The scalar is multiplied by the vector.
- Point product (scalar) of two vectors ).
If you understand basic vector operations, these functions can be directly implemented. For a better understanding of vectors and their associated operations, see
Wikipedia or wolfram mathworld.
Note that, in this example, the vector function is included in the script block marked as "vector functions" with corresponding annotations. However, it should be noted that each circular element (I .e. the ball) moves along its own velocity vector as shown below (see
init
Function ):
Javascript
var gv0 = new Vector(0, 0);ball0.v = gv0;ball0.v.xc = 200; ball0.v.yc = 80;
A new generic vector is created locally.gv0
And the vector is appended to the globalball0
Circle element. After this operation, the x-axis and Y-axis components of the velocity vector of the ball 0 are set to 200 pixels per second and 80 pixels per second respectively.
The collision between the ball and the wall has been described in Example 3. Now there is a collision between the ball and the ball. Unfortunately, the associated mathematical operations are very complicated. At the high level, to determine the correct speed vector after the collision of the two balls, the following mathematical calculations are required:
- Calculate the relative velocity using the velocity vector before the collision of two ballsVAB:Javascript
var Vab = vDiff(ballA.v, ballB.v);
- Calculate the normal unit vector of the collision pointN:Javascript
var n = collisionN(ballA, ballB);
- Calculate "impulse"FConservation of momentum:Javascript
f = f_numerator / f_denominator;
- Calculate the relative velocity using the velocity vector before the collision of two ballsVAB:Javascript
ballA.v = vAdd( ballA.v, vMulti(f/Ma, n) ); ballB.v = vDiff( ballB.v, vMulti(f/Mb, n) );
For more information, see the "have collision, will travel" section in the collision response.
Example 5-put all together: ball arena
Activity link:Example 5
Now we have introduced the collision between the ball and the wall, and between the ball and the ball. We can extend Example 4 to place all the balls in a sphere arena rather than in a box for collision, A "ball Arena ".
The sample code is not displayed due to the length (use "View Source"You can view the Code ). However, the following screen is provided:
Key code items to be mentioned include:
- Programmatically create all ball elements (that is
circle
And add custom attributes to these elements (such as velocity vector objects ).
- The color, radius, and initial position of each ball (in the arena) are randomly selected. Therefore, each time you refresh the page, different initial condition sets are obtained.
- Because each ball no longer excludes the wall of a simple box, the equation of conventional vector reflectionV-2 (V • N) NUsed to calculate the correct speed vector after the ball hits the arena wall. For more information, see
Reflection.
- The quality of each ball is equal to the area of the ball (that is, the circle.
- By adjusting the recovery coefficient (that is
constants.epsilon
), You can adjust the energy loss of each bounce. Value 1 indicates that no energy should be lost, just like a pure elastic collision.
Example 6-object-oriented ball arena
Example 6 is exactly the same as Example 5, but it adopts a more object-oriented approach.
Exercise
Compared with the last two examples, the following logical steps may include:
- Add reset button.
- Add button to increase or decrease the number of balls used in simulation.
- Add button to increase or decrease the simulation speed.
- Add button to reduce the recovery factor.
- Add a button for switching the ball tracking (each ball will have a "moving track", which indicates the position where the ball center has passed ).
- The most important thing is to improve collision detection that is as simple as possible in simulation.
These extensions are reserved for your exercises. They will help you understand the technology described in this topic to a great extent.
Related Topics
-
Basic SVG Animation
-
HTML5 graphics
-
Scalable Vector Graphics (SVG)