Chapter 8. Adding our hero life line

After learning how to create a level in the previous chapter, it is time to add a life line to our hero that slowly depletes overtime. In the game, our hero can die in a few ways. He can fall off the platform and hit the ground, go off the screen, collide with certain obstacles like TNT, or just run out of his life line. Because our hero is a pencil he will need to collect as many sharpeners as he can to increase his life line. The life line will be displayed on the top right hand corner of the screen. The goal is to reach the finish line before you run out of lead and not hit the ground. Let’s see how to achieve this.

We will discuss the following Swift concepts in this chapter:

  • Convenience initializers
  • SKCropNode
  • Protocols

Creating a life line

To create a life line we need to start out with a full state and slowly deplete the health as time goes by, which in our case is the lead in the pencil. You can follow along with the Life Line Node playground code in the Github repo. We then integrate that code back into our Pencil Adventure Xcode project after we get the life line working the way that we want.

You can read the full source code of our Pencil Adventure game here on Github.

As usual, we will import the required frameworks and libraries and then define some global function that we used in the visual effects chapter called the callbackAfter. We will use this to fire a callback to decrease the health of our hero over time and restart the timer again until we run out of health, after which we print out Game Over for now.

So to follow a good object-oriented design pattern we have created a LineLineNode class, which inherits from SKCropNode. This class is like SKNode, but it has a maskNode which is an SKNode that will crop out the node from the scene. We will use this maskNode to slowly crop out the heart from our scene and when it is completely gone we will trigger the Game Over by printing it on the console.

Swift has a keyword called convenience, which we have used in our class constructor. Basically, this keyword lets the compiler know that we will call another initializer of the class, which in our case is calling init. The reason for using convenience instead of overloading the parameter is because we want to pass the scene into the LifeLineNode to get its scale so we can position it correctly for that scene and also to trigger a callback to the scene for game over later on when we are out of our life line.

convenience init(forScene scene: SKScene) {
    self.init()
    ...
}

Our game has the rule that about every second our hero will lose some of his health. To replenish it, he needs to get as many sharpeners as he can. So we not only need a subtract but also an addLifeLine method in our LifeLineNode class.

In our subtractLifeLine method we subtract 1% each time with this method, but in our addLifeLine we expect a life parameter to be passed to make the LifeLineNode class more flexible. This will allow you to give more life life to the hero for other power up items that we may add in the future.

private func subtractLifeLine() {
    lifeLine -= 0.01
    maskNode.yScale = lifeLine
    if lifeLine > 0 {
        callbackAfter(0.1, subtractLifeLine)
    } else {
        println("Game Over")
    }
}

public func addLifeLine(life: CGFloat) {
    // Give more led till Mr Pencil reaches the end
    if lifeLine + life > 1 {
        lifeLine = 1.0
    } else {
        lifeLine += life
    }
    maskNode.yScale = lifeLine
}

Integrating into the Pencil Adventure project

Integrating back, we create a separate file for LifeLineNode and instead of accepting a plain SKScene we change it to a GameScene class that implements the GameOverProtocol.

We will also change the println(“Game Over”) to calling the onGameOver method on the gameScene defined in the GameOverProtocol.

public protocol GameProtocol {
    var viewableArea: CGRect! { get }
    
    func gameEnd(didWin: Bool)
}

Protocols

Protocol patterns in Swift are similar to Interfaces in Java and they are exactly like Protocols in Objective-C with a few extra features. They help create a contract between classes to ensure that a method is implemented. Compilers use this to enforce that a certain object of a class can perform that method or has certain attributes so as to avoid errors during runtime. You can define protocols by just specifying the methods it needs or to implement attributes it should have. The cool thing about protocols in Swift is that you can even specify that these attributes must have a getter and setter as well.

In our GameProtocol we want any game scene to be able to handle the gameEnd method that will be called whenever the game ends so you can have a getter for a viewableArea. If we wan to set the viewableArea we can add the set keyword next to get as such.

var viewableArea: CGRect! { get set }

We do not want others to set the viewable area of the game scene, so we will not add the set in our project.

Summary

You have now implemented our life line node. You can now have our character die along with hitting the ground making it a little more challenging and fun. In this chapter we learned the purpose of convience methods and how it can be applied in our game and when to use it. This feature is unique to Swift and helps the reader understand the code slightly better.

Sprite Kit gives us a SKCropNode class as part of the framework, which is really handy for our use case. You can use it for a variety of use cases such as showing a loader that fills in completely or other use cases where you need to mask your node partially. 

Finally we learned about the Protocol pattern in Swift, which is really useful when doing object-oriented programming. Using protocols you can enforce a class to have certain methods and in Swift we can even enforce that a class may have certain attributes that can be read and also set if desired. In the next chapter we will go over saving the score when our hero makes it through to the end with his life line.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset