0 votes
by (680 points)

Hello guys.

Throughout most of my Twine story, I've been using Sugarcube <<repeat>> macros (which I have read is basically the javascript setInterval method) to time certain automatically triggering events and for the most part, it has been working great!  I trigger the repeat macro every 100 miliseconds since there are certain events that require precise timing.... and I've found out that precise timing isn't exactly setInterval's forte...

I've come to understand that the usage of <<repeat>> to constantly change the value of variables and <<replace>> them into the passage's divs is what game programmers would call a "game loop", and I've also come to understand that setInterval is not a very good way to do it. 

The problem is especially apparent during  a "bossfight" which has the <<repeat>> macro running for at least 10 minutes (or probably longer if the player takes longer to kill the boss): it lags the browser, and makes the setInterval timing go haywire.

I set out to test the discrepancy in timing between setInterval and the computer's clock using a simple test passage: 

Actual Clock: <span id="timer">0ms</span>
setInterval Clock: <span id="timer2">0ms</span>
Timing discrepancy: <span id="disc">0ms</span>

<<set $initial_time to new Date()>>\
<<set $setinterval_time to 0>>\

<<repeat 100ms>>
	<<set $setinterval_time += 100>>
    <<replace "#timer">><<print new Date() - $initial_time>>ms<</replace>>
    <<replace "#timer2">><<print $setinterval_time>>ms<</replace>>
    <<replace "#disc">><<print new Date() - $initial_time - $setinterval_time>>ms<</replace>>

What I've found is that if this passage is allowed to run for a large amount of time, the discrepancy between the setinterval clock and the actual clock grows bigger... and this only gets worse with user input (which i understand is due to javascript being single-threaded and that user input messes with that through force yielding).


So my two questions are: 

1. How do I incorporate the requestAnimationFrame() method as an alternative to <<repeat>> to "animate" my entire passage (or at least replace various elements within the passage)? Some examples of code would be nice. 

2. Will exporting my game as an .exe using nw.js make my game more "playable" lag-wise? Or will nw.js run into the same timing errors that setInterval has? 

P.S. I'm not a very good programmer, and my skills with javascript are still quite lacking, so I would prefer to code in Twinescript if at all possible ;_;

1 Answer

+1 vote
by (63.1k points)

Can you give us an example of what you need this timing for? It seems like you could utilize events and the time() function or similar methods to get user input and see how long it took, which would be far easier. 

As far as the specific questions: 

  1. As far as I know, you don't need to do anything special to use window.requestAnimationFrame() in SugarCube, but I've never used it, so I can't speak to that specifically. What specifically are you attempting to do and what's happening or not happening? 
  2. I doubt it. NW.js just wraps your game in a dedicated browser shell. For the most part, your game will behave exactly the same in this shell as it would in Chromium/Chrome. 
The issue with overusing repeat (and setInterval) is that the repeating code is blocking, that is, when your code runs every 100ms, nothing else happens until the code finishes, this includes blocking user input, which will make your game feel laggy and unresponsive. Generally, repeating stuff is not a good option for capturing and reacting to changes. What JavaScript does do really well is events though. 
If you want an example of how to implement your system using events, assuming its possible, we just need more to go on.