精灵怎么开始闪烁?

时间:2016-08-12 02:21:23

标签: swift sprite-kit

所以我创造了一个游戏,你可以点击它让它们跳起来。你得到每个点击点。当我达到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")
    }

}

看到这个,看看我的意思。(点击或点击链接)

This shows the sprites flashing at 10 points

提前感谢,乔丹

3 个答案:

答案 0 :(得分:4)

您可以向update添加属性观察器,而不是更改score中的背景图像,只有在分数达到特定值时才会更改背景。例如:

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

也就是说,闪烁可能是由渲染节点的顺序引起的。来自Apple的文档,

  

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

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

self.backgroundNode.zPosition = -100

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

答案 1 :(得分:3)

因为这个而闪烁

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时,您正在更新纹理 EVERY FRAME

这绝对是错误的。

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

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

你怎么能这样做?

只需创建shouldUpdateTexture: Bool = false属性,然后每次更新score时,如果score从9到10或19到20或29到30,那么转{{1}转到shouldUpdateTexture

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

完整代码

false

那就是它。

更新

正如 @ Knight0fDragon 指出的那样,将我放入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) { if shouldUpdateTexture { 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 } } } } 方法的代码移动到update可能会更快。

  

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

     

缺点:如果您在同一帧内多次更改didSet值,则会执行多次纹理加载。

答案 2 :(得分:2)

只是一种替代方案,允许在分数中发生多项更改,而不会使用不必要的代码充斥更新功能

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



}