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);
}
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);
}
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>
Can you please paste your entire code ? It would be better if you create a working instance of your issue.
Sure. I added the html with it as well.
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.
Ah, thank you but why would timestamp be undefined ? Shouldn’t it have a value when the function tick is called by requestanimationframe?
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.
Oh I understand. Then couldn’t I just call tick(0) inside requestAnimationFrame? Yes that seems to solve it as well