ios - 如何在iOS SpriteKit中的每个精灵之间延迟将脉冲应用于组的所有精灵?

问题描述

我正在 Xcode 中为 iOS 制作一个砖块破坏风格的游戏。没有桨,球都是从同一位置发射的(由第一个球从最后一层落下的位置决定)。根据玩家创造的球数量,每次发射不同数量的球。每场比赛都从一个球开始,但用户在玩游戏时会收集更多。当对球精灵施加脉冲时,我只能同时移动一个精灵或所有球精灵。如何在每次精灵启动之间延迟移动球精灵?

下面我将回顾我已经尝试过的内容。在此先感谢您的帮助!

到目前为止,我已经尝试了几件事。首先,我试图在允许用户启动并将所有球精灵放在同一位置之前创建所有球精灵。然后我列举了它们并试图在那里延迟启动它们。然而,这只是在延迟后同时发射所有球,而不是单独发射。

gameWorldNode.enumerateChildNodes(withName: BallCategoryName) {
     node,stop in
     let ball = node as! SKSpriteNode
     ball.move(toParent: gameWorldNode)
                    
     //Calculate Vector
     var dx = CGFloat(touchLocation.x - ball.position.x)
     var dy = CGFloat(touchLocation.y - ball.position.y)
                    
     //Calculate Magnitude
     let magnitude = sqrt(dx * dx + dy * dy)
                    
     dx /= magnitude
     dy /= magnitude
                    
     //Create Vector
     let vector = CGVector(dx: 30.0 * dx,dy: 30.0 * dy)
                    
     let secondsToDelay = 0.25
     dispatchQueue.main.asyncAfter(deadline: .Now() + secondsToDelay){       
          //Apply impulse
           ball.physicsBody!.applyImpulse(vector)
                
     }

}

其次,我突然想到,如果我在施加脉冲之前、前一个球发射之后才创建球精灵,可能会更好地提高游戏性能。所以我尝试了以下代码。然而,虽然我认为我现在可能走在正确的道路上,但新创建的球精灵没有启动。他们被创造出来,但出于某种原因,他们没有应用冲动。

let ball = gameWorldNode.childNode(withName: BallCategoryName) as! SKSpriteNode
ball.move(toParent: gameWorldNode)

//Calculate Vector
var dx = CGFloat(touchLocation.x - ball.position.x)
var dy = CGFloat(touchLocation.y - ball.position.y)

//Calculate Magnitude
let magnitude = sqrt(dx * dx + dy * dy)

dx /= magnitude
dy /= magnitude

//Create Vector
let vector = CGVector(dx: 30.0 * dx,dy: 30.0 * dy)

ball.physicsBody!.applyImpulse(vector)

var i = 1
while (i != ballsAvailabe) {
    //Create new ball sprite
    let nextBall: SKSpriteNode = Ball()
    nextBall.position = CGPoint(x: locationX,y: locationY)
    gameWorldNode.addChild(nextBall)

    let secondsToDelay = 0.1
    dispatchQueue.main.asyncAfter(deadline: .Now() + secondsToDelay) {
        //Apply impulse to ball
        nextBall.physicsBody!.applyImpulse(vector)
    }
    //Update i
    i += 1
}

我还尝试将精灵添加到数组中并遍历该数组。然而,这只是一次发射每个球。

for _ in 0..<ballsAvailabe {
    //Create new ball sprite
    let ball: SKSpriteNode = Ball()
    ball.position = CGPoint(x: locationX,y: locationY)
    ball.physicsBody!.categoryBitMask = nextBallCategory
    ball.color = nextBallInPlay
    ball.colorBlendFactor = 1
    ball.physicsBody!.contactTestBitMask = BottomCategory | AddABallCategory | RedBlockCategory | BlueBlockCategory | OrangeBlockCategory | PurpleBlockCategory | GreenBlockCategory | CyanBlockCategory
    ballSprites.append(ball)
    gameWorldNode.addChild(ball)
}
                
  for sprite in ballSprites {
       let secondsToDelay = 0.3
       dispatchQueue.main.asyncAfter(deadline: .Now() + secondsToDelay)      {
            sprite.physicsBody!.applyImpulse(vector)
        }
    }

编辑: 遵循下面的约翰评论,我在第二次尝试中添加代码,以确保正确创建物理体。抱歉,代码中的所有变量都是我创建的全局变量,并保存在自己的文件中,以确保我在整个代码中保持值一致。这效果更好。当用户只有一个球时,它可以完美地工作。但是,当用户收集更多要发射的球时,它有时会延迟到预期位置而完美发射。其他时候它只会发射第一个球。其他时候它会发射到一个意想不到的位置。

这是更新的代码

//Grab existing ball object
 let ball = gameWorldNode.childNode(withName: BallCategoryName) as! SKSpriteNode
                
//Assign to game world node
ball.move(toParent: gameWorldNode)
                
//Apply ball properties
ball.color = nextBallInPlay
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width / 2)
ball.physicsBody!.categoryBitMask = RedBallCategory
ball.name = BallCategoryName
ball.colorBlendFactor = 1
ball.physicsBody?.pinned = false
ball.physicsBody?.mass = ballMass
ball.physicsBody?.affectedByGravity = ballGravity
ball.physicsBody?.allowsRotation = ballRotation
ball.physicsBody?.isDynamic = ballDynamic
ball.zPosition = ballZPos
ball.physicsBody?.friction = ballFriction
ball.physicsBody?.restitution = ballRestitution
ball.physicsBody?.lineardamping = ballLineardaming
ball.physicsBody?.angulardamping = ballAngulardamping
                 
//Stop more launches and accidently using power ups
isFingerOnScreen = true
canBallBeLaunched = false
canUsePowerUps = false
                
//Ensure physics world speed is accurate
physicsWorld.speed = 1
                
//Launching location
var dx = CGFloat(touchLocation.x - locationX)
var dy = CGFloat(touchLocation.y - locationY)
                
//Calculate Magnitude
let magnitude = sqrt(dx * dx + dy * dy)
                
dx /= magnitude
dy /= magnitude
                
//Create Vector
let vector = CGVector(dx: 30.0 * dx,dy: 30.0 * dy)
                
//Apply impule to first ball
ball.physicsBody!.applyImpulse(vector)

//loop to create x number of balls based on what the user has collected
var i = 1
while (i != ballsAvailabe) {
    //Create new ball sprite
    let nextBall: SKSpriteNode = Ball()
    nextBall.position = CGPoint(x: locationX,y: locationY)
    gameWorldNode.addChild(nextBall)
                    
    //Ball properties
    nextBall.color = nextBallInPlay
    nextBall.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.width / 2)
    nextBall.physicsBody!.categoryBitMask = RedBallCategory
    nextBall.name = BallCategoryName
    nextBall.colorBlendFactor = 1
    nextBall.physicsBody?.pinned = false
    nextBall.physicsBody?.mass = ballMass
    nextBall.physicsBody?.affectedByGravity = ballGravity
    nextBall.physicsBody?.allowsRotation = ballRotation
    nextBall.physicsBody?.isDynamic = ballDynamic
    nextBall.zPosition = ballZPos
    nextBall.physicsBody?.friction = ballFriction
    nextBall.physicsBody?.restitution = ballRestitution
    nextBall.physicsBody?.lineardamping = ballLineardaming
    nextBall.physicsBody?.angulardamping = ballAngulardamping

    //Delay between each ball
    let secondsToDelay = 0.1
    dispatchQueue.main.asyncAfter(deadline: .Now() + secondsToDelay) {
         //Apply impulse to ball
         nextBall.physicsBody!.applyImpulse(vector)
    }
    //Update i
    i += 1
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)