Solution 1 :

I have checked and found out the issue is in the first statement of tick function. When program starts then value of parameter is undefined. And thats why first statement of tick function result in NaN.

Just use some default value for parameter “timestamp”. Its working now but speed is low and i hope you are aware about it.

Line to check:
function tick(timestamp=10)

function tick(timestamp=10) {
  deltatime = (timestamp - oldframetime) / 1000;

  var step = deltatime * speed;
  var newlocx = movetowards(x, dstx - 50, 5);
  var newlocy = movetowards(y, dsty - 50, 5);

  ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
  ctx.fillStyle = 'green';
  ctx.fillRect(newlocx, newlocy, 100, 100);

  x = newlocx;
  y = newlocy;
  console.log(newlocx + ":" + newlocy);
  oldframetime = timestamp;
  requestAnimationFrame(tick);
}

Solution 2 :

You should be starting the animation with requestAnimationFrame rather than indirectly as you have done.

Replace

requestAnimationFrame(function(){
tick();
});

with

requestAnimationFrame(tick)

Then in the function tick you check if oldframetime has been set, if not set deltaTime to 0, as no time has passed, and thus starts the animation at the start. If you set the value of deltaTime to any other value you end up not rendering the animation from the start.

function tick(timestamp){
    if (!oldframetime) { 
       deltaTime = 0;
    } else { 
       deltatime = (timestamp - oldframetime)/1000;  
    }

    // .. animation code

    oldframetime = timestamp;
    requestAnimationFrame(tick);
}

Problem :

I’m trying to have a simple rectangle move from current location to the clicked location on the canvas. When I provide a constant speed, the rectangle appears and moves fine. But when I multiply it by deltatime the rectangle doesn’t appear anymore. I’m using requestAnimationFrame as the draw loop.

canvas.js

window.addEventListener('DOMContentLoaded', (event) => {
    let canvas = document.getElementById("gamecanvas");
    let ctx = canvas.getContext('2d');
    var oldframetime = 0;
    var x = 0;
    var y = 0;
    var dstx = 0;
    var dsty = 0;
    var deltatime = 0;
    var speed = 5;
    function getmousepos(evt){
        var rect = canvas.getBoundingClientRect();
        return {
          x: evt.clientX - rect.left,
          y: evt.clientY - rect.top
        };
    }
    canvas.addEventListener("mousedown",e=>{
        let coord = getmousepos(e);
        dstx = coord.x;
        dsty = coord.y;
    });
    function movetowards(current,target,maxdistancedelta){
        if(Math.abs(target - current)<=maxdistancedelta){
            return target;
        }
        return current+Math.sign(target - current) * maxdistancedelta;
    }
    function tick(timestamp){
        deltatime = (timestamp - oldframetime)/1000;   

        var step = deltatime*speed;
        var newlocx = movetowards(x,dstx-50,5);
        var newlocy = movetowards(y,dsty-50,5);

        ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
        ctx.fillStyle = 'green';
        ctx.fillRect(newlocx,newlocy,100,100);

        x = newlocx;
        y = newlocy;
        console.log(newlocx+":"+newlocy);
        oldframetime = timestamp;
        requestAnimationFrame(tick);
    }
    requestAnimationFrame(function(){
        tick();
    });
});

In that example, newlocx and newlocy both print NaN:NaN
But if I choose not to use step and give it a constant speed of like 5, then it works fine.

    function tick(timestamp){
        deltatime = (timestamp - oldframetime)/1000;   

        var step = deltatime*speed;
        var newlocx = movetowards(x,dstx-50,5);
        var newlocy = movetowards(y,dsty-50,5);

        ctx.clearRect(0,0,canvas.clientWidth,canvas.clientHeight);
        ctx.fillStyle = 'green';
        ctx.fillRect(newlocx,newlocy,100,100);

        x = newlocx;
        y = newlocy;
        console.log(newlocx+":"+newlocy);
        oldframetime = timestamp;
        requestAnimationFrame(tick);
    }

The print is also accurate now. Why does multiplyng step by deltatime prevent the rectangle from moving? Or even appearing?

Here’s the HTML if anyone’s interested.

index.html

<html>
    <head>
        <script src="canvas.js"></script>
    </head>
    <body>
        <canvas id="gamecanvas" width="2000" height="1000"></canvas>
    </body>
</html>

Comments

Comment posted by Jasdeep Singh

Can you please paste your entire code ? It would be better if you create a working instance of your issue.

Comment posted by Irelia

Sure. I added the html with it as well.

Comment posted by Andre Nuechter

Is the speed maybe so high the shape is immediately moved out of view?

Comment posted by Irelia

No @AndreNuechter I’ve done the multiplication myself which is 5*0.016(60 fps) and that’s a value of 0.08 which is just very slow. I’ve put in 0.08 myself and it still appears.

Comment posted by Irelia

Ah, thank you but why would timestamp be undefined ? Shouldn’t it have a value when the function tick is called by requestanimationframe?

Comment posted by Jasdeep Singh

As you can see when we are calling tick method for the first time from inside window.DOMContentLoaded, we are not passing any argument. Any unassigned value in javascript has default value of undefined. This is the reason it is undefined for first time.

Comment posted by Irelia

Oh I understand. Then couldn’t I just call tick(0) inside requestAnimationFrame? Yes that seems to solve it as well

Comment posted by Irelia

so just call function tick with timestamp of 0?

Comment posted by Blindman67

@Nina No don’t call

Comment posted by Irelia

Oh! Gotcha! Thanks!

By