Spawn SKSpriteNode объекты в случайное время - PullRequest
0 голосов
/ 12 марта 2019

Я создаю игру, в которой я хотел бы создавать препятствия в случайное время. Препятствия будут вступать в контакт с игроком.

Вот код, который у меня есть:

var obstacle : SKSpriteNode?

func createObstacles() {
let obstaclesArray = ["obstacle_1", "obstacle_2", "obstacle_3", "obstacle_4", "obstacle_5"]
let randomObs = obstaclesArray.randomElement()
let selectedTexture = SKTexture(imageNamed: randomObs!)
obstacle = SKSpriteNode(imageNamed: randomObs!)
obstacle?.physicsBody = SKPhysicsBody(texture: selectedTexture, size: selectedTexture.size())
obstacle?.position = CGPoint(x: scene!.size.width/2 + selectedTexture.size().width, y: -120)
obstacle?.zPosition = -15
if let obs = obstacle?.physicsBody {
obs.affectedByGravity = true
obs.allowsRotation = false
obs.isDynamic = true
obs.restitution = 0
obs.categoryBitMask = obstacleCategory
obs.collisionBitMask = floorCategory
obs.contactTestBitMask = heroCategory
}
addChild(obstacle!)
}

func spawnObstacles() {
let wait = SKAction.wait(forDuration: 1, withRange: 0.4)
let spawn = SKAction.run {
createObstacles()
}
let moveLeft = SKAction.moveBy(x: -scene!.size.width - obstacle.size.width - 10, y: 0, duration: 2)
let sequence = SKAction.sequence([wait, spawn, moveLeft, SKAction.removeFromParent()])
self.run(SKAction.repeatForever(sequence))
}

Я прочитал несколько похожих вопросов, но ответ - мой код, но он не работает. Создание узла Spritekit в произвольное время

Я тоже пробовал другой способ:

var randDelay = Double.random(in: 0.7 ..< 1.4)
DispatchQueue.main.asyncAfter(deadline: randDelay, execute: {
    if self.canCreateObstacle == true {
    self.spawnObstacle()
    }})

Но это не работает, и каждый раз, когда я перезагружаю игру, кажется, что функция вызывается два раза, если я перезагружаю игру в третий раз, она вызывается 3 раза и так далее.

Кто-нибудь с хорошим и чистым решением для порождения объектов в случайное время?

1 Ответ

0 голосов
/ 12 марта 2019

Не использовать DispatchQueue Настройте повторяющееся последовательное действие, используя wait(forDuration:withRange:), как вы делали ранее.

https://developer.apple.com/documentation/spritekit/skaction/1417760-wait

Сначала создайте общий узел, используемый для появления препятствий,затем присоедините этот общий узел к сцене.
Наконец, назначьте повторяющееся последовательное действие этому узлу.Boom, все готово.

Причина, по которой вы хотите назначить его случайному узлу, заключается в том, что вы хотите, чтобы ваша игра имела возможность перестать генерировать препятствия, а также изменили свойство скорости, чтобыузел генерирует узлы быстрее или медленнее.

Вы также хотите отделить порождение / ожидание от перемещения / уничтожения, потому что на данный момент ваш код запутан.Вы говорите, что переместите сцену влево на 2 секунды, затем подождите случайное количество времени, чтобы вызвать следующего врага, но я думаю, что вы пытаетесь просто вызвать врагов на некотором интервале времени и переместить противника влево.

Ваш код сцены должен выглядеть примерно так

class GameScene : SKScene{
    let obstacleGenerator = SKNode()
    func didMove(to: view){


        let wait = SKAction.wait(forDuration: 1, withRange: 0.4)
        let spawn = SKAction.run({createObstacles()})

        let sequence = SKAction.sequence([wait, spawn])
        obstacleGenerator.run(SKAction.repeatForever(sequence))
        addChild(obstacleGenerator)

    }

    func createObstacles() {
        let obstaclesArray = ["obstacle_1", "obstacle_2", "obstacle_3", "obstacle_4", "obstacle_5"]
        let randomObs = obstaclesArray.randomElement()
        let selectedTexture = SKTexture(imageNamed: randomObs!)
        obstacle = SKSpriteNode(imageNamed: randomObs!)

        obstacle.position = CGPoint(x: scene!.size.width/2 + selectedTexture.size().width, y: -120)
        obstacle.zPosition = -15
        let body = SKPhysicsBody(texture: selectedTexture, size: selectedTexture.size())
        body.affectedByGravity = true
        body.allowsRotation = false
        body.isDynamic = true
        body.restitution = 0
        body.categoryBitMask = obstacleCategory
        body.collisionBitMask = floorCategory
        body.contactTestBitMask = heroCategory
        obstacle.physicsBody = body
        addChild(obstacle!)
        let moveLeft = SKAction.moveBy(x: -scene!.size.width - obstacle.size.width - 10, y: 0, duration: 2)
        let seq = SKAction.sequence([moveLeft,SKAction.removeFromParent()])
        obstacle.run(seq)
    }
}

Теперь, что касается увеличения вашего нереста с каждым сбросом, вы никогда не сообщаете, как вы сбрасываете.Я собираюсь предположить, что вы никогда не удаляете предыдущее действие после сброса, и именно поэтому ваша скорость увеличивается.Всегда лучше просто создать новый экземпляр GameScene при выполнении сброса.

...