Search code examples
iosswiftsprite-kitskspritenodegamekit

How to convert this game code to Swift 4?


I am an old programmer from way back but haven't done anything in a few (24) years. :). Things have changed a little.

I found some code that I'm trying to play around with but it seems the code was written in an earlier version of swift. I have converted it to the best of my ability, and the programs compiles with no errors. But the sprite node doesn't move at all.

Ultimately I'm trying to get a sprite node (player) to follow my touch as I drag it around the screen. and to stop when I stop touching.

If someone has a different way to accomplish the same goal that is fine also.

GameScene.swift

import SpriteKit
import GameplayKit

class GameScene: SKScene {

let trackingAgent = GKAgent2D()
var player = AgentNode()

var seekGoal : GKGoal = GKGoal()

let stopGoal = GKGoal(toReachTargetSpeed: 0)

var seeking : Bool = false {
    willSet {
        if newValue {
            self.player.agent.behavior?.setWeight(1, for: seekGoal)
            self.player.agent.behavior?.setWeight(0, for: stopGoal)
        }else{
            self.player.agent.behavior?.setWeight(0, for: seekGoal)
            self.player.agent.behavior?.setWeight(1, for: stopGoal)
        }
    }
}

var agentSystem = GKComponentSystem()

var lastUpdateTime : TimeInterval = 0

override func didMove(to view: SKView) {
    super.didMove(to: view)

    self.trackingAgent.position = vector_float2(Float(self.frame.midX), Float(self.frame.midY))

    self.agentSystem = GKComponentSystem(componentClass: GKAgent2D.self)

    self.player = AgentNode(scene: self, radius: Float(40.0), position: CGPoint(x: self.frame.midX, y: self.frame.midY))

    self.player.agent.behavior = GKBehavior()
    self.agentSystem.addComponent(self.player.agent)

    self.seekGoal = GKGoal(toSeekAgent: self.trackingAgent)
}

override func update(_ currentTime: CFTimeInterval) {

    if lastUpdateTime == 0 {
        lastUpdateTime = currentTime
    }

    let delta = currentTime - lastUpdateTime
    lastUpdateTime = currentTime
    self.agentSystem.update(deltaTime: delta)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.seeking = true
    handleTouch(touches: touches)
}

override func touchesCancelled(_ touches: Set<UITouch>?, with event: UIEvent?) {
    self.seeking = false
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.seeking = false
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    handleTouch(touches: touches)
}

func handleTouch(touches:Set<UITouch>) {
    guard let touch = touches.first else {
        return
    }

    let location = touch.location(in: self)

    self.trackingAgent.position = vector_float2(Float(location.x), Float(location.y))
}
}

AgentNode.swift

import GameplayKit
import SpriteKit

class AgentNode : SKNode, GKAgentDelegate {
var agent = GKAgent2D()

var triangleShape = SKShapeNode()

override init(){
    super.init()
}

init(scene:SKScene, radius:Float, position:CGPoint) {
    super.init()

    self.position = position
    self.zPosition = 10;
    scene.addChild(self)

    agent.radius = radius
    agent.position = vector_float2(Float(position.x), Float(position.y))
    agent.delegate = self
    agent.maxSpeed = 100 * 4
    agent.maxAcceleration = 50 * 4

    let ship = SKSpriteNode(imageNamed:"Spaceship")
    ship.setScale(1.0 / 8.0)
    ship.zRotation = CGFloat(-Double.pi / 2.0)
    self.addChild(ship)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

private func agentWillUpdate(agent: GKAgent) {

}

private func agentDidUpdate(agent: GKAgent) {
    guard let agent2D = agent as? GKAgent2D else {
        return
    }

    self.position = CGPoint(x: CGFloat(agent2D.position.x), y: CGFloat(agent2D.position.y))
    self.zRotation = CGFloat(agent2D.rotation)
}
}

Solution

  • The last two functions should not be private. And change to delegate's signature. It's working now. Have fun.

       func agentWillUpdate(_ agent: GKAgent) {
    
    }
    
    
    
    func agentDidUpdate(_ agent: GKAgent) {
        guard let agent2D = agent as? GKAgent2D else {
            return
        }
    
        self.position = CGPoint(x: CGFloat(agent2D.position.x), y: CGFloat(agent2D.position.y))
        self.zRotation = CGFloat(agent2D.rotation)
    }