In order to animate the ball within the court, we must write some JS code. There are three parts to the code we need: the global variables, the animation loop, and the trigger. It is important that you understand this. The basic concepts here are used in the game project as well.
Global Variables
Before we start animating, we need to create variables within the JS that will be used to make calculations. These are called global variables. They are set at the start of the program, and they are used throughout. In this animation, we need to bring the actors in the JS, we need to set the boundaries of the court (so the ball bounces), and we need a variable to track the ball’s position. We will also use this section of the JS code to place the ball in the horizontal centre of the court.
You will need a <script> tag to contain the JS code. As usual, write this tag at the end of of your HTML file, just before the closing body tag. All the code that follows should appear within this script tag.
So first, we need to create handlers for the two actors. This makes referring to them throughout the code easier. So we create two variables that refer to the elements in the DOM. Because the values of these references will not change in the program we write, we use the const command to create them, like this:
//The court
const court = document.getElementById("court");
//The ball
const ball = document.getElementById("ball");
Now we need a variable to control the vertical position of the ball. In our animation, the ball only moves up and down, so we only need one variable to control its position on the y axis. The animation will consist in changing the value of this variable every time the ticker ticks. You will see this variable used a lot in the animation code. If we wanted the ball to move left and right, we would need another variable. Notice that here, we use the let command to create the variable, because the value will change, that’s the whole point. The value of this variable will be translated to CSS in the animation code and applied to the top CSS attribute of the ball. (More about this later.) The ball starts at position 0, which is the top of the court, so we assign it the value 0.
//Position of ball (top)
let p = 0;
The next global variable we’ll create is the boundary of the bottom of the court. We need to calculate this because of the height of the ball. If the ball were flat, the bottom of the court would equal the height of the court. But because the ball has a height of its own, the bottom of the court – in the logic of the code – is the height of the court minus the height of the ball. This is maths, again, I know. We don’t want to have to calculate this every time we need it, so we make it a global variable. This one is also a constant.
//Lower point of court
const bottom = court.offsetHeight - ball.offsetHeight;
Finally, we need an operator to determine the direction of the ball. The position of the ball in time is determined by a calculation. In the math (or logical) context, every time the ticker ticks, the next position is either greater than the current position (ball is going down) or it is lesser than the current position (ball is going up). So in math terms, ball going down means addition, ball going up means subtraction. So we simply need to use a multiplyer that has a positive or negative value whenever we want to change direction – when the ball hits a court boundary. This will be our operator. When its value is positive, 1, the ball goes down; when it is negative, -1, the ball goes up.
//Operator (to change direction)
let oper = 1;
Before we get started on the next section of the code, we need to position the ball in the horizontal centre of the court. The ball will move up and down, but we want it to stay in the middle horizontally. It is easier to position the ball using JS, so here is the simple code to achieve this. Notice how we transform the numerical value of the JS calculation into a CSS value with a unit. We’ll do this to the vertical position as well later on.
//Place ball in horizontal centre of stage
ball.style.left = court.offsetWidth/2 - ball.offsetWidth/2 + "px";
Just to be sure you can compare your code with mine, here is how the whole Global Variables section should look.
/*** GLOBAL VARIABLES ***/
//The court
const court = document.getElementById("court");
//The ball
const ball = document.getElementById("ball");
//Position of ball (top)
let p = 0;
//Lower point of court
const bottom = court.offsetHeight - ball.offsetHeight;
//Operator (to change direction)
let oper = 1;
//Place ball in horizontal centre of stage
ball.style.left = court.offsetWidth/2 - ball.offsetWidth/2 + "px";
Next, we will write the animation loop.
Animation Loop
Now that we have our global variables, we can write the code that will set the animation in motion. The animation code is all built within a function. And we will call this function using the ticker later; the function will be called every time the ticker ticks. (If you’re following, the ticker’s rate sets the FPS of our animation.) So the first thing we do is create the function.
const bounce = function() {
};
I will not repeat the lines above in the code samples below, but all the code we will discuss in this section has to be written within this function (before the closing curly brackets). Note that there are different ways of creating functions in JS, this is done here using a reference method. Don’t worry too much about this for now.
The first thing we need to do in the loop is to check if the ball has reached a boundary of the court and needs to change direction – to bounce. Remember that we use the oper variable to determine the direction. So we make a test. If the position of the ball, p is greater than the bottom of the court (calculated in the global variables), or if it is lesser than the top of the court (which is 0), then mathematically invert the value of the oper: in maths, multiply the number by -1.
//Detect reaching court boundary
if (p > bottom || p < 0) {
//Change direction
oper *= -1;
}
And then, we need to move the ball. Remember that this function will be called every time the ticker ticks. The purpose of this function is to move the ball, to create the animation. So this is what it does. We calculate the next position by adding 15 pixels (this sets the speed which can be different) in the current direction: positive is down, negative is up.
//Move ball by 15px in direction of oper (logical, math)
p = p + 15 * oper;
Once we have the numeric value of the next position, we need to translate it in a usable CSS value that we can assign to the top property of the ball. So we take the numeric value and add a unit to it, px, so we can assign it to the CSS.
//Set ball at logical position (in CSS)
ball.style.top = p + "px";
That’s it for the animation loop. Here is the whole thing for your reference.
/*** Animation Loop ***/
const bounce = function() {
//Detect reaching court boundary
if (p > bottom || p < 0) {
//Change direction
oper *= -1;
}
//Move ball by 15px in direction of oper (logical, math)
p = p + 15 * oper;
//Set ball at logical position (in CSS)
ball.style.top = p + "px";
}
Trigger
Lastly, we need to start the animation. This is the easiest step. So we have setup the initial elements, and the global variables. Then we have written the code that calculates and controls the animation (the position of the ball). Now the last step is to start the animation by setting up our ticker, and calling the animation loop. The code looks like this.
/*** Trigger animation ***/
let i = setInterval(bounce,40); //runs at 25 frames per sec
This animation’s FPS is 25. The interval uses milliseconds. We set it at 40 milliseconds, so it will tick 25 times per seconds. (1000 divided by 25 equals 40. Maths again.) Note that setInterval does not run at the exact set interval all the time. In the game we will use a different ticker, and this one will have a better FPS rate and will be more accurate.
Congratulations! You have built an animation in pure JS. The result should look like what I have presented at the start of the tutorial.
One more thing is important to note. You will have more than one animation written in JavaScript in your showcase file. Be careful to use different names for the functions and variables of your different animations. Otherwise, you will have conflicts between them.