Saturday, February 10, 2018

java - Using System Time to compute delay times that correctly deal with app pauses?


In my Android app I have the requirement to introduce small (for slowing down animation) and larger delays (for the purpose of delaying the appearance of a character for example).


I've experimented with 2 different ways, those being:


long grabTime;
int delayInMillis;

public void doStuff(){

//Initialise timeGrab variable
if (grabTime==0)

grabTime = System.currentTimeMillis();

//Has the desired number of Milliseconds passed?
if (System.currentTimeMillis()>timeGrab+delayInMillis)

//If so, then do something here

//And re-grab the time ready for the next time
grabTime = System.currentTimeMillis();


}

Where I have a batch of sprites (where each one will have a different delay) I find it easier to do this


long grabTime;
int spritesDelay = new int[numberOfSprites];
int forLoopCounter;

//Populate the array with desired delays (in seconds)
spritesDealay[0]=1;
spritesDealay[1]=2;

spritesDealay[2]=3;
spritesDealay[3]=4;


public void doStuff(){

//Initialise timeGrab variable
if (grabTime==0)
grabTime = System.currentTimeMillis();


//Has 1 second second passed?
if (System.currentTimeMillis()>(timeGrab+1000)){

//If so, reduce delay counters by 1

for (forLoopCounter = 0;forLoopCounter
spritesDelay[forLoopCounter]--;
}


//And re-grab the time ready for the next 1 second count
grabTime = System.currentTimeMillis();
}

//Now run through all the sprites and check to see if any of the timers have expired

for (forLoopCounter = 0;forLoopCounter
if (spriteDelay[forLoopCounter]<=0){


//Do stuff here

//If action has completed then reset the delay

if (*Some criteria has been met*){

spriteDelay[forLoopCounter]=4; //put in either explicit value for all sprites or restore previously backed up spriteDelay array (Not shown here)


}


}


}
}

In my app (a game) - I am using the second method to have some sprites moving in an up/down motion, each successive one with a slight delay on the previous one (think of a wave like motion).


The problem


This does work, however, when I pause my game (which simply halts game updates and continues rendering with a 'paused' graphic over the screen), on resuming play, things are out of sync slightly (because obviously the system time doesn't stop when the game is paused, so the first check after un-pausing to see if the second has elapsed will always be true providing the game was paused for longer than 1 second).



After the sprites have all moved through one motion, then they do sync up again and everything is OK.


However I'm not happy with the remainder of the current cycle being out of sync.


Alternatives?


Another way I've thought of doing this is hold an int that counts up each time my game update method is run (my game is 'limited' to 60 logic updates per second), then when it reaches 60, I would know a second has passed. This has the advantage that the counting will stop when the game is paused.


However, if the game were ever to be run on a device that couldn't handle 60 logic updates per second then it would slow down counting and throw everything off. (My ticks per seconds are separated from my rendering per second which runs flat out so although the FPS may drop, the logic updates per second should carry on at 60. I find it unlikely that a device wouldn't be able to handle 60 game updates per second (as I've tested this on a Galaxy Ace version 1 and that was fine at 60) but I'd like my app to be as robust as possible and don't really want to risk the timings being thrown off by a slow device however unlikely.


So I'm a bit stuck. Is there another system timer I can use which can be controlled? (switched off when required) or would my 'logic-updates-per-second' method be the best bet?




No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...