I have made a simple timer but in trying to increase the timers speed over time, so I basically want the timer to have an interval of 1.0 and every 10 seconds I want that timer's interval to decrease by 0.1
How can I go about doing that?
[self schedule:#selector(tick:)interval:1.0];
That's in the init section
-(void)tick:(ccTime)dt{
myTime = myTime+1;
totalTime = myTime;
[timeLabel setString:[NSString stringWithFormat:#"%i", totalTime]];
}
That's the timer.
It's a basic timer which has an interval of 1.0 second, however I would like the interval to decrease by 10% every 10 seconds.
in .h file
#property(nonatomic,readWrite)CGFloat lastUpdatedInterval;
in.m file, initialize self.lastUpdatedInterval = 1.0;
then call
[self schedule:#selector(tick:)interval:self.lastUpdatedInterval];
in update loop,
-(void)tick:(ccTime)dt
{
if(myTime>9 && (myTime%10 == 0))
{
[self unschedule:#selector(tick:)];
self.lastUpdatedInterval = self.lastUpdatedInterval - (self.lastUpdatedInterval*0.1);
[self schedule:#selector(tick:)interval:self.lastUpdatedInterval];
}
myTime = myTime+1;
totalTime = myTime;
[timeLabel setString:[NSString stringWithFormat:#"%i", totalTime]];
}
Related
I am very new in Iphone Development. I have an issue . I am using a NSTimer which update a UiLabel in every second. now i have two problem :
when my app goes in background and after it when i open app . app goes hangs.
if i goes next or back on other ui screen then wen i comes on timer screen then my label again shows 0.
can anyone help me.
code which i am using :
timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:#selector(updateCountdown) userInfo:nil repeats: YES];
-(void) updateCountdown
{
secondsLeft--;
//nits testing
if(secondsLeft == 1)
{
[self.view addSubview:recipePage6View.view];
}
if (secondsLeft<0)
{
[timer invalidate];
timer=nil;
lblDisplayTimer.text =#"00:00:00";
}
else
{
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
lblDisplayTimer.text = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
//lblDisplayTimer.text = [NSString stringWithFormat:#"%02d:%02d",minutes,seconds];
}
}
You need to set up a special background timer task and not have an NSTimer on the main run loop which gets suspended in background. The documentation on how to do this is here
Currently I am developing a game which needs a stop watch say 1 minute,when user taps the play button it enters the game screen,I want the to run the stop watch count down of 1 minute 01:00,00:59,00:58 etc. For that reason I searched and found NSTimer would be the ideal choice to implement a stop watch.Hence I took a label,created an instance of NSTimer,assigned time interval and started decrementing the value in timer label,i.e.:
-(void)viewDidAppear:(BOOL)animated
{
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(viewWillAppear:) userInfo:nil repeats:YES];
[super viewDidAppear:YES];
}
-(void)viewWillAppear:(BOOL)animated
{
static int currentTime = 60;
int newTime = currentTime--;
int minutesRemaining = newTime / 60; // integer division, truncates fractional part
int secondsRemaining = newTime % 60; // modulo division
self.timerLabel.text = [NSString stringWithFormat:#"%02d:%02d", minutesRemaining, secondsRemaining];
if ([self.timerLabel.text isEqualToString:#"00:00"])
{
[stopWatchTimer invalidate];
}
[super viewWillAppear:YES];
}
The problem here is the timer starts running 01:00,00:59,00:58 and goes on,say at 53rd second,I navigated to another view and came back,it is running from 00:53,00:52 and so on,but I want it to run from 01:00 and for that I implemented invalidating NSTimer in viewDidDisappear i.e.
-(void)viewDidDisappear:(BOOL)animated
{
if ([stopWatchTimer isValid])
{
[stopWatchTimer invalidate];
self.stopWatchTimer = nil;
}
[super viewDidDisappear:YES];
}
Still the same issue exists!
Done lots of Research on the issue and found no answer useful and working.
Can some one please guide me,any help is appreciated.
Thanks every one in advance :)
You are use the selector viewWillAppear for the timer. viewWillAppear is a method on a viewController that gets called when the view appears on screen, you should not call it yourself. Instead, create your own method that decrements the timer:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateTime:) userInfo:nil repeats:YES];
currentTime = 60; // This could be an instance variable
self.timerLabel.text = #"01:00";
}
-(void)updateTime {
int newTime = currentTime--;
int minutesRemaining = newTime / 60; // integer division, truncates fractional part
int secondsRemaining = newTime % 60; // modulo division
self.timerLabel.text = [NSString stringWithFormat:#"%02d:%02d", minutesRemaining, secondsRemaining];
if ([self.timerLabel.text isEqualToString:#"00:00"])
{
[self.stopWatchTimer invalidate];
}
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if ([self.stopWatchTimer isValid])
{
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
}
}
With this technique the timer is responsible for calling every second, but you will probably have timing issues after some seconds. To have a more accurate timing, you should store the time that you started the countdown and then on every updateTime call, compare the current time with the stored started time.
Add to your interface:
#property (nonatomic) NSTimeInterval startTime;
then in the implementation:
-(void)viewDidAppear:(BOOL)animated
{
self.startTime = [NSDate timeIntervalSinceReferenceDate];
self.duration = 60; // How long the countdown should be
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:#selector(updateTime)
userInfo:nil
repeats:YES];
self.timerLabel.text = #"01:00"; // Make sure this represents the countdown time
}
-(void)updateTime {
int newTime = self.duration - (round([NSDate timeIntervalSinceReferenceDate] - self.startTime));
int minutesRemaining = newTime / 60; // integer division, truncates fractional part
int secondsRemaining = newTime % 60; // modulo division
self.timerLabel.text = [NSString stringWithFormat:#"%02d:%02d", minutesRemaining, secondsRemaining];
if (newTime < 1)
{
[self.stopWatchTimer invalidate];
/* Do more stuff here */
}
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if ([self.stopWatchTimer isValid])
{
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
}
}
Some extra (unrelated) comments on the code:
when implementing viewDidDisappear: pass the animated parameter to the call to super:
[super viewDidDisappear:animated];
when implementing viewDidAppear: pass the animated parameter to the call to super, also, make sure you call super first this in the method, before doing anything else
I am developing a QuiZ app. It needs a countdown timer, In that I want to start a timer at 75:00.00 (mm:ss.SS) and decrease it to 00:00.00 (mm:ss.SS) by reducing 1 millisecond. I want to display an alert that Time UP! when time reaches to 00:00.00 (mm:ss.SS).
I am displaying the time by following below link
Stopwatch using NSTimer incorrectly includes paused time in display
Here is a simple solutions to your problem.
Declarations
#interface ViewController : UIViewController
{
IBOutlet UILabel * result;
NSTimer * timer;
int currentTime;
}
- (void)populateLabelwithTime:(int)milliseconds;
-(IBAction)start;
-(IBAction)pause;
#end
Definition
- (void)viewDidLoad
{
[super viewDidLoad];
currentTime = 270000000; // Since 75 hours = 270000000 milli seconds
}
-(IBAction)start{
timer = [NSTimer scheduledTimerWithTimeInterval:.01 target:self selector:#selector(updateTimer:) userInfo:nil repeats:YES];
}
-(IBAction)pause{
[timer invalidate];
}
- (void)updateTimer:(NSTimer *)timer {
currentTime -= 10 ;
[self populateLabelwithTime:currentTime];
}
- (void)populateLabelwithTime:(int)milliseconds {
int seconds = milliseconds/1000;
int minutes = seconds / 60;
int hours = minutes / 60;
seconds -= minutes * 60;
minutes -= hours * 60;
NSString * result1 = [NSString stringWithFormat:#"%#%02dh:%02dm:%02ds:%02dms", (milliseconds<0?#"-":#""), hours, minutes, seconds,milliseconds%1000];
result.text = result1;
}
Use following code for reducing timer.
double dblRemainingTime=60; //1 minute
if(dblRemainingTime >0)
{
dblRemainingTime -= 1;
int hours,minutes, seconds;
hours = dblRemainingTime / 3600;
minutes = (dblRemainingTime - (hours*3600)) / 60;
seconds = fmod(dblRemainingTime, 60);
[lblRemainingTime setText:[NSString stringWithFormat:#"%02d:%02d",minutes, seconds]];
}
else
alert('Time up buddy');
I am working on a count down timer and am having trouble getting the if statement to stop the timer when the count is less that 0. Any guidance on solving this would be greatly appreciated. Thanks in advance for your help..
-(void) startCountdown{
time = 90;
//NSLog[#"Time Left %d Seconds", time];
//This timer will call the function updateInterface every 1 second
myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateInterface:) userInfo:nil repeats:YES];
}
-(void) updateInterface:(NSTimer*)theTimer{
if(time >= 0){
time --;
CountDownText.text = [NSString stringWithFormat:#"%d", time];
NSLog(#"Time Left %d Seconds", time);
}
else{
CountDownText.text =#"Times Up!";
NSLog(#"Times Up!");
// Timer gets killed and no longer calls updateInterface
[myTimer invalidate];
}
}
I tested your code and it worked perfectly and the timer stopped at -1. So my best guess is that time might be declared as unsigned value, so it never becomes less than zero.
Looks like your countdown won't stop until it gets to -1 (instead of 0) because you're checking for greater-than-or-equal to zero and then decrementing (and then displaying).
Either decrement first and then check if time is greater-than zero:
-(void) updateInterface:(NSTimer*)theTimer{
time --;
if(time > 0){
CountDownText.text = ...
or check if time is greater-than 1:
-(void) updateInterface:(NSTimer*)theTimer{
if(time > 1){
time --;
CountDownText.text = ...
I'm making a game on iPhone using cocos2d, and I have a question.
In my init method I'm doing this :
[self schedule:#selector(newMonster:) interval:1];
It create a new monster every second.
But I'd like that the interval change over time. For example :
The 10 first seconds of the game: a new monster appears every 1 second.
Then for 10 seconds: a new monster appears every 0.8 second.
And after every 0.5 second...
How can I do that?
Thanks !
You may try this- (I have copied some code from #bddckr)
Initial time:
self.monsterSpawnStartDate = [NSDate date];
self.lastTimeScheduledBefore = 0;//new var
Scheduled Method to create monster
- (void)scheduledMethod {
NSTimeInterval seconds = [[NSDate date] timeIntervalSinceDate:monsterSpawnStartDate];
[self newMonster]; // Let a new monster spawn
if (seconds >= 20.0 && lastTimeScheduledBefore == 10){
[self unschedule:#(scheduledMethod)];
[self unschedule:#(scheduledMethod) interval:0.5];
lastTimeScheduledBefore = 20;
}
else if (seconds >= 10.0 && lastTimeScheduledBefore == 0){
[self unschedule:#(scheduledMethod)];
[self unschedule:#(scheduledMethod) interval:0.8]
lastTimeScheduledBefore = 10;
}
}
You can modify it as your need. You can use mod if it goes through a cycle.
Make an instance variable and property of NSDate called monsterSpawnStartDate, make it an retaining property and synthesize it.
As soon as your first monster should be created, set it:
self.monsterSpawnStartDate = [NSDate date]; // Current date and time
And replace your code by this:
[self schedule:#selector(adjustMonsterSpawnRate) interval:0.1]; // Seems like you want it to fire every 0.1 seconds
Implement adjustMonsterSpawnRate like this:
- (void)adjustMonsterSpawnRate {
NSTimeInterval seconds = [[NSDate date] timeIntervalSinceDate:monsterSpawnStartDate];
if (((seconds <= 10.0) && (seconds % 1.0)) || ((seconds <= 20.0) && (seconds % 0.8)) ((seconds > 20.0) && (seconds % 0.5)))
[self newMonster]; // Let a new monster spawn
}
I think a better option would be to use a scheduled function for timing and use accumulated time to trigger the enemy creation as follows
self.time_since_last_monster = 0
[self schedule:#selector(new_monster:) interval:0.3];
-(void) new_monster:(ccTime)dt{
self.time_since_last_monster += dt;
if(self.time_since_last_monster > monster_interval){
self.time_since_last_monster -= monster_interval;
[self create_new_monster];
// at this point based on some condition, you can now change monster_interval
}
}
This would give more flexibility.
I'm pretty dumb, so here's what I'd do:
in the .h set a float
float nextMonsterIn;
then in the body
nextMonsterIn = 1.0;
[self scheduleOnce:#selector(newMonster:) interval:nextMonsterIn];
[self schedule:#selector(kickUpDifficulty:) interval:10];
- (void) newMonster : (ccTime) dt
{
[self scheduleOnce:#selector(newMonster:) interval:nextMonsterIn];
//-----make a monster-----
}
- (void) kickUpDifficulty : (ccTime) dt
{
if(nextMonsterIn == 1.0)
nextMonsterIn = 0.8;
else if(nextMonsterIn == 0.8)
{
nextMonsterIn = 0.5;
[self unschedule:#selector(kickUpDifficulty:)];
}
}
Basically every time I call newMonster i'd recursively re-schedule the newMonster based on my current delay, then I can adjust the delay in a timer or every time a monster is killed or wherever.