1

I created a game involving falling balls. Every time the player taps a ball, they're 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

DrPepperGrad
  • 361
  • 1
  • 4
  • 17

1 Answers1

2

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

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • When adding that line, it actually strips the ability for me to tap the ball at all. It went against this post that I made earlier http://stackoverflow.com/questions/38790908/touch-sprite-make-it-jump-up-then-fall-down-again-and-again – DrPepperGrad Aug 07 '16 at 01:26
  • @JNorris: Updated again, please try and let me know – Luca Angeletti Aug 07 '16 at 01:40
  • Nothing. I still can't tap the ball, when I remove touchesBegan from GameScene.swift. – DrPepperGrad Aug 07 '16 at 01:49
  • @JNorris: Tomorrow I'll try on a new project then. – Luca Angeletti Aug 07 '16 at 01:57
  • Yes! Thank you. Thanks for the help so far. – DrPepperGrad Aug 07 '16 at 01:59
  • any luck on the problem? – DrPepperGrad Aug 08 '16 at 00:05
  • It does work. In the console, I see the numbers going up by 1 every time I tap the ball, but how do I change the score label to display the increase in points/taps? – DrPepperGrad Aug 08 '16 at 13:48
  • @JNorris: Just put this `scoreLabel.text = "\(score)"` inside the `didSet`. I updated my code. – Luca Angeletti Aug 08 '16 at 13:58
  • Perfect. Thanks for the help. @appzYourLife – DrPepperGrad Aug 08 '16 at 14:53
  • Although, this interferes with my other post again. Now I can't tap the ball to make it jump again. The point gets added, but that's it. It's because of the `userInteractionEnabled = true` http://stackoverflow.com/questions/38790908/touch-sprite-make-it-jump-up-then-fall-down-again-and-again – DrPepperGrad Aug 08 '16 at 15:20
  • 1
    @JNorris: You don't need to set `userInteractionEnabled = false`. I updated my code. Look at the new `GameScene` code. You just need to put inside `GameScene.touchesBegan(touches:withEvent)` the code you want to execute when the user does tap outside of the Ball. – Luca Angeletti Aug 08 '16 at 15:29
  • 1
    awesome, everything is running smoothly. Thank you for the help! @appzYourLife – DrPepperGrad Aug 08 '16 at 15:37