SKSpriteNode 在 GameScene 中消失

Posted

技术标签:

【中文标题】SKSpriteNode 在 GameScene 中消失【英文标题】:SKSpriteNode disappear in GameScene 【发布时间】:2018-03-20 08:56:50 【问题描述】:

我在 swift 中遇到了 spritekit 的一些问题。

我密切关注在线教程(将不同的教程组合到一个项目中),当我意识到我的 SKSpriteNodes(我的“玩家”和“敌人”)时尝试了代码有时 当我在模拟器或我的 iPhone 上试用它时丢失了。

我的情况有点类似于这位用户的问题here,但我认为我的问题不在于尺寸。

有人能告诉我吗?谢谢!

这是我的代码。

var player : SKSpriteNode!
var backdrop : SKSpriteNode!
var gameTimer : Timer!
var possibleEnemies = ["enemy01", "enemy02", "enemy03"]
let bulletsCategory : UInt32 = 0x1 << 0
let enemyCategory : UInt32 = 0x1 << 1

override func didMove(to view: SKView) 

    player = SKSpriteNode(imageNamed: "bird.png")
    player.position = CGPoint(x: 0, y: (player.size.height / 2) )

    self.addChild(player)

    self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
    self.physicsWorld.contactDelegate = self
    self.anchorPoint = CGPoint (x: 0.5 , y: 0)

    createBackdrop()

    scoreLabel = SKLabelNode(text: "Score: 0")
    scoreLabel.position = CGPoint(x: 260, y: self.frame.size.height - 90)
    scoreLabel.fontName = "Avenir Book"
    scoreLabel.fontSize = 35
    scoreLabel.fontColor = UIColor.gray
    score = 0

    self.addChild(scoreLabel)

    gameTimer = Timer.scheduledTimer(timeInterval: 0.75, target: self, selector: #selector(addEnemies), userInfo: nil, repeats: true)


@objc func addEnemies() 

    possibleEnemies = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: possibleEnemies) as! [String]

    let enemy = SKSpriteNode(imageNamed: possibleEnemies[0])

    let randomEnemyPosition = GKRandomDistribution(lowestValue: -360, highestValue: 360)
    let position = CGFloat(randomEnemyPosition.nextInt())

    enemy.position = CGPoint(x: position, y: self.frame.size.height + enemy.size.height)

    enemy.physicsBody = SKPhysicsBody(rectangleOf: enemy.size)
    enemy.physicsBody?.isDynamic = true
    enemy.physicsBody?.categoryBitMask = enemyCategory
    enemy.physicsBody?.contactTestBitMask = bulletsCategory
    enemy.physicsBody?.collisionBitMask = 0

    self.addChild(enemy)

    let animationDuration : TimeInterval = 6

    var actionArray = [SKAction]()
    actionArray.append(SKAction.move(to: CGPoint(x: position, y: -enemy.size.height), duration: animationDuration))
    actionArray.append(SKAction.removeFromParent())

    enemy.run(SKAction.sequence(actionArray))


override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) 
    fireBullets()


func fireBullets() 

    self.run(SKAction.playSoundFileNamed("shoot.wav", waitForCompletion: false))

    let bullets = SKSpriteNode(imageNamed: "bullet.png")
    bullets.position = player.position
    bullets.position.y += 5
    bullets.physicsBody = SKPhysicsBody(rectangleOf: bullets.size)
    bullets.physicsBody?.isDynamic = true

    bullets.physicsBody?.categoryBitMask = bulletsCategory
    bullets.physicsBody?.contactTestBitMask = enemyCategory
    bullets.physicsBody?.collisionBitMask = 0
    bullets.physicsBody?.usesPreciseCollisionDetection = true

    self.addChild(bullets)

    let animationDuration : TimeInterval = 0.3

    var actionArray = [SKAction]()
    actionArray.append(SKAction.move(to: CGPoint(x: player.position.x, y: self.frame.size.height + 10), duration: animationDuration))
    actionArray.append(SKAction.removeFromParent())

    bullets.run(SKAction.sequence(actionArray)) 


func didBegin(_ contact: SKPhysicsContact) 

    var firstBody : SKPhysicsBody
    var secondBody: SKPhysicsBody

    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask 
        firstBody = contact.bodyA
        secondBody = contact.bodyB
     else 
        firstBody = contact.bodyB
        secondBody = contact.bodyA
    

    if (firstBody.categoryBitMask & bulletsCategory) != 0 && (secondBody.categoryBitMask & enemyCategory) != 0 

        hitByBullets(bulletNode: firstBody.node as! SKSpriteNode, enemyNode: secondBody.node as! SKSpriteNode)  
     


func hitByBullets (bulletNode: SKSpriteNode, enemyNode: SKSpriteNode) 

    let shot = SKEmitterNode(fileNamed: "Magic01")!
    shot.position = enemyNode.position
    self.addChild(shot)

    self.run(SKAction.playSoundFileNamed("shot.mp3", waitForCompletion: false))

    bulletNode.removeFromParent()
    enemyNode.removeFromParent()

    self.run(SKAction.wait(forDuration: 2)) 
        shot.removeFromParent()
    

    score += 1 


func touchDown(atPoint pos : CGPoint)   
    player.position = pos 


override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)  
    for t in touches  self.touchDown(atPoint: t.location(in: self))  


override func update(_ currentTime: TimeInterval) 
    // Called before each frame is rendered

    moveBackdrop()   

【问题讨论】:

我从来没有在 SpriteKit 中使用过touchDown - 你确定你需要它并且不能在touchesBegan 中使用它吗?如果你有一个精灵“失踪”,一个好技巧是在updatetouchesBegan或类似的地方打印它的位置——然后你就会知道它是否真的从场景中消失了,或者以某种方式被移动到你不能移动的地方看见。另外,它的zPosition 是否意味着它落后于其他东西? 【参考方案1】:

你的精灵没有出现的问题是你的对象都没有设置 zPosition。您需要按照您希望它们在场景中显示的方式对对象进行分层。

例如...

background.zPosition = 1
player.zPosition = 1
enemy.zPosition = 1
bullet.zPosition = 2
scoreLabel.zPosition = 100

在我看来,您不应该使用计时器来生成敌人。 Spritekit 在更新功能中内置了自己的计时功能。您已经在使用它来控制背景的时间。

您的问题中有很多代码,您需要查看我如何将代码调整为仅与您的问题相关的代码。在您的问题中包含所有代码实际上使您更不可能获得所需的帮助或答案,因为更难通过所有代码来弄清楚发生了什么。此外,在滚动数百行的问题中不要在代码中包含这么多空格,即使其中很多是空格也是非常乏味的。

【讨论】:

【参考方案2】:

没有意识到 zPosition 的重要性,因为我的项目有时会完美地显示在屏幕上。在各自的位置添加了以下内容,它们会间歇性地停止消失。

player.zPosition = 3
scoreLabel.zPosition = 100
enemy.zPosition = 3
bullets.zPosition = 2
backdrop.zPosition = 1
shot.zPosition = 3

【讨论】:

以上是关于SKSpriteNode 在 GameScene 中消失的主要内容,如果未能解决你的问题,请参考以下文章

SKSpriteNode 在 GameScene 中消失

SKSpriteNode 不显示

如何检查两个 SKSpriteNode 是不是彼此靠近?

SKScene - 如何从 SKSpriteNode 获取类

SKSpriteNode 不会居中

使 SKSpriteNode 透明