I am looking at the docs of Stopwatch and I'm sure that they don't have a method to start the stopwatch with the initial value.
I am developing an app that requires measuring the elapsed time. Therefore, Stopwatch becomes the obvious choice here. However, there is a use case, where the users of the app may accidentally close the app when clearing the background apps.
Since, running headless dart code in the background is kind of vague right now, I believe it is of best interest to keep track of time and the time gap, if there is any when resuming the app after an accidental close. A separate data object like the following could keep track of time and whether the stopwatch is running...
class StopwatchTracker{
final stopwatch;
final lastUpdated;
final isRunning;
final systemTime;
StopwatchTracker({this.stopwatch, this.lastUpdated, this.isRunning, this.systemTime});
}
With this I have an object that has data about the lastUpdated time from the stopwatch.
Compare this to the systemTime, which will be the device's current system time.
Now, we can see if there is a gap between the lastUpdated time and the systemTime. If there is a gap, the stopwatch should "leap" to the time, by "gap" units.
This StopwatchTracker object will only be initialized on app start/resume and every few seconds, it will update the lastUpdated time. I think the logic is there, but, as I mentioned, the Stopwatch class in dart, doesn't have a method to initialize it with a starting value.
I'm wondering whether I could extend the Stopwatch class to house a method to do that. Or a second option will be to update the ellapsedMillis itself or add the gap in mills to the ellapsedMillis and then show the result on the screen.
Will love to hear from you guys on this!
Yes I can! > Well yes, but actually no
I cannot set the starting value of the stopwatch to start/resume at a certain time or even readjust the current running time.
The easiest solution I have found is to extend the class Stopwatch like so:
class StopWatch extends Stopwatch{
int _starterMilliseconds = 0;
StopWatch();
get elapsedDuration{
return Duration(
microseconds:
this.elapsedMicroseconds + (this._starterMilliseconds * 1000)
);
}
get elapsedMillis{
return this.elapsedMilliseconds + this._starterMilliseconds;
}
set milliseconds(int timeInMilliseconds){
this._starterMilliseconds = timeInMilliseconds;
}
}
At present I don't require much more from this code. Just start the stopwatch at some point and then keep it running. And it can be easily extended for other get types of the class Stopwatch.
This is how I plan to use the class
void main() {
var stopwatch = new StopWatch(); //Creates a new StopWatch, not Stopwatch
stopwatch.start(); //start method, not overridden
stopwatch.milliseconds = 10000; //10 seconds have passed
print(stopwatch.elapsedDuration);//returns the recalculated duration
stopwatch.stop();
}
Want to play with the code, or test it out? Click here
Related
I have a simple project. A button adds points one at a time to a counter. I then change the scene via another button and return to the original scene. The point counter has gone back to zero. How do i prevent this?
Many ways to achieve this. But for starters you can save the number in Player Prefs.
"PlayerPrefs` is a class that stores Player preferences between game sessions. It can store string, float and integer values into the user’s platform registry"
So forexample this is your button callback function:
public void ButtonCallback()
{
number++;
PlayerPrefs.SetInt("MyNumber", number);
}
To get the number next time you are in the scene, you can get the number using:
int number = PlayerPrefs.GetInt("MyNumber");
You will probably need to check if number exists in the first place when you launch the scene first time using:
PlayerPrefs.HasKey("MyNumber");
Read up more on this on:
https://docs.unity3d.com/ScriptReference/PlayerPrefs.html
I need to do some calculations between every update(), so I need to ensure that a function is processed before the next frame.
Is there any way to achieve this? Just like "WaitForEndOfFrame" in Unity?
You can override the updateTree in your FlameGame (or in your Component, if you only want it to happen before the updates of a subtree) and do your calculations right before all the other components start updating. This would be right after the last frame, except for the first frame, but that one you can skip by setting a boolean.
So something like this:
class MyGame extends FlameGame {
bool isFirstTick = true;
#override
void updateTree(double dt) {
if(!isFirstTick) {
// Do your calculations
} else {
isFirstTick = false;
}
super.updateTree(dt);
}
}
But I have to ask, why do you need to do this? render won't be called until all the update calls are done, do can't you just put your calculations in the normal update method?
In Flutter we don't get an update() function unlike Unity. That is in the default API that we use, there are ways to tap into something of that effect. Normally we use a Ticker and create an animation to get periodic updates synced with screen refresh rate.
However, if what you are trying to do is to run something in between build() calls, WidgetsBinding.instance!.addPostFrameCallback() may be what you are looking for.
Here is a detailed answer that may help in this regard: https://stackoverflow.com/a/51273797/679553
I'm developing a video app, using video_player package. I want to repeat the videos n times. I'm doing this by adding listener and when video reaches the end, if the current repetition is not equal to the N, I simply call the _videoPlayerController.seekTo(Duration.zero), it works as expected in iOS, but in Android it takes some time to play it again, because of the buffer I guess. I have some logs. When I call the seekTo, first log is:
D/AudioTrack(26148): stop(59): called with 194560 frames delivered
After some time(3-4 seconds) the other logs come and video plays after these logs:
D/AudioTrack(26148): getTimestamp_l(60): device stall time corrected using current time 21442303047753
D/AudioTrack(26148): getTimestamp_l(60): stale timestamp time corrected, currentTimeNanos: 21440694441753 < limitNs: 21442169902753 < mStartNs: 21442230902753
W/AudioTrack(26148): getTimestamp_l(60): retrograde timestamp time corrected, 21442169902753 < 21442303047753
I'm not sure the problem in here is the buffering but if so, is there anyway to prevent buffering while using seekTo in android or is there any other way to achieve this functionality?
I'm thinking this problem come from the initial thread so if you call your first seek initial code in did dependencies method or you can try to wrap initial code to addpostframe call back with binding.
WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
_playController(index: 0, durationInSeconds: 5);
});
or try to call didChangeDepencies after the initState initialize.
#override
void didChangeDependencies() {
super.didChangeDependencies();
}
I am writing a game using CreateJS and using CocoonJS to distribute. Within CocoonJS API are a couple of listener functions that allow callbacks when pausing and resuming of the game. The game's timer and (time-based) animations are driven by the Ticker event's "delta" property. The issue that I am having at the moment is, on resuming the game following on from pausing it, the timer will pick up from the time at which it paused plus the time spent whilst paused. For example, I pause the game after 20 seconds for exactly 4 seconds, on resuming the game the timer will carry on from 24 seconds (not 20 seconds, which is intended). I've tried storing the ticker event's "runTime" property before pausing and attempting to then set the ticker event's "runTime" to this stored value on resume, but this doesn't work.
A snippet of my original code (before tinkering) is like the following:
createjs.Ticker.setFPS(60);
createjs.Ticker.on("tick", onTick, this);
Cocoon.App.on("activated", function() {
console.log("---[[[[[ APP RESUMING ]]]]]---");
createjs.Ticker.paused = false;
});
Cocoon.App.on("suspending", function() {
console.log("---[[[[[ APP PAUSING ]]]]]---");
createjs.Ticker.paused = true;
});
onTick = function (e) {
if (!e.paused) {
animateUsingTicker(e.deltaTime);
countDownTimerUsingTicker(e.deltaTime);
//etc...
stage.update();
}
};
Can someone please assist me on this?
Many thanks
One really easy way to deal with this is to use Timer.maxDelta. For example, if you are targeting 60fps, you could set this to something like 32ms (double the expected delta), to prevent getting huge values back when resuming an app/game.
I have been using mach_absolute_time() for all my timing functions so far. calculating how long between frames etc.
I now want to get the exact time touch input events happen using event.timestamp in the touch callbacks.
the problem is these two seem to use completely different timers. sure, you can get them both in seconds, but their origins are different and seemingly random...
is there any way to sync the two different timers?
or is there anyway to get access to the same timer that the touch input uses to generate that timestamp property? otherwise its next to useless.
Had some trouble with this myself. There isn't a lot of good documentation, so I went with experimentation. Here's what I was able to determine:
mach_absolute_time depends on the processor of the device. It returns ticks since the device was last rebooted (otherwise known as uptime). In order to get it in a human readable form, you have to modify it by the result from mach_timebase_info (a ratio), which will return billionth of seconds (or nanoseconds). To make this more usable I use a function like the one below:
#include <mach/mach_time.h>
int getUptimeInMilliseconds()
{
static const int64_t kOneMillion = 1000 * 1000;
static mach_timebase_info_data_t s_timebase_info;
if (s_timebase_info.denom == 0) {
(void) mach_timebase_info(&s_timebase_info);
}
// mach_absolute_time() returns billionth of seconds,
// so divide by one million to get milliseconds
return (int)((mach_absolute_time() * s_timebase_info.numer) / (kOneMillion * s_timebase_info.denom));
}
Get the initial difference between two i.e
what is returned by mach_absolute_time() initally when your application starts and also get the event.timestamp initially at the same time...
store the difference... it would remain same through out the time your application runs.. so you can use this time difference to convert one to another...
How about CFAbsoluteTimeGetCurrent?