Getting Started With iOS for a C# Programmer - Part Four - Controlling an Object

December 26, 2017

In this post, we covered how to move an object on the screen; this time, we’re going to control it. However, before we do, let’s change the game orientation to landscape only, as that’s really the only thing that makes sense on an iPhone for this type of game.

Landscape

The first thing to do is to change the code in the GameViewController to force the orienetation to landscape:

[code lang=“objc”] override var shouldAutorotate: Bool { return true }

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    if UIDevice.current.userInterfaceIdiom == .phone || UIDevice.current.userInterfaceIdiom == .pad {
        return .landscape
    } else {
        return .all
    }
}



When you run the simulator, the game will now appear on its side; to rectify that, select Hardware -> Rotate Left\*:

[![](http://pmichaels.net/wp-content/uploads/2017/11/xcode-part4-1-300x259.png)](http://pmichaels.net/wp-content/uploads/2017/11/xcode-part4-1.png)

# Control

As you may have noticed from the previous post, we do have a modicum of control over the rectangle; let's now change that so that we can press to the left and have it move left, or on the right and have it move right.

# Left and Right

It turns out that this is pretty easy [once you understand how the co-ordinates work in Swift](https://stackoverflow.com/questions/47196543/determine-the-width-of-an-skphysicsbody-in-swift):

[code lang="objc"]
    override func touchesBegan(\_ touches: Set<UITouch>, with event: UIEvent?) {
        for t in touches {
            self.touchDown(atPoint: t.location(in: player!))
        }
    }

And the touchDown function:

[code lang=“objc”] func touchDown(atPoint pos : CGPoint) { print (pos.x, pos.y)

    var halfWidth = (player?.frame.width)! / 2;
    
    if (pos.x < -halfWidth) {
        playerSpeed? -= CGFloat(1.0);
    } else if (pos.x > halfWidth) {
        playerSpeed? += CGFloat(1.0);
    }

}




Finally, we need the update event to do something with the playerSpeed:

[code lang="objc"]
    override func update(\_ currentTime: TimeInterval) {
        // Called before each frame is rendered
        player?.position.x += playerSpeed!
    }

Now we have a game where we can move the player left and right.

Tidy up

To clean up the screen before we get into firing, it would be nice if the player was lower down the screen, and a slightly different colour:

[code lang=“objc”]

func CreatePlayer() -> SKShapeNode {

    let playerSize = CGSize(width: 100, height: 10)
    
    let player = SKShapeNode(rectOf: playerSize)
    print(self.frame.minY, self.frame.maxY, self.frame.minX, self.frame.maxX, self.frame.width, self.frame.height)
    player.position = CGPoint(x:self.frame.midX, y:-150)
    player.strokeColor = SKColor(red: 0.0/255.0, green: 0.0/255.0, blue: 200.0/255.0, alpha: 1.0)
    player.lineWidth = 1
    
    player.physicsBody = SKPhysicsBody(rectangleOf: playerSize)
    
    player.physicsBody?.affectedByGravity = false
    player.physicsBody?.isDynamic = true
        
    return player
}



Remember, this is a landscape only game.

# Fire

Okay - so firing is just an extra clause in our touchDown function:

[code lang="objc"]
    
    func touchDown(atPoint pos : CGPoint) {
        print (pos.x, pos.y)
        
        var halfWidth = (player?.frame.width)! / 2;
        
        if (pos.x < -halfWidth) {
            playerSpeed? -= CGFloat(1.0);
        } else if (pos.x > halfWidth) {
            playerSpeed? += CGFloat(1.0);
        } else {
            Fire()
        }
    }

    func Fire() {
        let bullet = CreateBullet(point: (player?.position)!)
        self.addChild(bullet)
    }

    func CreateBullet(point : CGPoint) -> SKShapeNode {
        
        let bulletSize = CGSize(width: 1, height: 10)
        
        let bullet = SKShapeNode(rectOf: bulletSize)
        //print(self.frame.minY, self.frame.maxY, self.frame.minX, self.frame.maxX, self.frame.width, self.frame.height)
        bullet.position = point
        bullet.strokeColor = SKColor(red: 0.0/255.0, green: 0.0/255.0, blue: 200.0/255.0, alpha: 1.0)
        bullet.lineWidth = 4
        
        bullet.physicsBody = SKPhysicsBody(rectangleOf: bulletSize)
        
        bullet.physicsBody?.affectedByGravity = false
        bullet.physicsBody?.isDynamic = true
        
        bullet.name = "bullet"
        
        return bullet
    }


All we’ve actually done here is to create a new rectangle, and sourced it right at the centre of the player. We’ve added it to the self construct, so the automatic rendering will pick it up; next, we need to move it:

[code lang=“objc”] override func update(_ currentTime: TimeInterval) { // Called before each frame is rendered player?.position.x += playerSpeed!

    self.enumerateChildNodes(withName: "bullet") {
        (node, \_) in
        node.position.y += 1
    }
}



# Footnotes

\* Remember, when holding an iPhone or iPad, the button should always be on the right hand side - without wishing to judge, anyone that feels different is wrong, and very possibly evil.

# References

[https://stackoverflow.com/questions/475553/how-can-i-test-landscape-view-using-the-iphone-simulator](https://stackoverflow.com/questions/475553/how-can-i-test-landscape-view-using-the-iphone-simulator)


Profile picture

A blog about one man's journey through code… and some pictures of the Peak District
Twitter

© Paul Michaels 2022