首页 > 解决方案 > SpriteKit Sprite 在应该移动时冻结在屏幕上

问题描述

每隔一段时间,一个精灵就会在屏幕上冻结不动,即使屏幕上的其他精灵会继续你在屏幕上水平移动。我相信这可能与 element.run(SKAction.moveBy(x: moveSpeedFloat, y: 0, duration: 0.25))

我是否更新精灵移动太快?

有没有更好的方法来更新精灵动作?

谢谢,感谢帮助

游戏场景类:

import SpriteKit
import GameplayKit

class GameScene: SKScene {
    
    var gameScore: SKLabelNode!
    var countdownLabel: SKLabelNode!
    var bulletsLeftLabel: SKLabelNode!
    var reloadButton: UIButton!
    
    var slots = [TargetSlot]()
    
    let brownDuckTexture = SKTexture(imageNamed: "brownduck")
    let duckTexture = SKTexture(imageNamed: "duck")
    let frogTexture = SKTexture(imageNamed: "frog")
    let crocodileTexture = SKTexture(imageNamed: "crocodile")
    let posionAppleTexture = SKTexture(imageNamed: "posionapple")
    let targetTexture = SKTexture(imageNamed: "target")
    
    let rowDistribution = GKShuffledDistribution(lowestValue: 1, highestValue: 3)
    let textureDistribution = GKShuffledDistribution(lowestValue: 1, highestValue: 6)
    let moveSpeedDistribution = GKRandomDistribution(lowestValue: 50, highestValue: 100)
    
    var gameInProgress = true
    
    var score = 0 {
        didSet {
            gameScore.text = "Score: \(score)"
        }
    }
    
    var bulletsLeft = 6 {
        didSet {
            bulletsLeftLabel.text = "Bullets: \(bulletsLeft)"
        }
    }
    
    var timer:Timer?
    var timeLeft = 60 {
        didSet {
            countdownLabel.text = "Time: \(timeLeft)"
            if timeLeft <= 0 {
                gameOver()
            }
        }
    }
    
    override func didMove(to view: SKView) {
        
        let background = SKSpriteNode(imageNamed: "251204.png")
        background.position = CGPoint(x: 512, y: 384)
        background.blendMode = .replace
        background.zPosition = -1
        addChild(background)
        
        gameScore = SKLabelNode(fontNamed: "GillSans-Bold")
        gameScore.text = "Score: 0"
        gameScore.position = CGPoint(x: 8, y: 8)
        gameScore.horizontalAlignmentMode = .left
        gameScore.fontSize = 48
        gameScore.zPosition = 1
        addChild(gameScore)
        
        countdownLabel = SKLabelNode(fontNamed: "GillSans-Bold")
        countdownLabel.text = "Time: 0"
        countdownLabel.position = CGPoint(x: 250, y: 8)
        countdownLabel.horizontalAlignmentMode = .left
        countdownLabel.fontSize = 48
        countdownLabel.zPosition = 1
        addChild(countdownLabel)
        
        bulletsLeftLabel = SKLabelNode(fontNamed: "GillSans-Bold")
        bulletsLeftLabel.text = "Bullets: 6"
        bulletsLeftLabel.position = CGPoint(x: 475, y: 8)
        bulletsLeftLabel.horizontalAlignmentMode = .left
        bulletsLeftLabel.fontSize = 48
        bulletsLeftLabel.zPosition = 1
        addChild(bulletsLeftLabel)
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            [weak self] in
            self?.moveTargets()
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
            [weak self] in
            self?.createEnemy()
        }
        
        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(onTimerFires), userInfo: nil, repeats: true)
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        if bulletsLeft <= 0 {
            return
        }
        guard let touch = touches.first else { return }
        let location = touch.location(in: self)
        let tappedNodes = nodes(at: location)
        
        bulletsLeft -= 1
        
        for node in tappedNodes {
            guard let targetSlot = node.parent as? TargetSlot else { return }
            
            if node.name == "good" {
                score += 1
            } else if node.name == "bad" {
                score -= 1
            }
            
            targetSlot.removeEnemy()
            targetSlot.removeFromParent()
            //            print(slots.count)
            let itemToRemove = targetSlot
            if let index = slots.firstIndex(of: itemToRemove){
                slots.remove(at: index)
            }
            //            print(slots.count)
            
        }
    }
    
    func createTarget(at position: CGPoint, row: Int, texture: SKTexture, trait: String, scale: CGFloat, moveSpeed: Int){
        let slot = TargetSlot()
        //        print(position, row, texture, trait, scale)
        slot.configure(at: position, row: row, texture: texture, trait: trait, scale: scale, moveSpeed: moveSpeed)
        addChild(slot)
        slots.append(slot)
    }
    
    func createEnemy(){
        var texture: SKTexture
        var trait: String
        var scale: CGFloat
        var moveSpeed: Int
        //        let randomNum = Int.random(in: 1...6)
        let randomNum = textureDistribution.nextInt()
        switch randomNum {
        case 1:
            texture = brownDuckTexture
            trait = "good"
            scale = 0.2
        case 2:
            texture = duckTexture
            trait = "good"
            scale = 0.2
        case 3:
            texture = frogTexture
            trait = "good"
            scale = 0.4
        case 4:
            texture = crocodileTexture
            trait = "bad"
            scale = 0.3
        case 5:
            texture = posionAppleTexture
            trait = "bad"
            scale = 0.2
        case 6:
            texture = targetTexture
            trait = "bad"
            scale = 0.2
        default:
            return
        }
        
        let randomNumber = rowDistribution.nextInt()
        moveSpeed = moveSpeedDistribution.nextInt()
        switch randomNumber {
        case 1:
            createTarget(at: CGPoint(x: -50, y: 100), row: 1, texture: texture, trait: trait, scale: scale, moveSpeed: moveSpeed)
        case 2:
            createTarget(at: CGPoint(x: 550, y: 200), row: 2, texture: texture, trait: trait, scale: scale, moveSpeed: moveSpeed)
        case 3:
            createTarget(at: CGPoint(x: -50, y: 300), row: 3, texture: texture, trait: trait, scale: scale, moveSpeed: moveSpeed)
        default:
            return
        }
        //        print("created at: \(randomNumber)")
        
        if gameInProgress == true {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
                [weak self] in
                self?.createEnemy()
            }
        }
    }
    
    func moveTargets(){
        for (index, element) in slots.enumerated() {
            if element.position .x >= 1150 || element.position .x <= -650 {
                element.removeEnemy()
                element.removeFromParent()
                slots.remove(at: index)
            } else {
                let moveSpeed: Int = element.moveSpeed
                let moveSpeedNegative: Int = -moveSpeed
                let moveSpeedFloat = CGFloat(moveSpeed)
                let moveSpeedFloatNegative = CGFloat(moveSpeedNegative)
                
                if element.row == 1 || element.row == 3 {
                    element.run(SKAction.moveBy(x: moveSpeedFloat, y: 0, duration: 0.25))
                } else {
                    element.run(SKAction.moveBy(x: moveSpeedFloatNegative, y: 0, duration: 0.25))
                }
            }
        }
        
        if gameInProgress == true {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
                [weak self] in
                self?.moveTargets()
            }
        }
    }
    
    @objc func onTimerFires() {
        timeLeft -= 1
        
        if timeLeft <= 0 {
            timer?.invalidate()
            timer = nil
        }
    }
    
    func gameOver() {
        gameInProgress = false
        
        let gameOver = SKSpriteNode(imageNamed: "gameOver")
        gameOver.position = CGPoint(x: 512, y: 384)
        gameOver.zPosition = 1
        addChild(gameOver)
        
        let finalScoreLabel = SKLabelNode(fontNamed: "GillSans-Bold")
        finalScoreLabel.position = CGPoint(x: 512, y: 300)
        finalScoreLabel.text = "Final Score: \(score)"
        finalScoreLabel.fontSize = 48
        finalScoreLabel.zPosition = 1
        addChild(finalScoreLabel)
    }

    @objc func reloadBullets() {
        
        bulletsLeft = 6
        
    }
}

目标插槽类:

import UIKit
import SpriteKit

class TargetSlot: SKNode {
    var targetNode: SKSpriteNode!
    
    var row: Int!
    var texture: SKTexture!
    var trait: String!
    var scale: CGFloat!
    var moveSpeed: Int!
    

//    func configure(at position: CGPoint, row: Int, texture: SKTexture, triat: String, scale: CGFloat) {
    func configure(at position: CGPoint, row: Int, texture: SKTexture, trait: String, scale: CGFloat, moveSpeed: Int){
        self.position = position
        self.row = row
        self.texture = texture
        self.trait = trait
        self.scale = scale
        self.moveSpeed =  moveSpeed
//        print(position, row, texture, triat, scale)
        targetNode = SKSpriteNode(texture: texture)
        targetNode.name = trait
        targetNode.setScale(scale)
        
        targetNode.position = position
        addChild(targetNode)
    }
    
    func removeEnemy() {
        targetNode.removeFromParent()
        targetNode.removeAllActions()
    }
}

标签: iosswiftsprite-kit

解决方案


推荐阅读