vmars316 Posted June 15, 2016 Share Posted June 15, 2016 (edited) Hello & Thanks , From topic : http://w3schools.invisionzone.com/index.php?showtopic=55453#entry304554 I have lots of questions about requestAnimationFrame So I decided to make this question a separate issue : The code size is trimmed way down from the actual running game , to make it easy to follow . Here is the updated function to start and stop animation : var myGameArea = { start: function() { thrower.moveMe = false; // interval = setInterval(updateGameArea, 5); gid = requestAnimationFrame(updateGameArea); }, clear: function() { ctx.clearRect(0, 0, canvas.width, canvas.height); }, stop: function() { // clearInterval(this.interval); cancelAnimationFrame(gid); console.log('stop: function cancelAnimationFrame GID'); } } How come the 'stop' function doesn't work ? <div id="buttons" class="center" align="center"> <button type="button" onclick="myGameArea.start()" ontouchstart="myGameArea.start()">Start</button> <button type="button" onclick="myGameArea.stop()" ontouchstart="myGameArea.stop()">Stop</button> </div> And here is the game loop : function updateGameArea() { setTimeout(function() { myGameArea.clear(); targetImgsCnt = 0; if (idTag == "truth01" && truth01.visible) { truth01.update(); } targetImgsCnt = 1; if (idTag == "lies01" && lies01.visible) { lies01.update(); } targetImgsCnt = 2; if (thrower.visible) { if (thrower.moveMe) { thrower.update(); } ctx.drawImage(targetImgs[targetImgsCnt], thrower.x, thrower.y, thrower.width, thrower.height); thisIdTag = thrower.idTag; visible = this.visible; tripsMax = this.tripsMax; tripsCnt = this.tripsCnt; directionX = this.directionX; thisx = this.x; } requestAnimationFrame(updateGameArea); }, 1000 / framesPerSecond); } Also : var gid; var framesPerSecond = 17; Here are my ?s : How come the 'stop' function doesn't work ? Why is it so slow ? I have tried several speeds , but always , soooo slow . And this really puzzles me : I can increase the speed by simply clicking the 'start' button repeatedly . Though , I suppose I could add another 'start' button and call it 'Increase Speed' button I would rather use the methods (timestamp & performance.now) here : https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame and here : https://developer.mozilla.org/en-US/docs/Web/API/Performance/now But I can't piece it all together , to make it work . I would like some help with this also . Thanks Edited June 15, 2016 by vmars316 Link to comment Share on other sites More sharing options...
justsomeguy Posted June 15, 2016 Share Posted June 15, 2016 What's that call to setTimeout doing in updateGameArea? You're telling the browser that you want to run your function right before the browser is going to repaint the page, but the only thing that function does is schedule some code to run later. Why not run that code immediately, right before the browser updates the page? That's when you should be updating things on the page, when the browser is ready to show them. You use the timestamp passed to the callback function to figure out how much you need to move everything. How come the 'stop' function doesn't work ?Because it only cancels the very first frame, which already happened long before you press that button. You re-schedule the animation frame callback in the other function, but you don't save the ID for that to stop it. Basically, you need to stop using setTimeout and setInterval, and rely only on requestAnimationFrame and the timestamp that gets passed to the callback to figure out how much everything needs to move. Link to comment Share on other sites More sharing options...
Ingolme Posted June 15, 2016 Share Posted June 15, 2016 Like I said, you should use the timestamp that's passed as a parameter to your function. function updateGameArea(timestampIsInHere) { console.log(timestampIsInHere); It's an argument that's passed into your function by the browser. You can give it whatever name you want. You should not use setTimeout or setInterval while using requestAnimationFrame, because requestAnimationFrame is intended to substitute those functions. The concept of "frames per second" no longer exists when you use requestAnimationFrame. Each time the function is called you are given a timestamp telling you the current time with microsecond precision. You have to use that timestamp to determine how much to change the values in your program. Link to comment Share on other sites More sharing options...
vmars316 Posted June 17, 2016 Author Share Posted June 17, 2016 Thanks All , Ah , finally , I get it . I misread var start = null; var element = document.getElementById("SomeElementYouWantToAnimate"); element.style.position = 'absolute'; function step(timestamp) { if (!start) start = timestamp; var progress = timestamp - start; element.style.left = Math.min(progress/10, 200) + "px"; if (progress < 2000) { window.requestAnimationFrame(step); } } window.requestAnimationFrame(step); And thought I must use 'timestamp' in some way , until I started tinkering with the code above , turning it into this : <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <canvas id="canvas" width="400" height="200" style="background-color:#992D2D"></canvas> <br> <button id="start_Me" onmouseup="startMe()" ontouchend="startMe()">Click to Start Me</button> <br><br> <button id="stop_Me" onmouseup="stopMe()" ontouchend="stopMe()">Click to Stop Me</button> <script> // var gid; var loopCount = 0; var lastTimestamp = 0; var LoopDuration = 0; var durationAverage = 0; // var start = null; var element = document.getElementById("stop_Me"); element.style.position = 'absolute'; function step(timestamp) { if (loopCount < 1) {durationAverage =0; LoopDuration = 0;} if (!start) start = timestamp; var progress = timestamp - start; element.style.left = Math.min(progress/10, 400) + "px"; // if (progress < 2000) { loopCount += 1; // = loopCount + 1; LoopDuration = timestamp - lastTimestamp; if (loopCount < 11) { console.log("LoopDuration = " + LoopDuration) ; durationAverage = durationAverage + LoopDuration } lastTimestamp = timestamp; if (loopCount > 399) { stopMe(); window.location.reload(); } gid = window.requestAnimationFrame(step); // } } //window.requestAnimationFrame(step); function startMe() { gid = window.requestAnimationFrame(step); console.log('start: gid = window.requestAnimationFrame(step);') } function stopMe() { cancelAnimationFrame(gid); console.log('stop: function cancelAnimationFrame gid'); console.log("durationsTotal = " + durationAverage) ; durationAverage = durationAverage / 10.0; console.log("durationAverage = " + durationAverage) ; } </script> </body> </html> This works as intended , except for the 1st loopDuration which reports as '2454857.5550000095' . I am curious why that happens . It seems that loopDuration runs between 16.xxx to 32.xxx . Also , there is a 1 ==> 2 second delay for this to happen : window.location.reload(); Another anomaly (to me) is that when I run code online : It runs fine except that when it encounters if (loopCount > 399) { stopMe(); window.location.reload(); } It goes into a loop . And I have to use TaskManager to shut it down . Thanks Link to comment Share on other sites More sharing options...
Ingolme Posted June 17, 2016 Share Posted June 17, 2016 That's because lastTimestamp starts off as 0. You should have this at the beginning of your function: function step(timestamp) { if(lastTimestamp == 0) { lastTimestamp = timestamp; } This makes sure that on the first frame the delta time is zero so nothing changes. Link to comment Share on other sites More sharing options...
Ingolme Posted June 17, 2016 Share Posted June 17, 2016 If you want to stop the loop, just don't call requestAnimationFrame(). if (loopCount > 399) { window.location.reload(); } else { // Only called if loopCount < 400 gid = window.requestAnimationFrame(step); } Link to comment Share on other sites More sharing options...
vmars316 Posted June 18, 2016 Author Share Posted June 18, 2016 Foxy Mod , Ah , much better : liesandcowpies.com/javascript/measureTimestamp.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <!-- http://liesandcowpies.com/javascript/ http://jsbeautifier.org --> </head> <body> <canvas id="canvas" width="400" height="200" style="background-color:#992D2D"></canvas> <br> <button id="start_Me" onmouseup="startMe()" ontouchend="startMe()">Click to Start Me</button> <br><br> <button id="stop_Me" onmouseup="stopMe()" ontouchend="stopMe()">Click to Stop Me</button> <br><br> <p id="traceMsg"></p> <script> // var gid; var loopCount = 0; var lastTimestamp = 0; var loopDuration = 0; var durationSums = 0; var durationAverage = 0; var oneTraceLine = ''; // var start = null; var element = document.getElementById("stop_Me"); element.style.position = 'absolute'; function step(timestamp) { if (lastTimestamp == 0) { lastTimestamp = timestamp; } if (!start) start = timestamp; var progress = timestamp - start; element.style.left = Math.min(progress / 10, 400) + "px"; loopCount += 1; loopDuration = timestamp - lastTimestamp; if (loopCount < 12) { writeTraceLog("loopCount = " + loopCount + " , loopDuration = " + loopDuration); durationSums = durationSums + loopDuration } lastTimestamp = timestamp; if (loopCount > 399) { stopMe(); } else { // Only called if loopCount < 400 gid = window.requestAnimationFrame(step); } } //window.requestAnimationFrame(step); function startMe() { gid = window.requestAnimationFrame(step); writeTraceLog('start: gid = window.requestAnimationFrame(step);') } function stopMe() { cancelAnimationFrame(gid); writeTraceLog('stop: function cancelAnimationFrame gid'); writeTraceLog("durationSums = " + durationSums); durationAverage = durationSums / 10; writeTraceLog("durationAverage = " + durationAverage); // window.location.reload(); } function writeTraceLog(oneTraceLine){ document.getElementById("traceMsg").innerHTML += (oneTraceLine + "<br>"); } </script> </body> </html> Thank You very much ! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now