I am doing a simple stop clock like game.
The game consists of a timer for 60 secs
I attain it by
AtlasSpriteManager *mgr = [AtlasSpriteManager spriteManagerWithFile:#"bringit_timer.png" capacity:10];
[self addChild:mgr z:5 tag:2];
AtlasSprite *sprite = [AtlasSprite spriteWithRect:CGRectMake(0,0,33,200) spriteManager:mgr];
[mgr addChild:sprite];
sprite.position = ccp(160,240);
sprite.scale = 1.0;
[sprite runAction:[RotateBy actionWithDuration:60 angle:360]];
After that i need to add effects by scaling up the clock for every 10sec.
I can get the effect by
[Circle runAction:[ScaleTo actionWithDuration:2 scale:1.3]];
but dont know how to find 10th second.
Can anyone tell me how to find the value of the timer in the 10th second with some sample code.
Why don't you have a timer fire every 10 seconds as opposed to every 60 seconds? You can have a flag/counter/etc. to count when 60 seconds have passed and then reset to watch for the next 60 seconds.
Related
I have a requirement where I am displaying a media library video (AVAsset) using AVPlayer and updating the current frame in the video using a custom slider in the UI.
However, what I am looking for is how to tie the slider with the video without actually trimming the video.
I want to show a fraction of video attached to the slider i.e. say I have a video of duration 10 secs. I want the slider to be attached to 3-6 secs, which means if the slider is at start it should show the frame at 3.0 secs in the video and if the slider is at end it should show the frame at 6th sec in the video.
Simply put, to the user it should appear as the video is only of total duration 3 secs.
P.S. There is a lot in the above question, but I've tried my best to simplify my query.
1) Seek to start position:
int32_t preferredTimeScale = 600;
CMTime inTime = CMTimeMakeWithSeconds(self.startTime, preferredTimeScale);
[mainPlayer seekToTime:inTime];
2) Set a timer:
_EndOFRegionCheckTimer = [NSTimer scheduledTimerWithTimeInterval:0.10f
target:self
selector:#selector(_checkEndPassedFired)
userInfo:nil
repeats:YES];
3) In timer fire event check current position and stop playing if necessary:
- (void)_checkEndPassedFired {
AVPlayerItem *currentItem = mainPlayer.currentItem;
if ((double)currentItem.currentTime.value/currentItem.currentTime.timescale>self.stopTime)
{
[mainPlayer pause];
}
}
I have 5 audio channels being operated by five AVAudioPlayer objects, and I would like to add a very small delay to each of these channels, so that when I push a button, I get this:
Start sound 1 (which lasts 10 seconds)
Start sound 2 0.25 seconds after sound 1
Start sound 3 0.25 seconds after sound 2
Start sound 4 0.25 seconds after sound 3
Start sound 5 0.25 seconds after sound 3
I tired to do this just using sleep(0.25) between each calling of [AVAudioPlayerObeject play] like this:
[audioPlayer1 play];
sleep(delay);
[audioPlayer2 play];
sleep(delay);
[audioPlayer3 play];
sleep(delay);
[audioPlayer4 play];
sleep(delay);
[audioPlayer5 play];
...where delay is a float variable set to 0.25. However, this doesn't work, and I hear all 5 sounds at once. I tried experimenting with NSTimer, but I didn't really understand how to make a separate method for the delay, and then call the method with my code.
Can someone please help me revise my code to get the desired effect? Thanks!
Keep state with an integer that identifies which sound to start...
#property(assign, nonatomic) NSInteger startSound;
Schedule a timer...
self.startSound = 0;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
When the timer fires, start a new sound. Quit after you've started 5....
- (void)timerFired:(NSTimer *)timer {
if (self.startSound < 5) {
// assume you know how to play sound N, numbered 0..4
[self playSound:self.startSound++];
} else {
[timer invalidate];
}
}
You can make the timer interval and the max count of sounds variables in this class.
I wish to create a countdown timer in my app in such a way that I can give a certain duration (like 15 minutes or 15:00) and it starts on an action.
I also need for that countdown timer to take elapsed time duration and total time duration information from an external web service and start the countdown for the remaining time.
This is actually for a quiz application where the user will be presented with a series of questions and the timer will be placed on the question screen (for the whole quiz and not for only one question). The user can set the duration for the quiz and the countdown timer will begin as soon as the user start taking the quiz. There is also a pause functionality where user can pause the test and the information of time elapsed and total time duration will be registered in a web-service. The user can resume the quiz anytime with the countdown timer starting right from the time it was paused (taking this information from the web-service, that is).
Thanks in advance.
PS: To be honest, I had no idea on how to go about it. There was too much of confusion on what format will the time be stored over in the web-service and a lot of other stuff like if the program will go forward after the NSTimer is running in a loop etc. So you know what I mean. Yes, NSTimer does solve the problem as Alex told and provided with a sample code as well.
Look at the docs for NSTimer.
Generally, you would create an NSTimer which calls a method every second, like so:
NSTimer *theTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(tick) userInfo:nil repeats:YES];
Then in tick, you would decrement a variable holding the time remaining, and update a label on the display.
Also, if you want some working sample code, check out my little countdown app on GitHub.
Try these codes, I have already implemented it in my App. Best for resend OTP type functionalities.
int secondsLeft;
int hours, minutes, seconds;
secondsLeft = 60;
[self countdownTimer];
-(void)countdownTimer {
// secondsLeft = hours = minutes = seconds = 0;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
}
- (void)updateCounter:(NSTimer *)theTimer {
if(secondsLeft > 0 ) {
secondsLeft -- ;
hours = secondsLeft / 3600;
minutes = (secondsLeft % 3600) / 60;
seconds = (secondsLeft %3600) % 60;
labelSeconds.text = [NSString stringWithFormat:#"%02d seconds left.",seconds];
} else {
[timer invalidate];
return;
}
}
Im trying to create a NSThread game loop, i have some of the time been able to get a successful 57 FPS.
Some of the time my fps goes up to some ridiculice number.
I dont understand how its happening.
I check how long since the last loop and if it was to quick, sleep the thread for that much time.
This is not always happening, it sometimes escapes the if check on the speed and does the loop way to fast.
Any comments would mean alot.
Also where am i suposed to 'Tick' ?
- (void)gameLoop{
//gameIsRunning is set to TRUE in viewDidLoad
while (gameIsRunnning){
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Get Current date
NSDate *curTime = [NSDate date];
//Time since last loop and vurrent date;
NSTimeInterval timePassed_ms = [curTime timeIntervalSinceDate:old_date];// * 1000.0;
NSLog(#"***************");
//Cout the time interval
NSLog(#"Loop Time %f",timePassed_ms);
//Check if the loop was to fast and sleep for long enough to make up for about 60 FPS
if (timePassed_ms < 1.0/60) {
double timeToSleep = timePassed_ms - (1.0/60);
timeToSleep = timeToSleep*-1;
NSLog(#"Sleep For %f",timeToSleep);
[NSThread sleepForTimeInterval:timeToSleep];
}
//This new date is to try and check if after waiting the loop is taking the correct duration
NSDate *newDate = [NSDate date];
NSTimeInterval timePassed_after = [newDate timeIntervalSinceDate:curTime];// * 1000.0;
//Make an fps out of this new time interval after wait
double FPS = (1.0/timePassed_after);
NSLog(#"FPS %f",FPS);
NSLog(#"Adjusted Time %f",timePassed_after);
NSLog(#"***************");
//Reset olddate for next loop
old_date = curTime;
//Apparently this will capture touches and button events
while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002, TRUE) == kCFRunLoopRunHandledSource);
//A test on moving a ball to see how smooth it will be
[self performSelectorOnMainThread:#selector(moveBall) withObject:nil waitUntilDone:NO];
[pool drain];
}
}
You shouldn't rely on sleeping a thread because you can never be sure it will take the same amount of time.
So instead of making a thread sleep, do nothing with it, nothing at all (except of course with incrementing your fixed time step)
You will find you will have a much smoother Frame Rate then.
Also as a side note, don't use FPS as a performance indicator. Use the amount of time a single update has taken to be completed.
If you are aiming # 60fps, your goal processing time should be 0.01666* seconds. In reality you should be able to increase your processing time to 0.02555* which is 40fps and there should be no noticable performance hit on the game
EDIT: I also noticed you are creating a new pool and draining everytime the update is hit, in my experiences the autorelease pools should be placed at higher levels such appDelegate. But I wouldn't take it any lower then the level creation(create)/release(drain), moving this further up will help with performance as well.
I recommend switching to CADisplayLink API (docs). It creates a timer that automatically fires as often as the display refreshes, without you having to figure out how long to sleep. This will solve the problem about delivering "refresh" events to your code, but it will not solve all your problems.
Obviously, if your code can't finish in 1/60 seconds then you will not get 60 fps. Make sure your game logic and physics is not tied to the video refresh rate. Some people disagree whether CADisplayLink is the right thing to do. However, the agreed alternative is to update as fast as the hardware permits.
Last year, I switched a rendering loop in a toy game I had to use a display link (Mac, not iOS). I noticed a significant improvement in how "smooth" the game felt. Your results may vary.
Here is one way to do it (semi-pseudocode, simplified):
- (void)update:(CADisplayLink *)link {
now = gettime();
while (gametime < now) {
// Physics always updated at rate of 1/delta
advanceframe();
gametime += delta;
}
draw();
}
- (void) gameLoop
{
NSAutoreleasePool* loopPool = [NSAutoreleasePool new];
int loopCnt = 0;
while ( isRunning ) {
while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002f, TRUE) == kCFRunLoopRunHandledSource);
[self draw];
select(0, 0, 0, 0, &tm);
if ( loopCnt > 20000 ) { // 20000
loopCnt = 0;
[loopPool release];
loopPool = [NSAutoreleasePool new];
}
++loopCnt;
while(CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.002f, TRUE) == kCFRunLoopRunHandledSource);
}
[loopPool release];
}
timeIntervalSinceDate: returns the interval in seconds, not milliseconds.
(I wanted to write this in a little comment, not in a real answer, but couldn't figure out how to do this...)
I have a UILabel with a value of 0, and an int with a value of 300. How do I use NSTimer to have the UILabel go from 0 to 300 in 2 seconds? I want it to look like it's being added up incrementally.
Thanks in advance!
Actually NSTimer precision is about 50-100 milliseconds so it can't be so smooth as you want. But you can schedule timer for 0.05 and measure how much time had really passed from the beginning. After use
value = timePassedInSeconds*300/2;
NSString* label = [NSString stringWithFormat:#"%d", value];
if this won't be smooth enough try to use display link instead of NSTimer.
What are you trying to do? Are you trying to show some sort of point/score animation? You can do what you want if you do the math and fire off the timer at the interval you want, but I doubt you'll get what you want. You might want to look at UIImageView and feed it an array of images to animate or do the animations yourself with by painting.
I figured out a different solution:
I knew I wanted the "count up" to last 3 seconds... which is 60*0.05... basically the timer is hitting the method 60 times to get to the total amount.
addUpAb = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(addUpTimer) userInfo:nil repeats:YES];
-(void)addUpTimer {
int addNo = abTOT / 60;
abInt += addNo;
abductionCount.text = [NSString stringWithFormat:#"%d", abInt];
if(abInt >= abTOT) {
[addUpAb invalidate];
abCount.text = [NSString stringWithFormat:#"%d", abTOT];
}
}