swift - 随机生成两个节点

标签 swift sprite-kit

我正在 Swift 3 的 SpriteKit 中创建一个移动应用程序。我正在尝试创建角色必须躲避的两 block 岩石。我有随机生成 ->

func createTopRock(){
    var topRockChoice = [SKTexture(image: #imageLiteral(resourceName: "rockDown")), SKTexture(image: #imageLiteral(resourceName: "rockGrassDown")), SKTexture(image: #imageLiteral(resourceName: "rockSnowDown")), SKTexture(image: #imageLiteral(resourceName: "rockIceDown"))]

    let topRock = SKSpriteNode.init(texture: topRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    topRock.zPosition = -9
    topRock.name = "TopRock"
    topRock.position = CGPoint(x: self.frame.width + topRock.size.width * 2, y: frame.maxY - topRock.frame.height / 2)

    topRock.physicsBody = SKPhysicsBody(texture: topRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    topRock.physicsBody?.categoryBitMask = physicsCatagory.topRock
    topRock.physicsBody?.collisionBitMask = physicsCatagory.plane
    topRock.physicsBody?.contactTestBitMask = physicsCatagory.plane
    topRock.physicsBody?.affectedByGravity = false
    topRock.physicsBody?.isDynamic = false

    self.addChild(topRock)

    let randomNumTop = arc4random_uniform(3) + 3

    spawnDelayForeverTop = Timer.scheduledTimer(timeInterval: TimeInterval(randomNumTop), target: self, selector: #selector(self.createTopRock), userInfo: nil, repeats: false)
}

func createBtmRock(){
    var btmRockChoice = [SKTexture(image: #imageLiteral(resourceName: "rock")), SKTexture(image: #imageLiteral(resourceName: "rockGrass")), SKTexture(image: #imageLiteral(resourceName: "rockSnow")), SKTexture(image: #imageLiteral(resourceName: "rockIce"))]

    let btmRock = SKSpriteNode.init(texture: btmRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    btmRock.zPosition = -9
    btmRock.position = CGPoint(x: self.frame.width, y: frame.minY + btmRock.frame.height / 2)
    btmRock.name = "BtmRock"

    btmRock.physicsBody = SKPhysicsBody(texture: btmRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    btmRock.physicsBody?.categoryBitMask = physicsCatagory.topRock
    btmRock.physicsBody?.collisionBitMask = physicsCatagory.plane
    btmRock.physicsBody?.contactTestBitMask = physicsCatagory.plane
    btmRock.physicsBody?.affectedByGravity = false
    btmRock.physicsBody?.isDynamic = false

    self.addChild(btmRock)

    let randomNumBtm = arc4random_uniform(2) + 1

    spawnDelayForeverBtm = Timer.scheduledTimer(timeInterval: TimeInterval(randomNumBtm), target: self, selector: #selector(createBtmRock), userInfo: nil, repeats: false)
}

正如您从代码中看到的,一切正常。我不想做的一件事是让它像 Flappy Bird 一样,并使 btmRocktopRock 具有相同的位置,因此为了防止我添加了 timeIntervals 不同。这在一定程度上是有效的;但玩家仍然会遇到一些几乎不可能穿过的岩石。

enter image description here

我觉得我的做法是错误的,而且我不知道如何解决这个问题。我希望他们有时足够接近,很难,但并非几乎不可能。当我尝试实现一个 bool 系统时,当顶部岩石被创建并且在一定距离内时,不会创建底部岩石。我在尝试这样做时遇到的问题是,在那件事发生之后我再也没有底气了。提前致谢。

最佳答案

就我个人而言,我不会在我的 SpriteKit 游戏中使用计时器(原因你可以在 SO 中找到)。一个非常简单的解决方案可能是从 Update 函数中调用岩石的生成。

我还会创建一个基础底部岩石和基础顶部岩石,并根据需要复制它,因为动态创建物理对象可能会很昂贵(或者我会在开始时创建一个对象数组并从数组中提取)根据需要)

附注这是我即兴写下的,所以我不能保证不存在拼写错误;)

var genInterval = 4  //How many seconds between rocks on bottom or top (not between top & bottom. that will be half of this value)
var genOffset = genInterval / 2  //offset the bottom rocks half of the interval so that they do't line up
var bottomRock: SKSpriteNode!  //your base bottom rock for copying
var topRock: SKSpriteNode!  //your base top rock for copying
var updateTopTime: Double = 0
var updateBottomTime: Double = 0

func setupRocks() {

    //create the base bottom rock
    var btmRockChoice = [SKTexture(image: #imageLiteral(resourceName: "rock")), SKTexture(image: #imageLiteral(resourceName: "rockGrass")), SKTexture(image: #imageLiteral(resourceName: "rockSnow")), SKTexture(image: #imageLiteral(resourceName: "rockIce"))]

    bottomRock = SKSpriteNode(texture: btmRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    btmRock.zPosition = -9
    btmRock.position = CGPoint(x: self.frame.width, y: frame.minY + btmRock.frame.height / 2)
    btmRock.name = "BtmRock"

    btmRock.physicsBody = SKPhysicsBody(texture: btmRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    btmRock.physicsBody?.categoryBitMask = physicsCatagory.topRock
    btmRock.physicsBody?.collisionBitMask = physicsCatagory.plane
    btmRock.physicsBody?.contactTestBitMask = physicsCatagory.plane
    btmRock.physicsBody?.affectedByGravity = false
    btmRock.physicsBody?.isDynamic = false

    //create the base top rock
    var topRockChoice = [SKTexture(image: #imageLiteral(resourceName: "rockDown")), SKTexture(image: #imageLiteral(resourceName: "rockGrassDown")), SKTexture(image: #imageLiteral(resourceName: "rockSnowDown")), SKTexture(image: #imageLiteral(resourceName: "rockIceDown"))]

    topRock = SKSpriteNode(texture: topRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    topRock.zPosition = -9
    topRock.name = "TopRock"
    topRock.position = CGPoint(x: self.frame.width + topRock.size.width * 2, y: frame.maxY - topRock.frame.height / 2)

    topRock.physicsBody = SKPhysicsBody(texture: topRockChoice[mapChoice], size: CGSize(width: (self.scene?.size.width)! / 10,  height: (self.scene?.size.height)! / 2.2))
    topRock.physicsBody?.categoryBitMask = physicsCatagory.topRock
    topRock.physicsBody?.collisionBitMask = physicsCatagory.plane
    topRock.physicsBody?.contactTestBitMask = physicsCatagory.plane
    topRock.physicsBody?.affectedByGravity = false
    topRock.physicsBody?.isDynamic = false
}

override func update(_ currentTime: CFTimeInterval) {

    //optional prevents generation if game is not playing
    guard gameState == .playing else { return }

    if updateTopTime == 0 {
        updateTopTime = currentTime
    }

    if updateBottomTime == 0 {
        updateBottomTime = currentTime
    }

    if currentTime - updateBottomTime > genOffset {
        createBtmRock()
        genOffset = genInterval
        updateBottomTime = currentTime
    }
    else if currentTime - updateTopTime > genInterval {  
        createTopRock()
        updateTopTime = currentTime
    }
}

func createTopRock() {

    //You can make this number a class variable to increase the rate as the game progresses
    let randomNum = arc4random_uniform(3)

    //there is a 1 in 3 chance that this rock will get created
    if randomNum == 1 {

        let rock = topRock.copy as! SKSpriteNode()
        self.addChild(rock)
    }
}

func createBtmRock() {

    //You can make this number a class variable to increase the rate as the game progresses
    let randomNum = arc4random_uniform(2)

    //there is a 1 in 2 chance that this rock will get created
    if randomNum == 0 {

        let rock = bottomRock.copy as! SKSpriteNode()
        self.addChild(rock)
    }
}

关于swift - 随机生成两个节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46120401/

相关文章:

ios - 奇怪的 SpriteKit 帧速率下降 - 怀疑挥之不去的 SKPhysicsBody 实例

swift - UIAlertAction 背景颜色

swift - 为什么 iOS 实时照片的视频尺寸比照片小

ios - 使用 UITapGestureRecognizer 更改标签颜色

swift - SKAudioNode 播放一次声音

swift3 - 如何检查带有 key 的特定 SKAction 是否正在运行

ios - Sprite Kit 可用性 Pre iOS 7

ios - 使枚举数组符合 Hashable 以用作字典键

json - 使用 Swift 4 和 Xcode 9 获取 JSON 数据

swift - SpriteKit & Swift : How to create level "segments" that are randomly "stitched" together to create an endless game?