J Norris J Norris - 3 months ago 20
Swift Question

how come sprites start flashing?

SO I created a game where you tap balls to make them jump up. You get a point for every tap. Why do my sprites start flashing when I reach 10 points. I'm thinking it has something to do with the

update(timeInterval)
method. It may be a bug or bad coding.

import SpriteKit

class GameScene: SKScene {
let backgroundNode = SKSpriteNode(imageNamed: "redbackground")
override func didMoveToView(view: SKView) {



backgroundNode.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
self.addChild(backgroundNode)

//=======Ball 1=======//
let ball = Ball()

ball.position = CGPoint(x:self.frame.midX, y:440)

addChild(ball)



ball.physicsBody = SKPhysicsBody(circleOfRadius: 90)
ball.physicsBody?.dynamic = true
ball.physicsBody?.allowsRotation = false

ball.physicsBody?.friction = 0
ball.physicsBody?.angularDamping = 0
ball.physicsBody?.linearDamping = 0
ball.physicsBody?.usesPreciseCollisionDetection = true
ball.physicsBody!.categoryBitMask = 0
}

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

physicsBody?.velocity = CGVectorMake(0, 100)
physicsBody?.applyImpulse(CGVectorMake(0, 900))



}

override func update(currentTime: CFTimeInterval) {


if (score >= 10){
self.backgroundNode.texture = SKTexture(imageNamed: "orangebackground")
}


if (score >= 20){
self.backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
}


if (score >= 30) {
self.backgroundNode.texture = SKTexture(imageNamed: "greenbackground")
}

}


See this to see what I mean.(Click or tap link)

This shows the sprites flashing at 10 points

thanks in advance, Jordan

Answer

It is flashing because of this

override func update(currentTime: CFTimeInterval) {
    if (score >= 10){
        self.backgroundNode.texture = SKTexture(imageNamed: "orangebackground")
    }


    if (score >= 20){
        self.backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
    }


    if (score >= 30) {
        self.backgroundNode.texture = SKTexture(imageNamed: "greenbackground")
    }

}

Infact inside the update method, when the score become >= 10, you are updating the texture EVERY FRAME.

This is absolutely wrong.

If you want to update the texture just do it when you need to change it (e.g. when the score goes from 9 to 10, or from 19 to 20 or from 29 to 30.).

But there's no point in updating the texture when it stays at 10 of when it goes from 10 to 11 since you will update it with another texture which is the same.

How can you do it?

Just create a shouldUpdateTexture: Bool = false property, then each time you update the score, if the score goes from 9 to 10 or 19 to 20 or 29 to 30 then turn shouldUpdateTexture to true.

Finally inside the update method check if shouldUpdateTexture is true, in this case set it back to false and update the texture.

Full code

class GameScene: SKScene {

    private var score = 0 {
        didSet {
            shouldUpdateTexture = oldValue < 10 && score >= 10 || oldValue < 20 && score >= 20 || oldValue < 30 && score >= 30
        }
    }
    private var shouldUpdateTexture = false
    private var backgroundNode = SKSpriteNode(imageNamed: "defaultbackground")


    override func update(currentTime: CFTimeInterval) {
        guard shouldUpdateTexture else { return }
        shouldUpdateTexture = false
        switch score {
        case 10...19: backgroundNode.texture = SKTexture(imageNamed: "orangebackground")
        case 20...29: backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
        case 30...Int.max: backgroundNode.texture = SKTexture(imageNamed: "yellowbackground")
        default: break
        }
    }

}

That's it.

Comments