shannoga
shannoga

Reputation: 19869

Set timer loop for a fixed time

I am creating a game. When the user finished the game I am showing him the score. To make it interactive I am counting the score from 0 to the score.

Now since the user can earn 10 points or 100,000 I don't want hime to wait to long so I want that the total time will be fixed no matter what is the score.

So I did that but it seems that the timer interval is not influenced by the interval value.

Where is the problem ?

///score timer
-(void)startScoreCountTimer:(NSNumber*)score{

finishedGameFinalScore = [score integerValue];
CGFloat finishedGameFinalScoreAsFloat = [score floatValue];
CGFloat interval = 2.0f/finishedGameFinalScoreAsFloat;
NSLog(@"interval = %f",interval);

NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
timer = [[NSTimer alloc] initWithFireDate:fireDate
                                 interval:interval
                                   target:self
                                 selector:@selector(timerMethod:)
                                 userInfo:nil
                                  repeats:YES];

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:timer forMode:NSDefaultRunLoopMode];
}

- (void)timerMethod:(NSTimer*)theTimer{

scoreCount++;
finalScoreLabel.text = [NSString stringWithFormat:@"%i",scoreCount];

   if (scoreCount == finishedGameFinalScore ||finishedGameFinalScore ==0) {
    [theTimer invalidate];
    scoreCount=0;
    [self updateMedalsBoard];
   }
}

Upvotes: 0

Views: 2713

Answers (2)

WhoaItsAFactorial
WhoaItsAFactorial

Reputation: 3558

I would use a repeating NSTimer instead of a runloop.

aTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timerMethod:) userInfo:nil repeats:NO]; 

And change your timerMethod to something more like the following:

- (void)timerMethod:(NSTimer*)theTimer{  
     scoreCount = scoreCount + (finishedGameFinalScore * (numberOfSecondsYouWantToRun/100));
     finalScoreLabel.text = [NSString stringWithFormat:@"%i",scoreCount];
     if (scoreCount == finishedGameFinalScore ||finishedGameFinalScore ==0) {
         [theTimer invalidate];
         scoreCount=0;
         [self updateMedalsBoard];
     } else {
         theTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(timerMethod:) userInfo:nil repeats:NO];
     }
} 

This will make it so that scoreCount will increment by a non-fixed number, based on their total score. So if you wanted the score counter to run for 2 seconds and your player scored 100, it would incriment by 2 points every tenth of a second. Where if your player scored 100,000 points the score would incriment by 2000 every tenth of a second.

Upvotes: 3

Husker Jeff
Husker Jeff

Reputation: 857

NSTimers aren't guaranteed to fire exactly every X seconds (or milliseconds, or in your case, microseconds). You can only know for sure that they'll fire sometime after X seconds (etc.) have passed. In your case, it looks like you're incrementing the score just one point at a time, and that takes up time on the main thread before the NSTimer has an opportunity to fire again, which slows down the whole process.

A better approach might be to simply have the timer repeat every, say, 0.1 seconds for 2 seconds. In each invocation of timerMethod:, add 1/20th of the total score until you reach the final total in the last iteration. You can, of course play around with the exact intervals to find something that looks good.

Upvotes: 2

Related Questions