在 Spritekit 上双重生成(和重叠)敌人
double spawning (& overlapping) enemies on Spritekit
我在无休止的 运行 游戏中遇到了麻烦,主要是我创建的两种敌人的生成,有时当我们调用函数时会生成两个敌人 "startDifficultyTimer".
基本上,当我调用该函数时,游戏会在同一行中生成 2 个节点,因此玩家被迫失败,我想避免这种情况,但我不知道如何,我几乎尝试了所有方法,我试图从 didmove 中删除 createsequentialenemy但问题仍然存在,我认为(作为新手)问题出在 startDifficultTimer 函数中,因为当值达到极限时问题就消失了
我已经在下面发布了代码,对于可能存在的巨大错误,我们深表歉意,但我们是 swift 开发游戏的新手,非常感谢大家!
func createEnemy() {
let enemy: Enemy
let duration: CGFloat
switch Int(arc4random() % 100) {
case 0...70:
enemy = Enemy.createEnemy()
duration = CGFloat(Float(arc4random()%1)) + durationV
enemy.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 55, height: 37))
let enemyf = enemy.frame
let fixedx = frame.width + enemy.frame.width/2.0
let positions = [ CGPoint(x: fixedx, y: 383), CGPoint(x: fixedx, y: 447), CGPoint(x: fixedx, y: 511)]
let position = positions[Int(arc4random_uniform(UInt32(positions.count)))]
enemy.position = position
case 71...100:
enemy = Enemy.createEnemyMedium()
duration = CGFloat(Float(arc4random()%1)) + durationV
enemy.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 40, height: 70))
let enemyf = enemy.frame
let fixedx = frame.width + enemy.frame.width/2.0
let positions = [ CGPoint(x: fixedx, y: 415), CGPoint(x: fixedx, y: 479)]
let position = positions[Int(arc4random_uniform(UInt32(positions.count)))]
enemy.position = position
default:
enemy = Enemy.createEnemy()
//type = .small
duration = CGFloat(Float(arc4random()%1)) + durationV
let enemyf = enemy.frame
let fixedx = frame.width + enemy.frame.width/2.0
let positions = [ CGPoint(x: fixedx, y: 383), CGPoint(x: fixedx, y: 447), CGPoint(x: fixedx, y: 511)]
let position = positions[Int(arc4random_uniform(UInt32(positions.count)))]
let texture = SKTexture(imageNamed: "dronea1")
enemy.position = position
}
enemy.physicsBody!.isDynamic = false
enemy.physicsBody!.categoryBitMask = PhysicsCategory.Enemy
addChild(enemy)
let moveTo = SKAction.moveTo(x: 0.0, duration: TimeInterval(duration))
enemy.run(.repeatForever(.sequence([moveTo, .removeFromParent()])))
}
func createSequentialEnemies() {
// remove previous action if running. This way you can adjust the spawn duration property and call this method again and it will cancel previous action.
removeAction(forKey: spawnKey)
let spawnAction = SKAction.run(createEnemy)
let spawnDelay = SKAction.wait(forDuration: spawnDuration)
let spawnSequence = SKAction.sequence([spawnAction, spawnDelay])
run(SKAction.repeatForever(spawnSequence), withKey: spawnKey)later
}
func startDifficultyTimer() {
let difficultyTimerKey = "DifficultyTimerKey"
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run { [unowned self] in
guard self.spawnDuration > 0.5 else { // set a min limit
self.removeAction(forKey: difficultyTimerKey) // if min duration has been reached than you might as well stop running this timer.
return
}
self.spawnDuration -= 0.5 // reduce by half a second
self.createSequentialEnemies() // spawn enemies again
}
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence), withKey: difficultyTimerKey)
}
我认为问题在于您在计时器更改时说 "stop this action"。但是该语句不知道敌人是刚刚创建还是即将创建。无论它在循环中的哪个位置,您都会停止它并重新开始循环。因此,如果它刚刚创建了一个敌人,而您停止循环并通过更快地生成一个新敌人来重新开始,您将连续获得两个敌人。
解决此问题的方法可能是 运行 您的顺序相反。暂停然后生成你的敌人。
let spawnSequence = SKAction.sequence([spawnDelay, spawnAction])
你可能会在敌人之间获得稍长的距离,但不会让两个敌人重叠。
否则,您可以在每次生成最后一个敌人时跟踪生成时间,并将其从下一个生成时间中减去,以便在两者之间放置自定义等待操作。
我在无休止的 运行 游戏中遇到了麻烦,主要是我创建的两种敌人的生成,有时当我们调用函数时会生成两个敌人 "startDifficultyTimer". 基本上,当我调用该函数时,游戏会在同一行中生成 2 个节点,因此玩家被迫失败,我想避免这种情况,但我不知道如何,我几乎尝试了所有方法,我试图从 didmove 中删除 createsequentialenemy但问题仍然存在,我认为(作为新手)问题出在 startDifficultTimer 函数中,因为当值达到极限时问题就消失了 我已经在下面发布了代码,对于可能存在的巨大错误,我们深表歉意,但我们是 swift 开发游戏的新手,非常感谢大家!
func createEnemy() {
let enemy: Enemy
let duration: CGFloat
switch Int(arc4random() % 100) {
case 0...70:
enemy = Enemy.createEnemy()
duration = CGFloat(Float(arc4random()%1)) + durationV
enemy.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 55, height: 37))
let enemyf = enemy.frame
let fixedx = frame.width + enemy.frame.width/2.0
let positions = [ CGPoint(x: fixedx, y: 383), CGPoint(x: fixedx, y: 447), CGPoint(x: fixedx, y: 511)]
let position = positions[Int(arc4random_uniform(UInt32(positions.count)))]
enemy.position = position
case 71...100:
enemy = Enemy.createEnemyMedium()
duration = CGFloat(Float(arc4random()%1)) + durationV
enemy.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 40, height: 70))
let enemyf = enemy.frame
let fixedx = frame.width + enemy.frame.width/2.0
let positions = [ CGPoint(x: fixedx, y: 415), CGPoint(x: fixedx, y: 479)]
let position = positions[Int(arc4random_uniform(UInt32(positions.count)))]
enemy.position = position
default:
enemy = Enemy.createEnemy()
//type = .small
duration = CGFloat(Float(arc4random()%1)) + durationV
let enemyf = enemy.frame
let fixedx = frame.width + enemy.frame.width/2.0
let positions = [ CGPoint(x: fixedx, y: 383), CGPoint(x: fixedx, y: 447), CGPoint(x: fixedx, y: 511)]
let position = positions[Int(arc4random_uniform(UInt32(positions.count)))]
let texture = SKTexture(imageNamed: "dronea1")
enemy.position = position
}
enemy.physicsBody!.isDynamic = false
enemy.physicsBody!.categoryBitMask = PhysicsCategory.Enemy
addChild(enemy)
let moveTo = SKAction.moveTo(x: 0.0, duration: TimeInterval(duration))
enemy.run(.repeatForever(.sequence([moveTo, .removeFromParent()])))
}
func createSequentialEnemies() {
// remove previous action if running. This way you can adjust the spawn duration property and call this method again and it will cancel previous action.
removeAction(forKey: spawnKey)
let spawnAction = SKAction.run(createEnemy)
let spawnDelay = SKAction.wait(forDuration: spawnDuration)
let spawnSequence = SKAction.sequence([spawnAction, spawnDelay])
run(SKAction.repeatForever(spawnSequence), withKey: spawnKey)later
}
func startDifficultyTimer() {
let difficultyTimerKey = "DifficultyTimerKey"
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run { [unowned self] in
guard self.spawnDuration > 0.5 else { // set a min limit
self.removeAction(forKey: difficultyTimerKey) // if min duration has been reached than you might as well stop running this timer.
return
}
self.spawnDuration -= 0.5 // reduce by half a second
self.createSequentialEnemies() // spawn enemies again
}
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence), withKey: difficultyTimerKey)
}
我认为问题在于您在计时器更改时说 "stop this action"。但是该语句不知道敌人是刚刚创建还是即将创建。无论它在循环中的哪个位置,您都会停止它并重新开始循环。因此,如果它刚刚创建了一个敌人,而您停止循环并通过更快地生成一个新敌人来重新开始,您将连续获得两个敌人。
解决此问题的方法可能是 运行 您的顺序相反。暂停然后生成你的敌人。
let spawnSequence = SKAction.sequence([spawnDelay, spawnAction])
你可能会在敌人之间获得稍长的距离,但不会让两个敌人重叠。
否则,您可以在每次生成最后一个敌人时跟踪生成时间,并将其从下一个生成时间中减去,以便在两者之间放置自定义等待操作。