J Norris J Norris - 4 months ago 17
Swift Question

How to add 1 point every time SKNode is touched

I created a game that there are falling balls and every time you tap on a ball, the player is supposed to get a point. I set up the score label, but it just stays at 0. Is there something wrong with my code?

I use a GameElements.swift file as an extension. Here is the file:

extension GameScene {
//1st Ball//
func createPlayer() -> SKNode {

let playerNode = SKNode()
playerNode.position = CGPoint(x:self.size.width / 2, y:440)

let sprite = SKSpriteNode(imageNamed: "Ball")
sprite.name = "ballPoints"
playerNode.addChild(sprite)

playerNode.physicsBody = SKPhysicsBody(circleOfRadius: 120)

playerNode.physicsBody?.dynamic = true
playerNode.physicsBody?.allowsRotation = false

playerNode.physicsBody?.restitution = 3
playerNode.physicsBody?.friction = 0
playerNode.physicsBody?.angularDamping = 0
playerNode.physicsBody?.linearDamping = 0

playerNode.physicsBody?.usesPreciseCollisionDetection = true


playerNode.physicsBody?.categoryBitMask = CollisionBitMask.Player

playerNode.physicsBody?.categoryBitMask = 0

return playerNode
}
}


Here is the GameScene.swift file:

class GameScene: SKScene {

var foreground: SKNode!
var hud: SKNode!
var firstBall: SKNode!

var scoreLabel: SKLabelNode!

private var score = 0
override func didMoveToView(view: SKView) {


scoreLabel = SKLabelNode(fontNamed:"Geared-Slab")
scoreLabel.fontColor = UIColor.blackColor()
scoreLabel.position = CGPoint( x: self.frame.midX, y: 3 * self.frame.size.height / 4 )
scoreLabel.fontSize = 100.0
scoreLabel.zPosition = 100
scoreLabel.text = String(score)
self.addChild(scoreLabel)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
if(firstBall.containsPoint(location)) {
firstBall.physicsBody?.velocity = CGVectorMake(0, 600)
firstBall.physicsBody?.applyImpulse(CGVectorMake(0, 1100))


}
if
let touch : UITouch! = touches.first,
let tappedSprite = nodeAtPoint(touch!.locationInNode(self)) as? SKSpriteNode,
let scoreLabel = childNodeWithName("scoreLabel") as? SKLabelNode
where tappedSprite.name == "ballPoints" {
score += 1
scoreLabel.text = "Score: \(score)"
}
}
}

override init(size:CGSize) {
super.init(size: size)

foreground = SKNode()
addChild(foreground)


//1st Ball//
firstBall = createPlayer()
foreground.addChild(firstBall)
}

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

}


I know this is a lot of code, but I want experts to be able to test the code themselves. For background, I was following this tutorial: https://www.youtube.com/watch?v=0gOi_2Jwt28 up until a certain point.

enter image description here
Best regards, Jordan

Answer

Step 1

First of all let's create a class for the Ball

class Ball: SKSpriteNode {
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let scene = self.scene as! GameScene
        scene.score += 1
    }
}

Step 2

Then inside createPlayer() let's replace this

let sprite = SKSpriteNode(imageNamed: "Ball")

with this

let sprite = Ball(imageNamed: "Ball")
sprite.userInteractionEnabled = true

Step 3

Let's remove the touchesBegan from GameScene.

Update

This code is working as expected for me

class GameScene: SKScene {

    var scoreLabel: SKLabelNode!
    var ball: Ball!
    private var score = 0 {
        didSet {
            scoreLabel.text = "\(score)"
            print(score)

        }
    }

    override func didMoveToView(view: SKView) {
        let ball = Ball()
        ball.position = CGPoint(x:frame.midX, y: frame.midY)
        addChild(ball)
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        // this is called when you tap outside of the Ball
        // use self.ball to make the ball to jump
    }
}

class Ball: SKSpriteNode {

    init() {
        let texture = SKTexture(imageNamed: "ball")
        super.init(texture: texture, color: .clearColor(), size: texture.size())
        userInteractionEnabled = true
    }


    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let scene = self.scene as! GameScene
        scene.score += 1
    }

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

enter image description here