Inside my scene, I have overridden the default -(void) update: (CFTimeInterval) currentTime function. It is worth noting that the currentTime variable is actually the elapsed time since the beginning of a presumably arbitrary system time, as opposed to the elapsed time since last frame. This update function runs through all of my characters and applies their movement based on velocity per second and elapsed time since last update in seconds. The usual way to get the elapsed time since last update in seconds is to have an NSTimeInterval in your class that stores the last update, and subtract the last update time from the current update time, getting elapsed seconds. However, the initial elapsed time is NOT zero. As such, subtracting zero from a very large number produces a perceived elapsed time of many tens of thousands of seconds. As such, any characters already in motion on the very first frame will have moved very far away.
The obvious solution to this would be to initially set the last update time to the initial time elapsed. However, I do not see any method to access this within SKScene, or more specifically within -(void) didMoveToView: (SKView *) view.
Another solution would be to set the initial CFTimeInterval to a negative number, such as -1. Then, one would check each update function whether the time is -1. If so, one would set the elapsed time since last update to 0, otherwise one would do the ordinary elapsedTime = currentTime - lastUpdate. However, doing this if statement every single update function seems messy and unneeded.
Are there any other ways of finding this elapsed time since last update accurately?
You're right that checking for a flag every iteration is wasteful, so it's a question of what's the most efficient solution.
I would think the best (read: most efficient) solution would be to not apply any changes in the first update besides simply saving the currentTime variable. This shouldn't affect your gameplay at all; nobody will notice the frame has been dropped. You could do it by saving a pointer to a function, calling that function in the first iteration of update which will also change the pointer to another function, and then update will call the second function from that point onward.
The method I think you're looking for is CFAbsoluteTimeGetCurrent, but SK's update method tends to hand back a different, earlier time, likely due to the amount of time taken to pass the time into update versus just using CFAbsoluteTimeGetCurrent. If you're OK with a little extra overhead without using an if, disregard currentTime and always use CFAbsoluteTimeGetCurrent in your update method.
Then again, if you're worried about the overhead of a single if statement in each frame, you wouldn't be using a framework. 60 ifs per second is trivial work for even the slowest mobile processor anyway.
I think I understand.. but I may not. So correct me if I'm wrong. But your problem is that your initial delta time is very large, and so using that value to move characters results in them jumping immediately on the first frame of your game. If thats the case, then youre missing a crucial piece of the code in update.
if self.last_update_time == 0.0 { // this is the important part
self.delta = 0
} else {
self.delta = currentTime - self.last_update_time
}
self.last_update_time = currentTime
last_update_time time will always be 0 when your game starts, and delta will always be 0 too. After that point, your delta value will be very small numbers which you can use to progressively move your sprites.
hopefully this was helpful
Related
I am new using kotlin and I am wondering if I can do the following...
I wanna call a method on the first of each month, I found this and saw a couple of examples like this:
timer.schedule(1000) {
println("hello world!")
}
I am wondering if is possible to use (instead of a fixed time) a calendar day? like first of the month?
There's no built-in way to do this.
If the exact time of day doesn't matter*, then one approach is to schedule a task to fire every 24 hours, and have it check whether the current time is the first day of the month, and if so, perform the task.
(* It will drift slightly when summer time starts or ends, or leap-seconds get added, but that may not be significant.)
A more powerful (but more complex approach) is to set the timer to go off once, at the appropriate time on the 1st of next month. Then, after performing the task, it could re-schedule itself for the 1st of the following month. (You'd need to take care that it always did so, even if the task threw an exception.)
You could put all this into a timer class of your own, to separate it from the business logic you want to run.
For examples in Java (which will translate directly to Kotlin/JVM), see the answers to these questions.
I'm implementing negamax with alpha/beta transposition table based on the pseudo code here, with roughly this algorithm:
NegaMax():
1. Transposition Table lookup
2. Loop through moves
2a. **Bail if I'm out of time**
2b. Make move, call -NegaMax, undo move
2c. Update bestvalue, alpha/beta but if appropriate
3. Transposition table store/update
4. Return bestvalue
I'm also using iterative deepening, calling NegaMax with progressively higher depths.
My question is: when I determine I've run out of time (2a. in the beginning of move loop) what is the right thing to do? Do I bail immediately (not updating the transposition table) or do I just break the loop (saving whatever partial work I've done)?
Currently, I return null at that point, signifying that the search was canceled before "completing" that node (whether by trying every move or the alpha/beta cut). The null gets propagated up and up the stack, and each node on the way up bails by return, so step 3 never runs.
Essentially, I only store values in the TT if the node "completed". The scenario I keep seeing with the iterative deepening:
I get through depths 1-5 really quick, so the TT has a depth = 5, type = Exact entry.
The depth = 6 search is taking a long time, so I bail.
I ultimately return the best move in the transposition table, which is the move I found during the depth = 5 search. The problem is, if I start a new depth = 6 search, it feels like I'm starting it from scratch. However, if I save whatever partial results I found, I worry that I'll have corrupted my TT, potentially by overwriting the completed depth = 5 entry with an incomplete depth = 6 entry.
If the search wasn't completed, the score is inaccurate and should likely not be added to the TT. If you have a best move from the previous ply and it is still best and the score hasn't dropped significantly, you might play that.
On the other hand, if at depth 6 you discover that the opponent has a mate in 3 (oops!) or could win your queen, you might have to spend even more time to try to resolve that.
That would leave you with less time for the remaining moves (if any...), but it might be better to be slightly short on time than to get mated with plenty of time remaining. :-)
I have a certain amount of elements, and each of these elements represents one day. Each time midnight occurs (i.e. >>>user<<< time = 00:00), I want the "current" element in the list to expire (and the next one will take its place). Now this seems easy and all, but when you start scratching the surface it's a mess (at least according to me). The problems begin with time zones. If midnight occurs, and after this I change my time zone to one where this particular midnight has not occured yet, then when it does occur "again" in the new time zone, I do not want to count it again (the expired element should remain expired while the element that took its place should count as the current one). Also, when the app is suspended/shut down for a couple of days, I want it to update itself based on the number of valid midnights that occured since last use (as I see it, this makes using UIApplicationSignificantTimeChangeNotification pointless, as it is only sent for the most recent passed midnight).
Ideally, I would like these elements to be totally unaware of dates and time; they should simply be a list 0,1,2,3,... together with a "current element" pointer (i.e. a simple integer), which will be increased for each valid midnight occurence.
How would you suggest that I should implement this?
Base it on UTC midnight, so that no matter what time zone you're in, you're unaffected by the local time change. It eliminates the time zone issue altogether.
I'm relatively new to coding, and wondering if there's a conventional way to have some code execute on every nth iteration of a loop (in this case, an NSTimer ticking).
I'm using a CADisplayLink and it updates however many times per second, 40, 50, whatever. If I want to execute some code on every, say, 500 of those loops, is there a standard way to do so? I assume I could put something together with the modulo operator and an integer, but is there a better / more normalized way that a new coder should know?
Extra clarity (though I'm sure this is a fairly common thing to do..): I have a timer that ticks 60 times per second, but I only want to do something with every 10th iteration. I already know that I can use a modulo and an integer to do this, but I want to know if there's any other convention for handling a situation like this.
Thanks in advance!
Establish a dedicated timer for the right interval.
Regardless of whether you're using NSTimer or CADisplayLink, timer calls can be coalesced and offset if they take too long. If you have a display link that takes 20 frames to run, it only gets called thrice every second (given the refresh interval is 60 frames per second). And if you have a timer set to run every second that at one instance takes a bit more than two and a half seconds to run, it will have "ate" its next iteration and will run the next iteration half a second too late.
Because of this, your timer can get out of sync if you only count timer calls. To do something repeatedly on an interval, having a timer set to that interval is the absolute best approximation.
Having a second timer like this is not a performance problem unless you do very many timers, in which case you should standardize on one tick timer and have events scheduled for specific points in time (which still isn't the same as counting previous iterations).
Although I'm coding in Objective C, this is more of a general programming question.
What is the best way to convert a constantly changing scalar value to a changing interval or frequency?
Right now every time the scalar value changes I am destroying the NSInterval
ie
[self.myTimer invalidate];
self.myTimer = nil;
and creating a new one, but this seems like a VERY expensive way to achieve my goal, since the changing scalar value in my case represents the horizontal velocity of a swipe.
For a rough analogy, think of the speed of a swipe being reflected in a visual metronome, the faster you swipe, the higher(shorter interval) the frequency of the metronome.
First, understand that this is a "measurement" problem. To solve this problem, isolate the minimum attributes needed to solve the problem and derive the rest.
The distance moved and the time taken to move the distance are derived attributes of each measurement, in this case the measurement is named "swipe". In a racing analogy, the measurement is called a lap.
The "speed" can now be calculated. This will be the "velocity", which is simply distance/time.
The distance can be calculated given the start and end points of the swipe.
To obtain the time value, create an startTime instance of NSDate in touchesBegan:withEvents: and in touchesEnded:withEvents: calculate elapsedTimeInterval using [startTime timeIntervalSinceNow];
Depending on your needs, you may need a Measurement class with properties for startPosition, endPosition, startTime and endTime so you can keep track of "fastest" speed etc.
Take a look at Analysis Patterns by Martin Fowler. I find it very useful when trying to map domain problems to software solutions.