SKSpriteNode 在 GameScene 中消失

SKSpriteNode disappear in GameScene

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

我一直在密切关注在线教程(将不同的教程组合到一个项目中),当我意识到我的 SKSpriteNodes(我的 "player" 和 "enemy")时尝试了代码 有时 在模拟器或我的 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()   
}

您的精灵未显示的问题是 none 您的对象设置了 zPosition。您需要按照您希望对象在场景中显示的方式对对象进行分层。

例如...

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

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

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

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

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