1
votes

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

1
there is no reason why create player should be an extension, just throw it into the game scene class fileKnight0fDragon
Does adding extensions like this permit the extension to be in another file? I'm seriously asking this question, even if it's incredibly stupid. I simply do not know.Confused
and if so, how would it be done @Knight0fDragonConfused

1 Answers

2
votes

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