Resolved countdown timer

Discussion in 'iOS Programming' started by MrFusion, Jan 23, 2014.

  1. MrFusion, Jan 23, 2014
    Last edited: Jan 23, 2014

    MrFusion macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #1
    Hi

    Having just "discovered" sprite kit, I am trying to make a game which has a countdown timer. But my on screen timer is jittering.

    The timer itself works fine. A display string is created with the function below. This string is then displayed with a SKLabelNode. But the size of the SKLabelNode varies with 1 pixel. It's enough to cause jittering of the text for large font sizes. It's distracting and draws unwanted attention.

    SKLabelNode doesn't have an anchor point, otherwise it would probably be an easy fix.
    I tried fixing the position in the SKScene update: and didEvaluateActions: function, but that didn't work.
    What more can I try to fix this?

    Code:
    -(NSString *) formattedTimeInterval:(NSTimeInterval) timeInterval
    {
    	NSInteger timeInteger = (NSInteger)(timeInterval*100); //require resolution of 0.01s
    	NSInteger ms	= timeInteger % 100; // ms remainder
    	NSInteger s		= (timeInteger / 100) % 60; // s remainder
    	NSInteger min	= (timeInteger / 6000) % 60; //min remainder
    	NSInteger hours = (timeInteger / 360000); //hours
    
    	NSString *string = [NSString stringWithFormat:@"%@:%@:%@.%@",
    						[_formatter stringFromNumber:@(hours)],
    						[_formatter stringFromNumber:@(min)],
    						[_formatter stringFromNumber:@(s)],
    						[_formatter stringFromNumber:@(ms)]];
    
    	return string;
    }
    
    The number formatter has these properties:
    Code:
    //setup number formatter
    		_formatter = [[NSNumberFormatter alloc] init];
    		[_formatter setNumberStyle:NSNumberFormatterDecimalStyle];
    		[_formatter setMinimumFractionDigits:0];
    		[_formatter setMaximumFractionDigits:0];
    		[_formatter setFormatWidth:2];
    		[_formatter setPaddingCharacter:@"0"];
    		
    
    Code:
    -(void) didEvaluateActions
    {
    	SKLabelNode *countdownNode = (SKLabelNode *)[self childNodeWithName:kCountdown];
    	CGSize size = [countdownNode frame].size;
    	
    	if (size.width == 237) //236
    	{
    		CGRect frame = [self frame];
    		[countdownNode setPosition:CGPointMake(frame.size.width/2+0.5, //-0.5
    											   frame.size.height - size.height - kPadding)];
    	}
    	
    }
    
     
  2. dominsbeard macrumors newbie

    Joined:
    Oct 8, 2013
    #2
    It might depend on the text alignment in the label. For example if it is center aligned 3:20 will be slightly to the left of 3:19 (the 1 is smaller than 2).


    Also you could instead use this:

    Code:
    NSString *string = [NSString stringWithFormat:@"%02d:%02d:%02d.%03d", hours, min,s,ms];
    
     
  3. MrFusion thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #3
    Yes! This works. Thanks!

    Code:
    [countDownNode setHorizontalAlignmentMode:SKLabelHorizontalAlignmentModeLeft]; 
    
     
  4. pramgurusinga macrumors newbie

    Joined:
    Jan 27, 2014
    #4
    I'm trying to find a solution on my school project to implement the countdown timer in the sprite kit, but my problem is each time the label gets updated the labels are generated on top of previous label.

    could you please explain how to implement your code?
     
  5. MrFusion thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #5
    Create a SKScene with a SKLabelNode. Give the label a name. In the update function of your SKScene, update the content of the SKLabelNode with the setText function. Don't generate a new label each time.

    Otherwise post your code and we can provide feedback on how to improve it.
     
  6. pramgurusinga macrumors newbie

    Joined:
    Jan 27, 2014
    #6
    This is the NEW code. The problem also I'm having with this is, the timer doesnt show in the SKScene

    Code:
    @interface ViewController()
    {
    UILabel *progress;
        NSTimer *timer;
        int currMinute;
        int currSeconds;
    }
    @end
    
    
    @implementation ViewController
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        progress=[[UILabel alloc] initWithFrame:CGRectMake(80, 15, 100, 50)];
        progress.textColor=[UIColor redColor];
        [progress setText:@"Time : 3:00"];
        progress.backgroundColor=[UIColor clearColor];
        [self.view addSubview:progress];
        currMinute=3;
        currSeconds=00;
    
        // Do any additional setup after loading the view, typically from a nib.
    }
    -(void)start
    {
        timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerFired) userInfo:nil repeats:YES];
    
    }
    -(void)timerFired
    {
    if((currMinute>0 || currSeconds>=0) && currMinute>=0)
    {
        if(currSeconds==0)
        {
            currMinute-=1;
            currSeconds=59;
        }
        else if(currSeconds>0)
        {
            currSeconds-=1;
        }
        if(currMinute>-1)
        [progress setText:[NSString stringWithFormat:@"%@%d%@%02d",@"Time : ",currMinute,@":",currSeconds]];
    }
        else
        {
            [timer invalidate];
        }
    }
     
  7. MrFusion thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #7
    You are not using sprite kit elements. You are using a regular UILabel and a NSTimer. Spritekit has its own timer. Use that to your advantage.
    In semi pseudocode, I would do something like this:

    Code:
    @implementation YourView (subclass of SKView)
    -init
    {
     YourSKSceneSubclass *yourScene = alloc YourSKSceneSubclass
    [self presentScene:yourScene];
    }
    
    
    //user events (somehow you have to couple the start and stop event for your timer to the time at which they are generated. Then you pass this time to your scene)
    -(ibaction) startCountDown:(NSEvent) event
    {
     [self.scene startCountDown:[event timestamp]]; 
    }
    
    -(ibaction) stopCountDown:(NSEvent) event
    {
     [self.scene stopCountDown:[event timestamp]]; 
    }
    
    
    @end
    
    
    @implementation YourSKSceneSubclass (subclass of SKScene)
    {
     NSTimerInterval _startTime; 
    }
    -(ibaction) startCountDown:(NSEvent) event
    {
       _startTime = [event timestamp]; //this time when you start your counttime
      SKLabelScene *progessScene = alloc SKLabelScene
      [progessScene setName:@"countdown"]  //add the label to your view 
      [self addChild:progessScene];
    
    }
    
    -(void) stopCountDown
    {
      [[self childNodeWithName:@"countdown"] removeFromParent];  //remove the label from view
    }
    
    -(void) update:(CFTimeInterval) currentTime
    {
      CFTimeInterval expiredTime = currentTime - _startTime; //time that has passed since starting your timer
      CFTimeInterval remainingTime = <your time length in seconds> - expriredTime; // time that is left for the user
     [[self childNodeWithName:@"countdown"]  setText:....];
    
     if (remainingTime < 0)
       Time up. Game Over. Or whatever
    
    }
    
    
    
    
     
  8. pramgurusinga macrumors newbie

    Joined:
    Jan 27, 2014
    #8
    I've been able to create the timer programmatically. :D
    I'm not big fan of storyboard for now. I will upload the code later.
     
  9. MrFusion thread starter macrumors 6502a

    Joined:
    Jun 8, 2005
    Location:
    West-Europe
    #9
    hmmm, storyboard is actually great. You should learn to use it. But hey, step by step and at your own pace.
     

Share This Page