Moving and rotating sprite with touches using SKSpriteKit and Swift 4

82 views Asked by At

I am wanting my sprite "Character" to move and rotate "follow" my finger as I move it around. I had it working fine but somehow have managed to screw it up. I'm not sure what I've done but can't for the life of me figure it out.

Any help would be greatly appreciated. Im sure its something stupid that I'm just overlooking. Thanks in advance.

Mark

GameScene.swift

import SpriteKit
import GameplayKit

//MARK: ---------------Global Variables Section

var nodeType: String = String()

var characterNode = Character()
let characterImage: String = String("default_pose")
var characterTexture:SKTexture = SKTexture()
let characterSize: CGSize = CGSize(width: 64, height: 64)
let characterPosition: CGPoint = CGPoint(x: 0, y: 0)

var enemyNode = Enemy()
let enemyImage: String = String("blob1")
var enemyTexture = SKTexture()
let enemySize: CGSize = CGSize(width: 50, height: 50)
let enemyPosition: CGPoint = CGPoint(x: 150, y: 150)


class GameScene: SKScene, SKPhysicsContactDelegate {


    //MARK: --------------------Class Variables Section

    var affectedByGravity: Bool = false
    var dynamic: Bool = true
    var rotation: Bool = false

    var lastUpdateTime: CFTimeInterval = 0

    //MARK: --------------------DidMove to View Section

    override func didMove(to view: SKView) {

        var node = SKSpriteNode()

        node = addNode(NodeType: "Character")
        applyPhysics(physicsNode: node, nodeImage: characterImage, nodeSize: characterSize, nodeName: node.name!)
        node.zPosition = 10
        addChild(node)

        node = addNode(NodeType: "Enemy")
        applyPhysics(physicsNode: node, nodeImage: enemyImage, nodeSize: enemySize, nodeName: node.name!)
        node.zPosition = 9
        addChild(node)
    }


    //MARK: -----------------------Add Node Section

    func addNode(NodeType: String) -> SKSpriteNode {

        var node = SKSpriteNode()

        switch NodeType {

        case "Enemy":

            node = enemyNode.setupNode(nodeName: "Enemy", nodeImage: "blob1", nodeSize: enemySize, nodePosition: enemyPosition)

        default:
            node = characterNode.setupNode(nodeName: "Player", nodeImage: "default_pose", nodeSize: characterSize, nodePosition: characterPosition)
        }
        return node
    }

    //MARK: ------------------------Physics Section

    func applyPhysics(physicsNode: SKSpriteNode, nodeImage: String, nodeSize: CGSize, nodeName: String) {

        let nodeTexture: SKTexture = SKTexture(imageNamed: nodeImage)

        physicsNode.physicsBody = SKPhysicsBody(texture: nodeTexture, size: nodeSize)
        physicsNode.physicsBody?.isDynamic = dynamic
        physicsNode.physicsBody?.affectedByGravity = affectedByGravity
        physicsNode.physicsBody?.allowsRotation = rotation
        physicsNode.physicsBody?.categoryBitMask = 1
        physicsNode.physicsBody?.contactTestBitMask = 1
        physicsNode.physicsBody?.collisionBitMask = 1

    }

    //MARK: ------------------------Movement and Rotation Section

    func moveAndRotate(sprite: Character, toPosition position: CGPoint) {

        let angle = atan2(position.y - sprite.position.y, position.x - sprite.position.x)

        let rotateAction = SKAction.rotate(toAngle: angle - .pi / 2, duration: 0.05, shortestUnitArc:true)

        sprite.run(rotateAction)

        let offsetX = position.x - (sprite.position.x)
        let offsetY = position.y - (sprite.position.y)

        let normal = simd_normalize(simd_double2(x: Double(offsetX), y:Double(offsetY)))

        characterNode.velocity = CGVector(dx: CGFloat(normal.x) * sprite.movePointsPerSecond, dy: CGFloat(normal.y) * sprite.movePointsPerSecond)
    }

    //MARK: ----------------------Touches Section

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch = touches.first {
            let touchLocation = touch.location(in: self)
            characterNode.isMoving = true
            moveAndRotate(sprite: characterNode, toPosition: touchLocation)
        }
    }

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

        if let touch = touches.first {
            let touchLocation = touch.location(in: self)
            moveAndRotate(sprite: characterNode, toPosition: touchLocation)
        }
    }

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

        characterNode.isMoving = false
    }


    //MARK: ------------------Update Section

    override func update(_ currentTime: TimeInterval) {

        let deltaTime = max(1.0/30, currentTime - lastUpdateTime)
        lastUpdateTime = currentTime

        update(character: characterNode, dt: deltaTime)
    }

    func update(character: Character, dt: CFTimeInterval) {
        if characterNode.isMoving == true {
            let newX = character.position.x + character.velocity.dx * CGFloat(dt)
            let newY = character.position.y + character.velocity.dy * CGFloat(dt)

            character.position = CGPoint(x: newX, y: newY)
        }
    }
}

Character.swift

import SpriteKit
import GameplayKit

class Character: SKSpriteNode {

    let movePointsPerSecond: CGFloat = 150.0
    var velocity = CGVector(dx: 0.0, dy: 0.0)
    var isMoving = false

    var node: SKSpriteNode = SKSpriteNode()

    func setupNode(nodeName: String, nodeImage: String, nodeSize: CGSize, nodePosition: CGPoint) -> SKSpriteNode {

        node = SKSpriteNode(imageNamed: nodeImage)
        node.name = nodeName
        node.position = nodePosition

        return node
    }
}
1

There are 1 answers

0
Knight0fDragon On

Your node does not move because you never assign characterNode to the node on your screen

   override func didMove(to view: SKView) {

        var node = SKSpriteNode()

        node = addNode(NodeType: "Character")
        applyPhysics(physicsNode: node, nodeImage: characterImage, nodeSize: characterSize, nodeName: node.name!)
        node.zPosition = 10
        addChild(node)
        characterNode = node //ADD THIS LINE
        node = addNode(NodeType: "Enemy")
        applyPhysics(physicsNode: node, nodeImage: enemyImage, nodeSize: enemySize, nodeName: node.name!)
        node.zPosition = 9
        addChild(node)
    }