# Make a Clock in Sprite Kit: Adding Animation to the Clock

In our first installment, we added a label and set up a clock.  We could easily do that with a story board and a wired up label. The point of series this is to have a lot of cool animation running in Sprite Kit for a non game UI. We will begin to add animation today.

Before we do, as I discussed in another post, I grid my work. Instead of a whole class, I’ll only need a quick method here. Add this method just under the `@implementation`:

```-(CGPoint)gridPointX:(float)xPoint pointY:(float)yPoint{
CGFloat xDivision = CGRectGetMaxX(self.frame) /5.0;
CGFloat yDivision = CGRectGetMaxY(self.frame)/5.0;
return CGPointMake(xPoint * xDivision, yPoint * yDivision);
}
```

This will give us coordinates on a 6×6 grid for any point. Since the anchor points are the center of the node, there is a 4×4 grid of completely visible points. For this project, that is all we need.

# Make a Pendulum

Old-time clocks had a pendulum. We will use a flat design for a pendulum with a simple circle. Download the circle on the left by right clicking and using save as or its equivalent in your browser. Name it solidCirlce.png. Drag the downloaded file into your project, and in the dialog box, check on  copy to project . We now have a graphic, called a texture, for our project.

Add the following under the code `[self addChild:myTimeLabel];`

```//Make the ball
CGPoint tick = [self gridPointX:1 pointY:1];
CGPoint tock = [self gridPointX:4 pointY:1];
SKSpriteNode *bouncingBall = [SKSpriteNode spriteNodeWithImageNamed:@"solidcircle"];
bouncingBall.position = tock;
bouncingBall.name=@"bouncingBall";
```

Lines 2 and 3 set coordinates (1,1) and (4,1) on our grid for the swing of the clock. Line 4 initialized a Sprite Node from the bouncing ball image. We set the position and name in line 5 and 6 and add the child node to the node tree in line 7. Compared to the formatting and text options for a label, sprite nodes are usually less code to get started. Build and run this. There will be a solid circle in our app.

# Move the Pendulum

We have an object, now to move the object using animation. The `SKAction` class governs animation. We use one of three `runAction:(SKAction)` methods to associate an action with a node. Add the following code just under `[self addChild:bouncingBall];` :

```//simple animation to the ball
SKAction *bounceBall = [SKAction moveToX:tick.x duration:1.0];
[bouncingBall runAction:bounceBall withKey:@"bounceBall"];
```

Line 2 Creates a `SKAction`. Using a class method `moveToX:` it moves from `tock.x` to `tick.x`. The duration is in seconds, and we want to move in once second from `tock` to `tick`. Line 3 adds the action to the node, giving it a key bounceBall. Build and run this.

The ball moves from the right to the left in one second and stays there. We want a constantly moving ball. Replace the animation code above with this:

```//add animation to the ball
SKAction *bounceBall = [SKAction sequence:@[
[SKAction moveToX:tock.x duration:1.0],
[SKAction moveToX:tick.x duration:1.0],
]];
[bouncingBall runAction:[SKAction repeatActionForever:bounceBall] withKey:@"bounceBall"];
```

In line 2, we add the `SKAction` class method `sequence:`, which creates does actions from an array one after the other. We set up a literal array of two `SKAction`s, moving back and forth from `tick` to `tock`. In line 6, we added to our run action another class method `repeatActionForever:` to form an infinite motion. Build and run. We have a working pendulum.

The counterpart of `sequence:` is `group:`. While `sequence:` performs actions one at a time, `group:` performs actions at the same time. For example,  add another label after `[self addChild:myTimeLabel];`:

```self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
myDateLabel = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue"];
myDateLabel.text = @"Date Goes Here";
myDateLabel.fontSize = 40;
myDateLabel.alpha = 0.20;
myDateLabel.position = [self gridPointX:2.5 pointY:2.0];
myDateLabel.name = @"myDateLabel";
```

Add another instance variable, under `myTimeLabel`:

```SKLabelNode *myDateLabelNode;
```

Build and run. We now have a label just above the pendulum.

Add some code in `update:` to give us a date. Much of the code we did last time.  Make a formatted string and set the text property to make a date. Add this to the end of the code on `update:`

```NSString *formattedDateString =[NSString stringWithFormat:@"%04d %02d %02d", (int)currentDate.year, currentDate.month, currentDate.day];
myDateLabel.text = formattedDateString;
```

Build and run. The date is now on the bottom half of the app, faded out.

# Animate the Label with a Touch

We will toggle the between the date and time using a tap to the screen. Add the following `touchesBegan:` method to our scene implementation file:

```-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint topDisplay = [self gridPointX:2.5 pointY:4];
CGPoint bottomDisplay = [self gridPointX:2.5 pointY:2];
if ([touches count]>0){
SKAction *labelHideAction = [SKAction group:@[
[SKAction moveToY:bottomDisplay.y duration:3.0]
]];
SKAction *labelShowAction = [SKAction group:@[
[SKAction moveToY:topDisplay.y duration:3.0]]];

//remove previous action
[myTimeLabel removeActionForKey:@"timeLabelAction"];
[myDateLabel removeActionForKey:@"dateLabelAction"];

//toggle action
if(isShowingTime){
[myTimeLabel runAction:labelHideAction withKey:@"timeLabelAction"];
[myDateLabel runAction:labelShowAction withKey:@"dateLabelAction"];
}else{
[myTimeLabel runAction:labelShowAction withKey:@"timeLabelAction"];
[myDateLabel runAction:labelHideAction withKey:@"dateLabelAction"];
}
isShowingTime = !isShowingTime;
}
}
```

Line 4 checks for any touches to the frame. If there are some, we run the animation code, which toggles between two states. Line 5 and 9 set up two actions: moving up and fading in and moving down and fading out. After removing our previous actions, we set the actions for the two labels to either move up or down.

We need one more instance variable for a toggle. Place this under `myDateLabel:`

```BOOL isShowingTime;
```

Add this to initialize it at the end of `initWithSize:`

```isShowingTime=YES;
```

Build and run.

We now have a working clock which changes the date through animation. We quickly overrode the `touchesbegan:` method. Next time, we’ll explore this more and extend it to add some buttons to our clock.

# The Clock Code for MyScene.m

Here is the complete implementation file MyScene.m for the clock. This one file contains all the code for the clock, so it should cut and paste easily for those interested in doing so.

```//
//  MPMyScene.m
//  SpriteTimeClock
//
//  Created by Steven Lipton on 5/6/14.
//

#import "MPMyScene.h"

@implementation MPMyScene{
SKLabelNode *myTimeLabel;
SKLabelNode *myDateLabel;
BOOL isShowingTime;
}

-(CGPoint)gridPointX:(float)xPoint pointY:(float)yPoint{
CGFloat xDivision = CGRectGetMaxX(self.frame) /5.0;
CGFloat yDivision = CGRectGetMaxY(self.frame)/5.0;
return CGPointMake(xPoint * xDivision, yPoint * yDivision);
}

-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
/* Setup your scene here */
myTimeLabel = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue"];
myTimeLabel.text = @"00:00:00";
myTimeLabel.fontSize = 40;
myTimeLabel.position = CGPointMake(CGRectGetMidX(self.frame),
CGRectGetMaxY(self.frame)*0.80);
myTimeLabel.name = @"myTimeLabel";

self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];

myDateLabel = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue"];
myDateLabel.text = @"Date Goes Here";
myDateLabel.fontSize = 40;
myDateLabel.alpha = 0.20;
myDateLabel.position = [self gridPointX:2.5 pointY:2.0];
myDateLabel.name = @"myDateLabel";

//Make the ball
CGPoint tick = [self gridPointX:1 pointY:1];
CGPoint tock = [self gridPointX:4 pointY:1];
SKSpriteNode *bouncingBall = [SKSpriteNode spriteNodeWithImageNamed:@"solidcircle"];
bouncingBall.position = tock;
bouncingBall.name=@"bouncingBall";

/*
//simple animation to the ball
SKAction *bounceBall = [SKAction moveToX:tick.x duration:1.0];
[bouncingBall runAction:bounceBall withKey:@"bounceBall"];

*/
SKAction *bounceBall = [SKAction sequence:@[
[SKAction moveToX:tock.x duration:1.0],
[SKAction moveToX:tick.x duration:1.0],
]];
bounceBall.timingMode = SKActionTimingEaseInEaseOut;
[bouncingBall runAction:[SKAction repeatActionForever:bounceBall] withKey:@"bounceBall"];

isShowingTime = YES;
}

return self;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

CGPoint topDisplay = [self gridPointX:2.5 pointY:4];
CGPoint bottomDisplay = [self gridPointX:2.5 pointY:2];
if ([touches count]>0){
SKAction *labelHideAction = [SKAction group:@[
[SKAction moveToY:bottomDisplay.y duration:3.0]
]];
SKAction *labelShowAction = [SKAction group:@[
[SKAction moveToY:topDisplay.y duration:3.0]]];

//remove previous action
[myTimeLabel removeActionForKey:@"timeLabelAction"];
[myDateLabel removeActionForKey:@"dateLabelAction"];

//toggle action
if(isShowingTime){
[myTimeLabel runAction:labelHideAction withKey:@"timeLabelAction"];
[myDateLabel runAction:labelShowAction withKey:@"dateLabelAction"];
}else{
[myTimeLabel runAction:labelShowAction withKey:@"timeLabelAction"];
[myDateLabel runAction:labelHideAction withKey:@"dateLabelAction"];
}
isShowingTime = !isShowingTime;

}
}

-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
CFGregorianDate currentDate = CFAbsoluteTimeGetGregorianDate(CFAbsoluteTimeGetCurrent(), CFTimeZoneCopySystem());
CFRelease(CFTimeZoneCopySystem());
NSString *formattedTimeString = [NSString stringWithFormat:@"%02d:%02d:%02.0f", currentDate.hour, currentDate.minute, currentDate.second];
myTimeLabel.text = formattedTimeString;

NSString *formattedDateString =[NSString stringWithFormat:@"%04d %02d %02d", (int)currentDate.year, currentDate.month, currentDate.day];
myDateLabel.text = formattedDateString;

}

@end

```

### 4 responses to “Make a Clock in Sprite Kit: Adding Animation to the Clock”

1. […] the clock app so far, we have a date and a time. We can switch between them by tapping the screen of our phone. Most […]

2. […] have a quick and basic clock in a few lines of code. While this is not impressive by itself, next post we will add animation to the clock to switch between the date and the […]

3. Thanks for the tutorial. :)

Small typo error when you add the label for the date.
It should be “SKLabelNode *myDateLabelNode;” instead of “SKLabelNode *myDateLabelNode;”

4. Arf. I just made the same typo :p
Should be
SKLabelNode *myDateLabel;