Making HTML5 Canvas Canvas

Sunday, August 11, 2013

Part 2. Animating the canvas

At the first part, we learnt how to paint on our canvas. This is good, but a game is about interacting with objects, not just painting them. Therefore, we need to start giving motion to our rectangle.

First, we declare two new variables: "x" and "y". At the beginning, after declaring the variables "canvas" and "ctx", we add the next line:
var x=50,y=50;
And then, we modify the function "paint", so the screen cleans before we paint on it again, then it fills the rectangle at the given coordinates. We will make now the rectangle a little smaller:
function paint(ctx){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.fillStyle='#0f0';
    ctx.fillRect(x,y,10,10);
}
Right now, the "init" function calls only once the "paint" function, so it is painted only once. For this to be a true animation, we must make the function to call itself over and over. For this, we will call a "run" function where "paint(ctx)" was called on the "init" function:
    run();
And create the "run" function as follows:
function run(){
    requestAnimationFrame(repaint);
    act();
    paint(ctx);
}
At the first line, we call a requestAnimationFrame. This function will ask the browser for the next time it can do an animation frame, usually at 60 frames per second on good performance computers, through it can vary to lower performance computers. To know more about it, go to Appendix 2: RequestAnimationFrame.

After that, we call the "act()" and the "paint(ctx)" functions. We have seen before that "paint" draws everything to our canvas. The "act" function is used to call all the actions in our game; in this case, we will move our rectangle by adding 2 pixels per frame to our "x" variable:
function act(){
    x+=2;
}
As the actions could be put at the "paint" function, it is recommended to do it apart, to prevent errors like, what it is displayed on the screen, is not what it is happening really (If you mix both this can happen, therefore, is better to move everything first and then paint it). Besides, doing it on separate ways makes easier to know where the events happen so we can modify them later in an easier way.

We save and open once more the page "index.html". If everything is OK, we will watch our little square run through the canvas! There it goes.... There it goes... And it left...

Yes, it left, and won't come back... I we want to see it again, the page must be updated and it will do the same. But if what we want is to keep the rectangle inside the canvas, we can give it a condition for it to return to the screen if it comes out of it, adding the next two lines after "x+=2;":
    if(x>canvas.width)
        x=0;
This way, we tell it that if it's x coordinate is greater than the width of the canvas, it comes back to the x coordinate 0. If we update now the page, we will see the rectangle comes out on one side, and comes back on the other.

Finally, to make the game look better, I'll add a black background to the canvas, this time not directly as the grey one, but from the code, right after getting the canvas ID. This way, we can keep the grey screen for debugging, and use any we want for the game:
    canvas.style.background='#000';
You can give it any hexadecimal value from '#000' to '#fff'. Experiment with different colours so you find the one you think fits the best for your game.

Compatibility issue:


Because some browser older versions don't support requestAnimationFrame as is, your should add this function at the end of your code (more at Appendix 2: RequestAnimationFrame):
window.requestAnimationFrame=(function(){
    return window.requestAnimationFrame || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame || 
        function(callback){window.setTimeout(callback,17);};
})();

Final code:

[Canvas not supported by your browser]
window.addEventListener('load',init,false);
var canvas=null,ctx=null;
var x=50,y=50;

function init(){
    canvas=document.getElementById('canvas');
    canvas.style.background='#000';
    ctx=canvas.getContext('2d');
    run();
}

function run(){
    requestAnimationFrame(run);
    act();
    paint(ctx);
}

function act(){
    x+=2;
    if(x>canvas.width)
        x=0;
}

function paint(ctx){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.fillStyle='#0f0';
    ctx.fillRect(x,y,10,10);
}

window.requestAnimationFrame=(function(){
    return window.requestAnimationFrame || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame || 
        function(callback){window.setTimeout(callback,17);};
})();

No comments:

Post a Comment