- HTML5 Game Development by Example:Beginner's Guide(Second Edition)
- Makzan
- 1049字
- 2025-04-04 20:55:44
Time for action – Moving the ball with JavaScript Interval
We will use the function to create a timer. The timer moves the ball a little bit every 30 milliseconds. We are going to also change the direction of the ball movement once it hits the playground edge. Let's make the ball move now:
- We will use our last example, listening to multiple keyboard inputs, as the starting point.
- Open the
js/pingpong.js
file in the text editor. - In the existing
pingpong.playground
object, we change to the following code that adds height and width to the playground.playground: { offsetTop: $("#playground").offset().top, height: parseInt($("#playground").height()), width: parseInt($("#playground").width()), },
- We are now moving the ball, and we need to store the ball's status globally. We will put the ball-related variable inside the
pingpong
object:var pingpong = { //existing data ball: { speed: 5, x: 150, y: 100, directionX: 1, directionY: 1 } }
- We define a
gameloop
function and move the ball on each game loop iteration:function gameloop() { moveBall(); }
- We define the functions to check whether the ball is hitting the four boundary walls of the playground:
function ballHitsTopBottom() { var y = pingpong.ball.y + pingpong.ball.speed * pingpong.ball.directionY; return y < 0 || y > pingpong.playground.height; } function ballHitsRightWall() { return pingpong.ball.x + pingpong.ball.speed * pingpong.ball.directionX > pingpong.playground.width; } function ballHitsLeftWall() { return pingpong.ball.x + pingpong.ball.speed * pingpong.ball.directionX < 0; }
- Then, we define two functions that reset the game after either player wins.
function playerAWin() { // reset the ball; pingpong.ball.x = 250; pingpong.ball.y = 100; // update the ball location variables; pingpong.ball.directionX = -1; } function playerBWin() { // reset the ball; pingpong.ball.x = 150; pingpong.ball.y = 100; pingpong.ball.directionX = 1; }
- It is time to define the
moveBall
function. The function checks the boundaries of the playground, changes the direction of the ball when it hits the boundaries, and sets the new ball position after all these calculations. Let's put the followingmoveBall
function definition in the JavaScript file:function moveBall() { // reference useful varaibles var ball = pingpong.ball; // check playground top/bottom boundary if (ballHitsTopBottom()) { // reverse direction ball.directionY *= -1; } // check right if (ballHitsRightWall()) { playerAWin(); } // check left if (ballHitsLeftWall()) { playerBWin(); } // check paddles here // update the ball position data ball.x += ball.speed * ball.directionX; ball.y += ball.speed * ball.directionY; }
- We have calculated the ball's movement. Next, we want to render the view to update the ball's position based on the data. To do this, define a new
renderBall
function with the following code.function renderBall() { var ball = pingpong.ball; $("#ball").css({ "left" : ball.x + ball.speed * ball.directionX, "top" : ball.y + ball.speed * ball.directionY }); }
- Now, we need to update the
render
function to render the ball's update based on the updated game data:function render() { renderBall(); renderPaddles(); window.requestAnimationFrame(render); }
- The following lines of code is the new
init
function where we added agameloop
logic with thesetInterval
function:function init() { // set interval to call gameloop logic in 30 FPS pingpong.timer = setInterval(gameloop, 1000/30); // view rendering window.requestAnimationFrame(render); // inputs handleMouseInputs(); }
- We have prepared the code to move the ball every 33.3 milliseconds. Save all the files and open
index.html
in the web browser to test it. The paddles work just as in the last example, and the ball should be moving around the playground.
What just happened?
We just successfully made the ball move around the playground. We have a loop to run routine game logic 30 times per second. Inside that game loop, we moved the ball five pixels at a time. You can try the game and view the code in progress at http://makzan.net/html5-games/pingpong-wip-step6/.
There are three properties of the ball: speed, and the x and y directions. Speed defines how many pixels the ball moves in each step. The direction X/Y is either 1 or -1. We move the ball using the following equation:
new_ball_x = ball_x_position + speed * direction_x new_ball_y = ball_y_position + speed * direction_y
The direction value is multiplied by the movement. When the direction is 1, the ball moves to the positive direction of the axis. When the direction is -1
, the ball moves to the negative direction. By toggling the x and y directions, we can move the ball in four directions.
We compare the ball's X
and Y
values with the four edges of the playground DIV element. This checks whether the ball's next position is beyond the boundary, and then, we toggle the direction between 1 and -1 to create the bouncing effect.
Creating a JavaScript timer with the setInterval function
We have a timer to loop and move the ball periodically. This can be done by the setInterval
function in JavaScript.
Here is the general definition of the setInterval
function:
setInterval(expression, milliseconds)
The setInterval
takes two required arguments. Additional arguments are passed into the function as parameters:

Understanding the game loop
We have a timer to execute some game-related code every 33.3 milliseconds, so this code is executed 30 times per second. This frequency is known as frames per second, or FPS. In game development, this timer is called the game loop.
There are several common things that we will execute inside a game loop:
- Processing user input, which we just did
- Updating game objects' status, including position and appearance
- Checking game over
What is actually executing in the game loop differs in different types of games, but the purpose is the same. The game loop is executed periodically to calculate the game data.
Separating the data and the view logic
We have separated the data and the view logic. We used setInterval
for data and requestAnimationFrame
for view rendering. The data focuses on all the game data calculation, including an object's dimension and position based on the calculation. The view
logic focuses on updating the interface based on the keep-updating game data.
In our render function, the view updates the CSS of the DOM elements. Imagine later if we are rendering the game in the Canvas, or using any other techniques, that our view rendering logic can use a specific method to render the view based on the same game data. The game data's calculation is independent to the techniques we use to render the game interface.