Pong-3 adds motion to the ball upon the user pressing enter.

Important Functions

  • Math.random()
    • Returns a random number between 0 and 1.
  • Math.min(number1, number2)
    • Returns the lesser of the two numbers passed in.
  • Math.max(number1, number2)
    • Returns the greater of the two numbers passed in.
  • Math.floor(floatingPointNumber)
    • Returns the largest integer less than or equal to a given floating point number.

Important Code

You’ll see a few new variables near the bottom of load():

main.ts
let ballX = CANVAS_WIDTH / 2 - 10;
let ballY = CANVAS_HEIGHT / 2 - 10;
let ballDX = generateRandomNumber(400, 600);
let ballDY = generateRandomNumber(400, 600);
let gameState = 'start';

ballX and ballY will keep track of the ball position, while ballDX and ballDY will keep track of the ball velocity. gameState will serve as a rudimentary “state machine”, such that we’ll cycle it through the different states of our game (start, play, etc.).

In update(), we tweak our code for paddle movement by wrapping it around the Math.max() and Math.min() functions to ensure that the paddles can’t move beyond the edges of the screen:

main.ts
if (keys.w) {
player1Y = Math.max(0, player1Y - PADDLE_SPEED * dt);
} else if (keys.s) {
player1Y = Math.min(CANVAS_HEIGHT - 200, player1Y + PADDLE_SPEED * dt);
}
if (keys.ArrowUp) {
player2Y = Math.max(0, player2Y - PADDLE_SPEED * dt);
} else if (keys.ArrowDown) {
player2Y = Math.min(CANVAS_HEIGHT - 200, player2Y + PADDLE_SPEED * dt);
}

We also add new code to ensure the ball can only move when we are in the “play” state:

main.ts
if (gameState === 'play') {
ballX += ballDX * dt;
ballY += ballDY * dt;
}

Following this, we add functionality to launch the game and reset the ball when Enter is pressed.

The Enter-key branch should do three things:

  1. consume the key press so holding Enter does not repeatedly toggle the state,
  2. move from start into play,
  3. otherwise return to start, center the ball, and generate fresh velocity values.

Once in the “play” state, the ball’s position changes each frame using its velocity and DeltaTime.

Lastly, we tweak our render() function so that we can see the changes from update() at each frame:

main.ts
context.fillRect(ballX, ballY, 20, 20);

The only change of note is using the ball’s position variables to draw the ball to the screen instead of the static values we had before. This will make it appear like the ball is travelling across the screen.

🧩 Challenge: Launch and reset the moving ball

Finish the Enter-key state transition so Enter starts play from start and resets the ball when pressed during play.

Desired result placeholder

Powered by WebContainers
Files
Preparing Environment
  • Installing dependencies
  • Starting Vite dev server