随机生成两个节点

时间:2017-09-08 15:57:30

标签: swift sprite-kit

我正在Swift 3的SpriteKit中创建一个移动应用程序。我试图创造一个角色必须躲闪的两块岩石。我随机生成了 - >

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系统用于创建顶部岩石并且在一定距离内时,不要创建底部岩石。我试图做到这一点的原因是,在那之后我永远不会有底石。提前致谢。

2 个答案:

答案 0 :(得分:1)

最后一段中的逻辑似乎是一个合理的解决方案。您需要实现某种自定义逻辑,以防止顶部和底部岩石在某个设定距离内产生。

createBtmRock功能中,当您设置新摇滚的位置时,请检查它是否靠近任何现有的顶部岩石。您可以通过比较新岩石的position属性与所有现有岩石来确定贴近度。

如果您发现新岩石太靠近现有岩石,请不要将新岩石添加到场景中,并继续计时以确保将来生成底部岩石。

这是解决您眼前问题的简单方法。您可能希望研究用于生成岩石的程序生成策略。如果你想稍后改进行为(例如,在游戏进行过程中让岩石更难通过),你将需要一个更持久的解决方案。

考虑创建一个单独的函数,为您的岩石生成位置。您可以单独处理所有位置生成逻辑,并使用结果来定位您的岩石。

func generateRockPositions() -> [CGPoint]

您可以在用户启动游戏时提前执行此操作,或在游戏进行时生成位置。这样您就可以更轻松地在将来对程序生成算法进行更改。

希望这对你的游戏有所帮助!

答案 1 :(得分:1)

我个人不会在我的SpriteKit游戏中使用Timer(因为你可以找到所有的SO)。一个非常简单的解决方案可能是从Update func调用岩石的生成。

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

P.S。我把它从袖口上写下来,所以我不能保证拼写错误不存在;)

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)
    }
}