Applications open until spots fill up - Apply now.

Building the core mechanic

Building the core mechanic

April 11, 2017
Expand

Project: Learn to clone Timberman with SpriteKit and Swift 3

Time to work on the games core mechanic, it's a lesser known fact that cat's will punch sushi as all they want is some sashimi. Cats can also navigate space and time to teleport instantly from one side of the screen to the other and knock those sushi clean out of the sushi tower.

You will be adding a simple touch mechanic to the game, if the player touches anywhere on the left/right hand side of the screen, the cat will be moved to the left/right side and then punch the first piece of sushi in the sushi tower.

Touch control

Replace the touchBegan(...) method with the following:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
   /* Called when a touch begins */

   /* We only need a single touch here */
   let touch = touches.first!

   /* Get touch position in scene */
   let location = touch.location(in: self)

   /* Was touch on left/right hand side of screen? */
   if location.x > size.width / 2 {
      character.side = .right
   } else {
      character.side = .left
   }
}

You are performing a simple check to decide which side of the screen was touched. Remember the property observer didSet, that you setup in Character.swift (Take a quick look)? When you set the side property the cat will move set its position appropriately.

Run the game... You should have a working cat teleporter.

Animated cat teleporter

Cat knockout

Great, your cat can move, how about that punch?

You are going to create three animation actions to enable your cat to perform this feat.

  • A frame animation sequence for the cat punch
  • A rotation/move sequence for the sushi in both left/right flavors

One Punch animation

Open GameScene.sks and click on create new action in the timeline and name it Punch: Create new punch action

Save this new SpriteKit Action file as AnimationActions.sks Save SpriteKit Action file

This will open up the empty AnimationActions.sks, and you should have an empty Punch action in the timeline.

Expand then Punch action timeline, click on the Object library and drag across an AnimateWithTextures Action. Add AnimateWithTextures action

To build the animation you need to drag in the character2.png and character3.png from the Media Library into the Textures box of the new action. Set the duration to 0.15 as a punch should be snappy and tick Restore, this ensures when the punch is complete the cat will go back to it's default stance.

AnimateWithTextures attributes

Adding sound to the timeline

Let's enhance the punch with a swipe sound effect. You can tie this into the punch animation by adding a sound action to the timeline.

Drag the PlaySoundFileNamed action across to the Punch timeline, add it at 0 below the Animate With Textures action. Set the Filename to sfx_swipe. Adding sound to the timeline

Applying the action

You will run this custom Punch action whenever the side is set for the cat.

Open Character.swift, add the following inside the didSet observer after the if/else statement block.

/* Load/Run the punch action */
let punch = SKAction(named: "Punch")!
runAction(punch)

Run the game. Your cat should be able to punch now!

Animated cat punch

Sushi tower

Looking good, next you will need to manage the sushi stack in response to a punch, this will involve:

  • Removing the punched sushi from the sushi tower
  • Adding a new random sushi to the top of the tower
  • Animating the sushi being knocked out of the tower

Let's tackle removing and adding sushi before applying the visual polish.

Open GameScene.swift and add the following code inside touchBegan(...) immediately after the if/else statement block.

/* Remove from sushi tower array */
sushiTower.removeFirst()

/* Add a new sushi piece to the top of the sushi tower*/
addRandomPieces(1)

Run the game.... Well nothing much happens, this is because you are managing the sushi tower array correctly. However, you are not removing the sushi visually from the scene.

Improving the cycle

Replace this code block with:

/* Grab sushi piece on top of the base sushi piece, it will always be 'first' */
let firstPiece = sushiTower.first as SushiPiece!

/* Remove from sushi tower array */
sushiTower.removeFirst()
firstPiece.removeFromParent()

/* Add a new sushi piece to the top of the sushi tower */
addRandomPieces(1)

Run the game... You can see the sushi being removed from the sushi tower. Great, yet not quite what you want, would be better if the remaining sushi would drop down a position. Let's add this.

Moving the tower

Add the following code after the last block:

/* Drop all the sushi pieces down one place */
for sushiPiece in sushiTower {
   sushiPiece.run(SKAction.move(by: CGVector(dx: 0, dy: -55), duration: 0.10))

   /* Reduce zPosition to stop zPosition climbing over UI */
   sushiPiece.zPosition -= 1
}

Run the game... Should look a lot better now.

You're applying a moveBy action to move every piece of sushi in the sushi tower down by 55 pixels. You're also decreasing the Z-Position of each piece. If you recall every time a new piece is added the Z-Position is incremented, the problem here is as the position climbs it will eventually become higher than other visual elements such as our UI.
This way you keep the Z-Position of all the pieces in a manageable range.

Animating the sushi

Time for you to add a bit of polish and create two new action animations.

Open AnimationActions.sks and create a new action called FlipRight. Expand the timeline for this action and drag across a Move Action Set the Duration to 0.5, Timing function to Ease In and Offset X to 300.

Move action attributes

Now drag across a Rotate Action and place it directly under the Move Action. Set the Duration to 0.5

FlipRight action

Great, you will need a FlipLeft action as well, it is possible to Duplicate an action. However, there is no way to rename it which isn't so great.

Create a new action called FlipLeft Copy the two actions from FlipRight into the FlipLeft timeline. Modify the Offset X of the Move Action to -300

Now you have two actions ready to be run in your game code. You will create a new method in SushiPiece.swift to facilitate this.

Open SushiPiece.swift and add the following method to the class:

func flip(_ side: Side) {
   /* Flip the sushi out of the screen */

   var actionName: String = ""

   if side == .left {
      actionName = "FlipRight"
   } else if side == .right {
      actionName = "FlipLeft"
   }

   /* Load appropriate action */
   let flip = SKAction(named: actionName)!

   /* Create a node removal action */
   let remove = SKAction.removeFromParent()

   /* Build sequence, flip then remove from scene */
   let sequence = SKAction.sequence([flip,remove])
   run(sequence)
}

Read through the comments, most of this should already be familiar to you. You may not have seen the last section of code in which you build a SKAction.sequence, which is simply joining actions together. In this case when the Flip animation is complete you want the sushi to be removed from the game. Currently in the code you are calling removeFromParent() to instantly remove the sushi, so the player will never see the anination.

Open GameScene.swift and replace the following inside touchesBegan(...)

firstPiece.removeFromParent()

with

/* Animate the punched sushi piece */
firstPiece.flip(character.side)

Now run the game.... Flying sushi!

Animated cat punches

Summary

Great job, you've achieved a lot in this chapter, the game's core mechanic is now in place. You've learnt to:

  • Add touch controls
  • Build animations visually
  • Run animation sequences in code
  • Manage an array

Next it's time to turn this core game mechanic into an actual game.

Feedback

If you have feedback on this tutorial or find any mistakes, please open issues on the GitHub Repository.

Summer academy

An iOS Development Summer Course

Design, code and launch your own app. Locations across the USA and Asia

Find your location

Product College

A computer science college

Graduate into a successful career as a founder or software engineer.

Learn more