NEW: Learn SwiftUI with my free YouTube video series! >>

< Previous: Space: the final frontier   Next: Making contact: didBegin() >

Bring on the enemies: Timer, linearDamping, angularDamping

The point of our game is for the spaceship to survive while random "space debris" gets thrown at it. I've included three items of various shapes in this example, but you can add more easily enough. As long as the player stays alive their score ticks upwards, so clearly it's going to take some quick movement to get the highest score.

To add enemies and time to the game, we need to declare three new properties:

let possibleEnemies = ["ball", "hammer", "tv"]
var isGameOver = false
var gameTimer: Timer?

The possibleEnemies array contains the names of the three images that can be used as space debris in the game: a ball, a hammer and a TV. The isGameOver is a simple boolean that will be set to true when we should stop increasing the player's score.

The third property is a new type, called Timer. This is responsible for running code after a period of time has passed, either once or repeatedly.

When you create an Timer you specify five parameters: how many seconds you want the delay to be, what object should be told when the timer fires, what method should be called on that object when the timer fires, any context you want to provide, and whether the time should repeat.

We need to create a new enemy on a regular basis, so the first thing to do is create a scheduled timer. I'm going to give it a timer interval of 0.35 seconds, so it will create about three enemies a second. Put this code into didMove(to:):

gameTimer = Timer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(createEnemy), userInfo: nil, repeats: true)

Tip: The scheduledTimer() timer not only creates a timer, but also starts it immediately.

Creating an enemy needs to use techniques that you've mostly seen already: it will shuffle the possibleEnemies array, create a sprite node using the first item in that array, position it off the right edge and with a random vertical position, then add it to the scene.

That part is old. The new part is the way we're going to create the physics body of the debris: we're going to use per-pixel collision again, tell it to collide with the player, make it move to the left at a fast speed, and give it some angular velocity. But we're also going to set to 0 its linearDamping and angularDamping properties, which means its movement and rotation will never slow down over time. Perfect for a frictionless space environment!

Add this createEnemy() method:

@objc func createEnemy() {
    guard let enemy = possibleEnemies.randomElement() else { return }

    let sprite = SKSpriteNode(imageNamed: enemy)
    sprite.position = CGPoint(x: 1200, y: Int.random(in: 50...736))
    addChild(sprite)

    sprite.physicsBody = SKPhysicsBody(texture: sprite.texture!, size: sprite.size)
    sprite.physicsBody?.categoryBitMask = 1
    sprite.physicsBody?.velocity = CGVector(dx: -500, dy: 0)
    sprite.physicsBody?.angularVelocity = 5
    sprite.physicsBody?.linearDamping = 0
    sprite.physicsBody?.angularDamping = 0
}

Now that lots of debris will appear, we need to make sure we remove their nodes once they are invisible. In this game, that means removing nodes from the scene once they are effectively useless because they have passed the player. This will be done using a check in the update() method: if any node is beyond X position -300, we'll consider it dead.

The update() method is also a good place to make our score increment all the time. All we need to do is check whether isGameOver is still false, and add one to the score if so. Here's the code for the update() method:

override func update(_ currentTime: TimeInterval) {
    for node in children {
        if node.position.x < -300 {
            node.removeFromParent()
        }
    }

    if !isGameOver {
        score += 1
    }
}

Random deadly objects are thrown at the player, who scores points simply by staying alive.

LEARN SWIFTUI FOR FREE I wrote a massive, free SwiftUI tutorial collection, and also have a growing list of free SwiftUI tutorials on YouTube – get started today!

< Previous: Space: the final frontier   Next: Making contact: didBegin() >
MASTER SWIFT NOW
Buy Testing Swift Buy Practical iOS 12 Buy Pro Swift Buy Swift Design Patterns Buy Swift Coding Challenges Buy Server-Side Swift (Vapor Edition) Buy Server-Side Swift (Kitura Edition) Buy Hacking with macOS Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with Swift Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Beyond Code

Was this page useful? Let me know!

Average rating: 4.0/5

Click here to visit the Hacking with Swift store >>