- This topic has 13 replies, 3 voices, and was last updated 10 years, 6 months ago by Code_A.
-
AuthorPosts
-
Code_AMemberI am running into an issue that doesn’t make sense to me. Hopefully someone can help me shed some light on this.
I have two timers, one that fires 60 times / sec., and another one that fires every second to display how many times the main timer fired during the 1 second interval. This second timer is just confirming the main timer is working as expected (i.e., firing 60 times / second).
All works fine in the simulator (getting ~60 fires), however I am getting vastly different results depending on the device I install the app on, for example:
iPhone5 = ~60 (as expected!)
iPod4 = ~25
iPad1 = ~25
Droid Xyboard 8.2= ~35Why are they not all ~60? I wouldn’t expect hardware would make the big of a difference in the timer. Does this have something to do with the asynchronous nature of the timers, or is there a flaw in my logic? Is there a better way to implement the timer to get them all at 60 no matter what the device?
this.count = 0; this.start(); //start main timer this.start = function() { var self = this; this.oneSecondTimer(); //start timer to display count every second setInterval(function() { self.count++; }, 1000/60 ); //60 frames per second }; this.oneSecondTimer = function(){ var self = this; setInterval(function() { alert(self.count); self.count = 0; }, 1000) };
support-octavioMemberHi Code A,
I shared your issue with the dev team and learned that this happen because there is no guarantee on how often timer procedures are called. They can eat battery on mobile browsers so usually this time is limited for mobile devices.
To be as fast as and as battery-friendly as possible you must use requestAnimationFrame
Code_AMemberOctavio, thank you for the information. I will try to implement the timer on the way that you have suggested. Hopefully I get more consistent results using this method!
Code_AMemberSo I am trying to implement this but I am not having much luck. Hopefully someone with more JS experience can help me out. All this code worked when I was using sertInterval(), but now that I have switched to requestAnimationFrame() method it no longer works after one execution. I feel like it has something to do with the *this* keyword. I have tried several different variations but to no avail. Any ideas?
this.start(); this.start = function tick() { var self = this; requestAnimationFrame(tick); self.loop (); // <--- throws an error telling me this function is undefined after first execution!!! }; this.loop = function () { this.update(); this.draw(); };
TurgutGuneysuMemberHi CodeA,
This is not a direct answer, but there might be some explanation somewhere in these lines:
http://learn.jquery.com/javascript-101/this-keyword/
TG
Code_AMemberOk. So I have simplified the code to just run a recursive loop using this requestAnimationFrame() Example. I can only get the loop() function to execute once. Any help on this would be greatly appreciated. I have also included the .js file. Just add it to a .mobi file and it should run.
var test; function testThis() { this.start = function tick() { requestAnimationFrame(tick); this.loop(); }; this.loop = function () { alert("looping..."); }; } window.onload = function() { test = new testThis().start(); };
Attachments:
You must be logged in to view attached files.
TurgutGuneysuMemberHi CodeA,
Here is a looping version for you.
Got rid of all the “this” syntax to simplify.
Added a START button to kick things off, so one can setup the console view etc to see the trace output.
TG
See attachment CodeA.mobi
Attachments:
You must be logged in to view attached files.
Code_AMemberTG, thank you for your continued support. I appreciate your help with this issue.
One thing I should’ve mentioned is that all of my code is contained within the single .js file and I use an html widget as canvas to draw the game. I could try to separate out the looping part as you have suggested, but before restructuring all of my code I wanted to see if there was a way to get it to work the way I have it currently organized.
I have to think there is a way to maintain scope when calling the requestAnimationFrame function. I was able to do it with setInterval, but why not now? What is different?
TurgutGuneysuMemberHi CodeA,
Here is your code fixed to loop.
I think there were two issues:
1 – THIS reference: was always pointing to window() and causing your code not be found in the right place.
2 – the function that calls the requestAnimationFrame() recursively needs to have the timestamp parameter in the definition.Yada yada yada – it’s working !
I still have the execution start tied to the START button to control it.
You can easily lock it to window.onload.TG
Attachments:
You must be logged in to view attached files.
Code_AMemberThanks again for all of your help. I have found your example to be very useful and a good reference as I try to figure this out.
@tguneysu wrote:1 – THIS reference: was always pointing to window() and causing your code not be found in the right place.
How can I get THIS to remain in the scope of my start() function during the recursive call?
TurgutGuneysuMemberI found this article (pun intended) explaining scope that is very helpful:
http://javascriptplayground.com/blog/2012/04/javascript-variable-scope-this/Also:
//This calls myFunction with "this" set to obj. myFunction.call(obj, arg1, arg2, ...);
Along with this, if you do a series of “console.log(this)” displays, you can trace the “this” settings.
TG
Code_AMember@TG (or anyone else!)
Thank you for your continued support. I have read the article you posted along with some others, but I am struggling to get this to work. I can get it working just fine using the JS timer, but not when I use the requestAnimationFrame() method.I have put together a better example of my program and the exact situation I am facing. If you have time, I would appreciate you taking one more look at my code to try to get it working. Make sure the .test.js is included the JS libraries section of the .mobi file. When it runs, you should see it counting the loop iterations.
Thanks again.
Attachments:
You must be logged in to view attached files.
Code_AMemberMaybe another way to ask the same question about THIS:
Here is how I maintain the scope of THIS using the setInterval() method (and it works):
this.start = function tick(timestamp) { var self = this; setInterval(function() { self.loop(); }, 1000/60); }; this.loop = function () { alert("looping..."); };
Here I am trying to maintain the scope of THIS using the same logic with the recursive requestAnimationFrame() method (but it doesn’t work):
this.start = function tick(timestamp) { var self = this; //recursive call is resetting the scope of THIS!!! requestID = requestAnimationFrame(tick); self.loop(); }; this.loop = function () { alert("looping..."); };
How do I maintain the scope of THIS with the recursive function?
Code_AMemberAfter much searching, I finally found the solution. This is how you can maintain the scope of THIS with a recursive function call.
this.start = function () { var self = this; requestAnimationFrame(function(){self.start()}); //this is how you make the recursive call to the function self.loop(); }; this.loop = function () { alert("looping..."); };
Thanks for the help everyone.
-
AuthorPosts