QTimer setInterval without resetting remainingTime
Asked Answered
M

1

8

I have an app written in QT that uses QTimer. It's basically a game and all the actions are controlled by the timer. Game includes the ability to increase\decrease the game speed. The code for increasing the speed is

    timerValue -= speedUpValue;
    if (timerValue < maxSpeed) {
        timerValue = maxSpeed;
    }
    timer -> setInterval(timerValue); 

speedUpValueand maxSpeed are constants. Almost the same code is used for decreasing the speed. The problem is that setInterval resets the internal timer and therefore if you keep rapidly increasing or decreasing the speed game eventually never proceeds because remainingTime is constantly being reset. Is there a way to set remainingTime manually or change the interval without resetting it?

Maybellemayberry answered 3/10, 2015 at 0:54 Comment(1)
No, there is no way to change the interval without the timer restarting automatically. However, you can likely achieve a similar effect by only updating the interval when the timer times out.Ethiopian
F
4

You can omit the timer object altogether, and instead use the static method QTimer::singleShot(...), and set a new single shot on every timer event with the timerValue. So no matter how frequently timerValue is modified, each timer cycle will be completed with the old value and scheduled with the current value.

As RA mentioned, you can effectively achieve the same thing keeping the timer object, but moving the setInterval() to the timer event, basically the same thing as above, but keeping the timer object, if you need it for some reason.

As Craig mentioned in the comments, the first approach will also ensure timer events don't get accumulated, in case your game logic takes longer. Also, if you go for an asynchronous design, it is possible that the next game cycle will begin execution before the old one is completed if you go for a continuously running timer.

It this regard, it is best to not use a continuously running timer, but schedule each next game cycle manually, and only if you need to. For example, you may not need to schedule another if the game comes to an end. Also, this will allow for finer control over how accurate the game speed goes, after the game cycle execution is completed, you can calculate how much time remains until the next one is needed, and schedule it with that value, or if the execution took too long, you can schedule it immediately.

Feigned answered 3/10, 2015 at 7:30 Comment(4)
A further advantage to using a single-shot each time is that then events don't accumulate. If you use QTimer and cannot consume its signals as fast as they are generated, they bank up. Single shots cannot accumulate like this because you only initiate the next one when handling the current one. The main downside is less accuracy/regularity of interval.Virginiavirginie
@CraigScott: I know this is all old news, but it's the best information I can find at the moment. This answer seems to suggest that periodic QTimer events don't accumulate anyway. More like a check at the end of the event loop to see if the prescribed time has elapsed yet. If it has, even grossly, it fires one event and resets the timer. Which is right?Cogitative
@Cogitative It's been a long time since I made the above comment but I think it was based on actual behaviour I had seen rather than being hypothetical. Too long ago for me to remember the details, so you'd have to do your own tests to verify the behaviour with latest Qt.Virginiavirginie
Also consider that the slot connected to the timer signal might be a queued connection, so the accumulation might not be with the timer itself but rather in the queue of deferred slot invocations.Virginiavirginie

© 2022 - 2024 — McMap. All rights reserved.