在swift上一次移动多个精灵节点

时间:2014-09-28 07:47:15

标签: swift

我可以制作一个SK节点数组,其中一个是随机选择的,并从屏幕的顶部到底部。例如,假设我有25个左右的不同平台,它们会在人像iPhone上掉下来。我需要它从数组中随机选择一个平台开始,然后在一定的时间/或像素空间后随机选择另一个继续相同的动作,直到到达底部等。我是新的快速但有一个相当不错的了解它。我还没有找到如何创建一个SKsprite节点数组。有人可以帮忙吗?

到目前为止,我能够获得类似于我想要的任何效果的唯一方法是将每个节点放在屏幕上并将它们添加到字典中并使它们移动像这样

类ObstacleStatus {

    var isMoving = false
    var timeGapForNextRun = Int(0)
    var currentInterval = Int(0)
    init(isMoving: Bool, timeGapForNextRun: Int, currentInterval: Int) {
        self.isMoving = isMoving
        self.timeGapForNextRun = timeGapForNextRun
        self.currentInterval = currentInterval
}

func shouldRunBlock() -> Bool {
    return self.currentInterval >  self.timeGapForNextRun

}

func moveBlocks(){
    for(blocks, ObstacleStatus) in self.blockStatuses {
        var thisBlock = self.childNodeWithName(blocks)
        var thisBlock2 = self.childNodeWithName(blocks)
        if ObstacleStatus.shouldRunBlock() {
            ObstacleStatus.timeGapForNextRun = randomNum()
            ObstacleStatus.currentInterval = 0
            ObstacleStatus.isMoving = true
        }

        if ObstacleStatus.isMoving {
            if thisBlock?.position.y > blockMaxY{
                    thisBlock?.position.y -= CGFloat(self.fallSpeed)
            }else{
                thisBlock?.position.y = self.origBlockPosistionY
                ObstacleStatus.isMoving = false
            }
        }else{
                ObstacleStatus.currentInterval++
            }

    }
}

将此用作随机函数

func randomNum() -> Int{
 return randomInt(50, max: 300)        
}

func randomInt(min: Int, max:Int) -> Int {
    return min + Int(arc4random_uniform(UInt32(max - min + 1)))
}

所有这一切对我来说都是以随机的时间间隔向下移动碎片,经常与它们重叠,但增加随机数的最小值或最大值并不会对间隙的实际时间产生影响。我需要能够指定距离或时间间隔。

1 个答案:

答案 0 :(得分:1)

许多可能的解决方案之一是创建一个递归动作序列,它递归调用自己,直到不再有平台节点为止。你可以控制平均值"间隔时间"及其随机变化的范围。这是一个工作示例(假设iOS SpriteKit游戏模板):

import SpriteKit

extension Double {
    var cg: CGFloat { return CGFloat(self) }
}

extension Int {
    var cg: CGFloat { return CGFloat(self) }
}

func randomInt(range: Range<Int>) -> Int {
    return range.startIndex + Int(arc4random_uniform(UInt32(range.endIndex - range.startIndex)))
}

extension Array {
    func randomElement() -> Element? {
        switch self.count {
        case 0: return nil
        default: return self[randomInt(0..<self.count)]
        }
    }

    func apply<Ignore>(f: (T) -> (Ignore)) {
        for e in self { f(e) }
    }
}

class GameScene: SKScene {

    var screenWidth: CGFloat { return UIScreen.mainScreen().bounds.size.width }
    var screenHeight: CGFloat { return UIScreen.mainScreen().bounds.size.height }

    let PlatformName = "Platform"
    let FallenPlatformName = "FallenPlatform"

    func createRectangularNode(#x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat) -> SKShapeNode {
        let rect = CGRect(x: x, y: y, width: width, height: height)
        let path = UIBezierPath(rect: rect)
        let node = SKShapeNode(path: path.CGPath)
        return node
    }

    func createPlatformNodes(numNodes: Int, atHeight: CGFloat) -> [SKShapeNode] {
        var padding = 20.cg
        let width = (screenWidth - padding) / numNodes.cg - padding
        padding = (screenWidth - width * numNodes.cg) / (numNodes.cg + 1)
        let height = width / 4
        var nodes = [SKShapeNode]()
        for x in stride(from: padding, to: numNodes.cg * (width + padding), by: width + padding) {
            let node = createRectangularNode(x: x, y: atHeight, width: width, height: height)
            node.fillColor = SKColor.blackColor()
            node.name = PlatformName
            nodes.append(node)
        }
        return nodes
    }

    func createFallingAction(#by: CGFloat, duration: NSTimeInterval, timeGap: NSTimeInterval, range: NSTimeInterval = 0) -> SKAction {
        let gap = SKAction.waitForDuration(timeGap, withRange: range)
//      let fall = SKAction.moveToY(toHeight, duration: duration) // moveToY appears to have a bug: behaves as moveBy
        let fall = SKAction.moveByX(0, y: -by, duration: duration)
        let next = SKAction.customActionWithDuration(0) { [unowned self]
            node, time in
            node.name = self.FallenPlatformName
            self.fallNextNode()
        }
        return SKAction.sequence([gap, fall, next])
    }

    func fallNextNode() {
        if let nextNode = self[PlatformName].randomElement() as? SKShapeNode {
            let falling = createFallingAction(by: screenHeight * 0.7, duration: 1, timeGap: 2.5, range: 2) // mean time gap and random range
            nextNode.runAction(falling)
        } else {
            self.children.apply { ($0 as? SKShapeNode)?.fillColor = SKColor.redColor() }
        }
    }

    override func didMoveToView(view: SKView) {
        self.backgroundColor = SKColor.whiteColor()
        for platform in createPlatformNodes(7, atHeight: screenHeight * 0.8) {
            self.addChild(platform)
        }
        fallNextNode()
    }
}