Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 789338 of Move the ball

  • Revision slug: Games/Workflows/2D_Breakout_game_pure_JavaScript/Move_the_ball
  • Revision title: Move the ball
  • Revision id: 789338
  • Created:
  • Creator: trevorh
  • Is current revision? No
  • Comment Remove iframe use

Revision Content

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls")}}

This is the 2nd step out of 10 of the Gamedev Canvas tutorial. You can find the source code as it should look after completing this lesson at Gamedev-Canvas-workshop/lesson2.html.

You already know how to draw a ball from working through the previous article, so now let's make it move. Technically, we will be painting the ball on the screen, clearing it and then painting it again in a slightly different position every frame to make the impression of movement — just like how movement works with the movies.

Defining a drawing loop

To keep constantly updating the canvas drawing on each frame, we need to define a drawing function that will run over and over again, with a different set of variable values each time to change sprite positions, etc. You can run a function over and over again using a JavaScript timing function such as {{domxref("WindowTimers.setInterval()", "setInterval()")}} or {{domxref("window.requestAnimationFrame()", "requestAnimationFrame()")}}.

Delete all the JavaScript you currently have inside your HTML file except for the first two lines, and add the following below them. The draw() function will be executed within setInterval every 10 miliseconds:

function draw() {
    // drawing code
}
setInterval(draw, 10);

Thanks to the inifinite nature of setInterval the draw() function will be called every 10 milliseconds forever, or until we stop it. Now, let's draw the ball — add the following inside your draw() function:

ctx.beginPath();
ctx.arc(50, 50, 10, 0, Math.PI*2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();

Try your updated code now — the ball should be repainted on every frame.

Making it move

You won't notice the ball being repainted constantly at the moment, as it's not moving. Let's change that. First, instead of a hardcoded position at (50,50) we will define a starting point at the bottom center part of the Canvas in variables called x and y, then use those to define the position the circle is drawn at.

First, add the following two lines above your draw() function, to define x and y:

var x = canvas.width/2;
var y = canvas.height-30;

Next update the draw() function to use the x and y variables in the {{domxref("CanvasRenderingContext2D.arc()","arc()")}} method, as shown in the following bolded line:

function draw() {
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
}

Now comes the important part: we want to add a small value to x and y after every frame has been drawn to make it appear that the ball is moving. Let's define these small values as dx and dy and set their values to 2 and -2 respectively. Add the following below your x and y variable definitions:

var dx = 2;
var dy = -2;

The last thing to do is to update x and y with our dx and dy variable on every frame, so the ball will be painted in the new position on every update. Add the following two new lines indicated below to your draw() function:

function draw() {
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
    x += dx;
    y += dy;
}

Save your code again and try it in your browser. This works ok, although it appears that the ball is leaving a trail behind it:

Clearing the canvas before each frame

The ball is leaving a trail because we're painting a new circle on every frame without removing the previous one. Don't worry, because there's a method to clear canvas content: {{domxref("CanvasRenderingContext2D.clearRect()","clearRect()")}}. This method take four parameters: the x and y coordinates of the top left corner of a rectangle, and the x and y coordinates of the bottom right corner of a rectangle. The whole area covered by this rectangle will be cleared of any content previously painted there.

Add the following bolded new line to the draw() function:

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
    x += dx;
    y += dy;
}

Save your code and try again, and this time you'll see the ball move without a trail. Every 10 milliseconds the canvas is cleared, the blue circle (our ball) will be drawn on a given position and the x and y values will be updated for the next frame.

Cleaning up our code

We will be adding more and more commands to the draw() function in the next few articles, so it's good to keep it as simple and clean as possible. Let's start by moving the ball drawing code to a separate function.

Replace the existing draw() function with the following two functions:

function drawBall() {
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
}

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawBall();
    x += dx;
    y += dy;
}

Compare your code

You can check the finished code for this article for yourself in the live demo below, and play with it to understand better how it works:

{{JSFiddleEmbed("https://jsfiddle.net/end3r/3x5foxb1/","","415")}}

Exercise: try changing the speed of the moving ball, or the direction it moves in.

Next steps

We've drawn our ball and gotten it moving, but it keeps disappearing off the edge of the canvas. In the third chapter we'll explore how to make it bounce off the walls.

{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls")}}

Revision Source

<p>{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls")}}</p>

<div class="summary">
<p>This is the <strong>2nd step</strong> out of 10 of the <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch">Gamedev Canvas tutorial</a>. You can find the source code as it should look after completing this lesson at <a href="https://github.com/end3r/Gamedev-Canvas-workshop/blob/gh-pages/lesson02.html">Gamedev-Canvas-workshop/lesson2.html</a>.</p>
</div>

<p>You already know how to draw a ball from working through the previous article, so now let's make it move. Technically, we will be painting the ball on the screen, clearing it and then painting it again in a slightly different position every frame to make the impression of movement — just like how movement works with the movies.</p>

<h2 id="Defining_a_drawing_loop">Defining a drawing loop</h2>

<p>To keep constantly updating the canvas drawing on each frame, we need to define a drawing function that will run over and over again, with a different set of variable values each time to change sprite positions, etc. You can run a function over and over again using a JavaScript timing function such as {{domxref("WindowTimers.setInterval()", "setInterval()")}} or {{domxref("window.requestAnimationFrame()", "requestAnimationFrame()")}}.</p>

<p>Delete all the JavaScript you currently have inside your HTML file except for the first two lines, and add the following below them. The <code>draw()</code> function will be executed within <code>setInterval</code> every 10 miliseconds:</p>

<pre class="brush: js">
function draw() {
    // drawing code
}
setInterval(draw, 10);</pre>

<p>Thanks to the inifinite nature of <code>setInterval</code> the <code>draw()</code> function will be called every 10 milliseconds forever, or until we stop it. Now, let's draw the ball — add the following inside your <code>draw()</code> function:</p>

<pre class="brush: js">
ctx.beginPath();
ctx.arc(50, 50, 10, 0, Math.PI*2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
</pre>

<p>Try your updated code now — the ball should be repainted on every frame.</p>

<h2 id="Making_it_move">Making it move</h2>

<p>You won't notice the ball being repainted constantly at the moment, as it's not moving. Let's change that. First, instead of a hardcoded position at (50,50) we will define a starting point at the bottom center part of the Canvas in variables called <code>x</code> and <code>y</code>, then use those to define the position the circle is drawn at.</p>

<p>First, add the following two lines above your <code>draw()</code> function, to define <code>x</code> and <code>y</code>:</p>

<pre class="brush: js">
var x = canvas.width/2;
var y = canvas.height-30;
</pre>

<p>Next update the <code>draw()</code> function to use the x and y variables in the {{domxref("CanvasRenderingContext2D.arc()","arc()")}} method, as shown in the following bolded line:</p>

<pre class="brush: js">
function draw() {
    ctx.beginPath();
    <strong>ctx.arc(x, y, 10, 0, Math.PI*2);</strong>
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
}
</pre>

<p>Now comes the important part: we want to add a small value to <code>x</code> and <code>y</code> after every frame has been drawn to make it appear that the ball is moving. Let's define these small values as <code>dx</code> and <code>dy</code> and set their values to 2 and -2 respectively. Add the following below your x and y variable definitions:</p>

<pre class="brush: js">
var dx = 2;
var dy = -2;
</pre>

<p>The last thing to do is to update <code>x</code> and <code>y</code> with our <code>dx</code> and <code>dy</code> variable on every frame, so the ball will be painted in the new position on every update. Add the following two new lines indicated below to your <code>draw()</code> function:</p>

<pre class="brush: js">
function draw() {
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
    <strong>x += dx;
    y += dy;
</strong>}</pre>

<p>Save your code again and try it in your browser. This works ok, although it appears that the ball is leaving a trail behind it:</p>

<p><img alt="" src="https://mdn.mozillademos.org/files/10430/ball-trail.png" style="width: 480px; height: 320px; margin: 0px auto; display: block;" /></p>

<h2 id="Clearing_the_canvas_before_each_frame">Clearing the canvas before each frame</h2>

<p>The ball is leaving a trail because we're painting a new circle on every frame without removing the previous one. Don't worry, because there's a method to clear canvas content: {{domxref("CanvasRenderingContext2D.clearRect()","clearRect()")}}. This method take four parameters: the x and y coordinates of the top left corner of a rectangle, and the x and y coordinates of the bottom right corner of a rectangle. The whole area covered by this rectangle will be cleared of any content previously painted there.</p>

<p>Add the following bolded new line to the <code>draw()</code> function:</p>

<pre class="brush: js">
function draw() {
    <strong>ctx.clearRect(0, 0, canvas.width, canvas.height);</strong>
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
    x += dx;
    y += dy;
}
</pre>

<p>Save your code and try again, and this time you'll see the ball move without a trail. Every 10 milliseconds the canvas is cleared, the blue circle (our ball) will be drawn on a given position and the <code>x</code> and <code>y</code> values will be updated for the next frame.</p>

<h2 id="Cleaning_up_our_code">Cleaning up our code</h2>

<p>We will be adding more and more commands to the <code>draw()</code> function in the next few articles, so it's good to keep it as simple and clean as possible. Let's start by moving the ball drawing code to a separate function.</p>

<p>Replace the existing draw() function with the following two functions:</p>

<pre class="brush: js">
function drawBall() {
    ctx.beginPath();
    ctx.arc(x, y, 10, 0, Math.PI*2);
    ctx.fillStyle = "#0095DD";
    ctx.fill();
    ctx.closePath();
}

function draw() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    drawBall();
    x += dx;
    y += dy;
}</pre>

<h2 id="Compare_your_code">Compare your code</h2>

<p>You can check the finished code for this article for yourself in the live demo below, and play with it to understand better how it works:</p>

{{JSFiddleEmbed("https://jsfiddle.net/end3r/3x5foxb1/","","415")}}

<div class="summary">
<p>Exercise: try changing the speed of the moving ball, or the direction it moves in.</p>
</div>

<h2 id="Next_steps">Next steps</h2>

<p>We've drawn our ball and gotten it moving, but it keeps disappearing off the edge of the canvas. In the third chapter we'll explore how to make it <a href="https://developer.mozilla.org/en-US/docs/Games/Workflows/Breakout_game_from_scratch/Bounce_off_the_walls">bounce off the walls</a>.</p>

<p>{{PreviousNext("Games/Workflows/2D_Breakout_game_pure_JavaScript/Create_the_Canvas_and_draw_on_it", "Games/Workflows/2D_Breakout_game_pure_JavaScript/Bounce_off_the_walls")}}</p>
Revert to this revision