Swift 为什么精灵开始闪烁?

Swift 为什么精灵开始闪烁?,swift,sprite-kit,Swift,Sprite Kit,所以我创造了一个游戏,你轻拍球让它们跳起来。你每轻敲一次就得一分。为什么我的精灵在我达到10点时开始闪烁。我认为这与update(timeInterval)方法有关。这可能是一个错误或错误的编码 import SpriteKit class GameScene: SKScene { let backgroundNode = SKSpriteNode(imageNamed: "redbackground") override func didMoveToView(view: SKView) {

所以我创造了一个游戏,你轻拍球让它们跳起来。你每轻敲一次就得一分。为什么我的精灵在我达到10点时开始闪烁。我认为这与
update(timeInterval)
方法有关。这可能是一个错误或错误的编码

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")
    }

}
导入SpriteKit
类游戏场景:SKScene{
let backgroundNode=SKSpriteNode(图像名为:“redbackground”)
覆盖func didMoveToView(视图:SKView){
backgroundNode.position=CGPoint(x:CGRectGetMidX(self.frame),y:CGRectGetMidY(self.frame))
self.addChild(backgroundNode)
//==========球1=======//
让ball=ball()
ball.position=CGPoint(x:self.frame.midX,y:440)
addChild(球)
ball.physicsBody=SKPhysicsBody(圆圈半径:90)
ball.physicsBody?动态=真
ball.physicsBody?.allowsRotation=false
球体。物理体?摩擦力=0
球.物理体?.angularDamping=0
ball.physicsBody?.linearDamping=0
ball.physicsBody?.usesPreciseCollisionDetection=true
ball.physicsBody!.categoryBitMask=0
}
班级舞会:斯普林特诺德{
init(){
let texture=SKTexture(图像名为:“球”)
super.init(纹理:纹理,颜色:.clearColor(),大小:纹理.size())
userInteractionEnabled=true
}
覆盖功能触摸开始(触摸:设置,withEvent事件:UIEvent?){
让scene=self.scene为!游戏场景
场景分数+=1
physicsBody?速度=CGVectorMake(01100)
physicsBody?应用脉冲(CGVectorMake(0900))
}
覆盖函数更新(currentTime:CFTimeInterval){
如果(分数>=10){
self.backgroundNode.texture=SKTexture(ImageName:“orangebackground”)
}
如果(分数>=20){
self.backgroundNode.texture=SKTexture(ImageName:“yellowbackground”)
}
如果(分数>=30){
self.backgroundNode.texture=SKTexture(ImageName:“greenbackground”)
}
}
查看此内容以了解我的意思。(单击或点击链接)


提前感谢,Jordan

正因为如此,它才会闪烁

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")
    }

}
实际上,在更新方法中,当分数变为
=10
时,您正在更新纹理每帧

这是绝对错误的

如果要更新纹理,只需在需要更改纹理时执行(例如,当分数从9到10,或从19到20,或从29到30)

但是当纹理从10变为11时,当它保持在10时,更新纹理没有意义,因为你将使用另一个相同的纹理来更新它

你怎么能做到? 只需创建一个
shouldUpdateTexture:Bool=false
属性,然后每次更新
分数时,如果
分数从9到10或19到20或29到30,则将
shouldUpdateTexture
转到
true

最后,在
update
方法中检查
shouldUpdateTexture
是否为true,在这种情况下,将其设置回
false
并更新纹理

完整代码
class游戏场景:SKScene{
私人风险值得分=0{
迪塞特{
应该更新上下文=旧值<10&&score>=10 | |旧值<20&&score>=20 | |旧值<30&&score>=30
}
}
私有变量shouldUpdateTexture=false
私有var backgroundNode=SKSpriteNode(ImageName:“defaultbackground”)
覆盖函数更新(currentTime:CFTimeInterval){
如果应该更新上下文{
shouldUpdateTexture=false
交换分数{
案例10…19:backgroundNode.texture=SKTexture(图像名为:“orangebackground”)
案例20…29:backgroundNode.texture=SKTexture(图像名为:“yellowbackground”)
案例30…Int.max:backgroundNode.texture=SKTexture(图像名为:“yellowbackground”)
默认值:中断
}
}
}
}
就这样

更新 正如@Knight0fDragon所指出的,将我放入
update
方法中的代码移动到
didSet
中可能会更快

优点:这样您就不需要在每一帧执行布尔等式检查

Cons:如果在同一帧内多次更改
分数
值,则将执行纹理的多次加载


您可以在
得分
中添加属性观测者,而不是在
更新
中更改背景图像,该属性观测者仅在得分达到特定值时更改背景。例如:

let backgroundNames = ["orangebackground","yellowbackground","greenbackground"]
// The didSet observer is called when the score is updated
var score:Int = 0 {
    didSet {
        // Check if score is divisible by 10
        if score % 10 == 0 {
            // Determine the array index
            let index = score / 10
            // Wrap to avoid index out of range
            let name = backgroundNames[index % backgroundNames.count]
            print (name)
        }
    }
}
也就是说,闪烁可能是由节点的呈现顺序造成的。根据苹果的文档

…使用[ignoresSiblingOrder=true],您无法预测 共享相同高度的节点的渲染顺序。渲染 每次渲染新帧时,顺序可能会更改

例如,您可以通过将背景的
zPosition
设置为负值来解决此问题

self.backgroundNode.zPosition = -100

因此,背景总是在游戏节点之前绘制。

这只是一种替代方法,允许分数发生多次变化,而不会用不必要的代码淹没更新功能

class GameScene: SKScene {

    private var score = 0 {
        didSet {
             ///if a change in the 10s happen,  then update texture
             if(score/10 > oldValue/10)
             {
                 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: "greenbackground")
                     default: break
                 }
            }
        }
    }
    private var shouldUpdateTexture = false
    private var backgroundNode = SKSpriteNode(imageNamed: "defaultbackground")



}
然后是优化:(实际上不需要,但可能有助于思考代码)

class游戏场景:SKScene{
让bgTextures=[SKTexture(ImageName:“orangebackground”)、SKTexture(ImageName:“yellowbackground”)、SKTexture(ImageName:“greenbackground”)]
私人风险值得分=0{
迪塞特{
///如果在10秒内发生变化,则更新纹理
让bgIndex=分数/10
如果((bgIndex>oldValue/10)和&scoreclass GameScene: SKScene {

    private var score = 0 {
        didSet {
             ///if a change in the 10s happen,  then update texture
             if(score/10 > oldValue/10)
             {
                 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: "greenbackground")
                     default: break
                 }
            }
        }
    }
    private var shouldUpdateTexture = false
    private var backgroundNode = SKSpriteNode(imageNamed: "defaultbackground")



}
class GameScene: SKScene {
    let bgTextures = [SKTexture(imageNamed: "orangebackground"),SKTexture(imageNamed: "yellowbackground"),SKTexture(imageNamed: "greenbackground")]

    private var score = 0 {
        didSet {
             ///if a change in the 10s happen,  then update texture
             let bgIndex = score / 10
             if((bgIndex > oldValue/10) && score < bgTextures.count * 10)
             {
                backgroundNode.texture = bgTextures[bgIndex - 1]
             }
             else
             {
                backgroundNode.texture = bgTextures[bgTextures.count - 1]

             }

        }
    }
    private var shouldUpdateTexture = false
    private var backgroundNode = SKSpriteNode(imageNamed: "defaultbackground")



}