JLuc01
JLuc01

Reputation: 187

Moving from setInterval method to requestAnimationFrame with sprite

I am trying to use the method 'requestAnimationFrame' with the help I can find on Internet. I can move an element, but when I want to do it with sprites, I am lost.

For example, the code below is working normally with 'setInterval', but I cannot manage to make it work with 'requestAnimationFrame'.

<!DOCTYPE html>

<html>

<head>

<title>Animating Sprites in HTML5 Canvas</title>

<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no">

<style>
.demo {background: #aaaaaa;}
#myCanvas{background: #cccccc}
</style>

</head>

<body class="demo">

<canvas id="myCanvas" width="800" height="100"></canvas>

<script>

(function() {

// Canvas
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
// Set the fill style for the drawing context.
ctx.fillStyle = '#3399ff';

    // VARIABLES
    var width = 48;           // Width CANVAS
    var height = 60;          // Height CANVAS
    var xFrame = 0;           // Frame x coordinate
    var yFrame = 0;           // Frame y coordinate
    var dxFrame = 0;          // Frame dx position in canvas
    var dyFrame = 0;          // Frame dy position in canvas
    // SPRITE used
    image = new Image()
    image.src = 'myRunner2.png';
    //
    var requestID;

// shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return  window.requestAnimationFrame || 
        window.webkitRequestAnimationFrame || 
        window.mozRequestAnimationFrame || 
        window.oRequestAnimationFrame || 
        window.msRequestAnimationFrame || 
        function(/* function FrameRequestCallback */ callback, /* DOMElement         Element */ element){
            window.setTimeout(callback, 1000 / 60);
        };
})();

    // FUNCTION DRAWING MOVE (xFrame = 0 & yFrame = 1)      
    var drawMove = function(){
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(image, width * xFrame, height * yFrame, width, height, dxFrame, dyFrame, width, height);
        if (xFrame == 7) {
            xFrame = 0;
        } else {
            xFrame++
            dxFrame+=2;
        }
        //window.requestAnimFrame(eMove);
        }
    // ANIMATION in 3 moves: Idle + Move + Tired
    var intA;
    function eMove() {
        // Runner in motion (8 frames)
        yFrame = 1;
        xFrame = 0;
        clearInterval(intA);
        intA = setInterval(drawMove, 100);
    }
    eMove();
}());

</script>

</body>

</html>

I am looking for help about this issue, a portion of code will be great but a way to work or a direction to look for will be good as well. How to manipulate sprite with the method 'requestAnimationFrame'?

Ultimately, my goal is to move a sprite in one direction and the background in the other direction. I can move the sprite in one direction with setTimeout/setInterval methods alone or I can move in the other direction the background with 'requestAnimationFrame', but also separately.

I hope you understand my problem. Thank you,

JLuc01

Upvotes: 0

Views: 1225

Answers (1)

Shikkediel
Shikkediel

Reputation: 5205

For requestAnimationFrame to work well it needs an accurate timer by which it can update the progress. The animation would then also depend on this variable. Of course a total duration will have to be set as well (to measure the progress). Here's a general piece of code :

var initial = update = new Date().getTime(), progress = 0, duration = 2000;
requestAnimationFrame(frameSequence);

function frameSequence() {

update = new Date().getTime();
var elapsed = update-initial;
progress = Math.max(elapsed/duration, 1);

someFunction(); // do calculations and implement them based on progress

if (progress < 1) requestAnimationFrame(frameSequence);
}

And a live example (relevant code at the bottom)

http://codepen.io/Shikkediel/pen/vEzqoX?editors=001

Edit - some comments promoted to update :

The requestAnimationFrame call is just a basic loop really to replace the timeout. It could be as simple as using requestAnimationFrame(drawMove) instead of clearInterval(intA); intA = setInterval(drawMove, 100). It'll probably do the whole thing in 8/60 of a second that way though (I see there are 8 frames and 60 is the common display refresh rate) - hence a timer would be needed.

This would optimise and work for sure : setInterval(requestAnimationFrame(drawMove), 100). It will not force a frame on the display then like a timeout does (giving performance issues and flickering) but make it wait for the first appropriate instance when there is a new paint of the screen. But not using timeouts at all is a much better approach.

Upvotes: 1

Related Questions