2017-10-19 11 views
1

Je crée un jeu dans lequel j'ai deux fonctions différentes qui peuvent contenir différents types d'ennemis. Je veux faire un code qui change entre les deux tous les 10 points. Ainsi, de 0 à 10 "la fonction 1" est active, et de 10 à 20 "la fonction 2" est active, puis elle change de nouveau, puis revient à nouveau et ainsi de suite.Spritekit - Passage entre deux fonctions avec une minuterie

Ce sont mes deux fonctions contenant des ennemis:

var score = 0 

func createPipes() { 
    PipesHolder = SKNode() 
    PipesHolder.name = "Pipe" 


    let pipeLeft = SKSpriteNode(imageNamed: "PipeRight") 
    pipeLeft.name = "Pipe" 
    pipeLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    pipeLeft.position = CGPoint(x: 300, y: 0) 
    pipeLeft.physicsBody = SKPhysicsBody(rectangleOf: pipeLeft.size) 
    pipeLeft.physicsBody?.categoryBitMask = ColliderType.Pipe 
    pipeLeft.physicsBody?.affectedByGravity = false 

    let pipeRight = SKSpriteNode(imageNamed: "PipeLeft") 
    pipeRight.name = "Pipe" 
    pipeRight.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    pipeRight.position = CGPoint(x: -300, y: 0) 
    pipeRight.physicsBody = SKPhysicsBody(rectangleOf: pipeRight.size) 
    pipeRight.physicsBody?.categoryBitMask = ColliderType.Pipe 
    pipeRight.physicsBody?.affectedByGravity = false 


    PipesHolder.zPosition = 2 
    PipesHolder.xScale = 1.5 
    PipesHolder.yScale = 0.8 
    PipesHolder.position.x = CGFloat.randomBetweenNumbers(firstNum: 
    -220, secondNum: 220) 
    PipesHolder.position.y = self.frame.height + 100 

    PipesHolder.addChild(pipeLeft) 
    PipesHolder.addChild(pipeRight) 

    self.addChild(PipesHolder) 

    let destination = self.frame.height * 2 
    let move = SKAction.moveTo(y: -destination, duration: 10) 
    let remove = SKAction.removeFromParent() 

    let moveRight = SKAction.moveBy(x: 200, y: 0, duration: 1) 

    let moveLeft = SKAction.moveBy(x: -200, y: 0, duration: 1) 


    let moveBackAndForth = 
    SKAction.repeatForever(SKAction.sequence([moveRight, moveLeft])) 


    PipesHolder.run(moveBackAndForth) 

    PipesHolder.run(SKAction.sequence([move, remove]), withKey: 
    "MovePipes") 

} 

func spawnPipes() { 
    let spawn = SKAction.run({() -> Void in 
     self.createPipes() 
    }) 

    let delay = SKAction.wait(forDuration: 1) 
    let sequence = SKAction.sequence([spawn, delay]) 

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnPipes") 
} 

func createRedEnemies() { 
    let enemyHolder = SKNode() 
    enemyHolder.name = "Holder" 

    let enemyLeft = SKSpriteNode(imageNamed: "Enemy") 
    let enemyMiddle = SKSpriteNode(imageNamed: "Enemy") 
    let enemyRight = SKSpriteNode(imageNamed: "Enemy") 

    enemyLeft.name = "Enemy" 
    enemyLeft.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    enemyLeft.position = CGPoint(x: 200, y: 0) 
    enemyLeft.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 
    enemyLeft.size.width - 5, height: enemyLeft.size.height - 5)) 
    enemyLeft.physicsBody?.categoryBitMask = ColliderType.Enemy 
    enemyLeft.physicsBody?.collisionBitMask = 0 
    enemyLeft.physicsBody?.affectedByGravity = false 


    enemyMiddle.name = "Enemy" 
    enemyMiddle.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    enemyMiddle.position = CGPoint(x: 0, y: 0) 
    enemyMiddle.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 
    enemyMiddle.size.width - 5, height: enemyMiddle.size.height - 5)) 
    enemyMiddle.physicsBody?.categoryBitMask = ColliderType.Enemy 
    enemyLeft.physicsBody?.collisionBitMask = 0 
    enemyMiddle.physicsBody?.affectedByGravity = false 


    enemyRight.name = "Enemy" 
    enemyRight.anchorPoint = CGPoint(x: 0.5, y: 0.5) 
    enemyRight.position = CGPoint(x: -200, y: 0) 
    enemyRight.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: 
    enemyRight.size.width - 5, height: enemyRight.size.height - 5)) 
    enemyRight.physicsBody?.categoryBitMask = ColliderType.Enemy 
    enemyLeft.physicsBody?.collisionBitMask = 0 
    enemyRight.physicsBody?.affectedByGravity = false 


    enemyHolder.zPosition = 2 

    enemyHolder.position.y = self.frame.height + 100 
    enemyHolder.position.x = CGFloat.randomBetweenNumbers(firstNum: 
    -100, secondNum: 100) 

    enemyHolder.addChild(enemyLeft) 
    enemyHolder.addChild(enemyMiddle) 
    enemyHolder.addChild(enemyRight) 

    self.addChild(enemyHolder) 

    let destination = self.frame.height * 4 
    let move = SKAction.moveTo(y: -destination, duration: 9) 
    let remove = SKAction.removeFromParent() 

    enemyHolder.run(SKAction.sequence([move, remove]), withKey: 
    "MoveEnemies") 

} 

func spawnEnemies() { 
    let spawn = SKAction.run({() -> Void in 
     self.createRedEnemies() 
    }) 

    let delay = SKAction.wait(forDuration: 0.4) 
    let sequence = SKAction.sequence([spawn, delay]) 

    self.run(SKAction.repeatForever(sequence), withKey: "SpawnEnemies") 

} 

Voici le code que j'ai pour les fonctions secondaires que j'ajouter dans le « didMove »:

func shiftEnemies() { 

    if score >= 0 && score <= 10 { 
     spawnEnemies() 
    } else if score >= 11 && score <= 20 { 
     spawnPipes() 
    } else if score >= 21 && score <= 30 { 
     spawnEnemies() 
    } else if score >= 31 && score <= 40 { 
     spawnPipes() 
    } 

} 

Deux problèmes avec le " shiftedEnnemis() ". Le premier est évident, je ne peux pas écrire un code pour chaque score de 10. Le deuxième problème est que ce code ne fonctionne même pas. "SpawnEnemies()" est la seule fonction affichée. "spawnPipes()" ne s'affiche pas, jamais. Peut-être que le problème numéro deux sera résolu lorsque je réglerai le problème numéro 1.

Thx les gars!

Répondre

1

la raison pour laquelle votre fonction SpawnEnemies est la seule fonction qui est appelée est parce que vous mettez la fonction shiftEnemies dans la méthode didMove(toView:) et didMove(toView:) n'est appelé un moment où vous présentez votre scène

ce que je recommande est essayer d'appeler la fonction shiftEnemies() dans la partie du code où le score est ajouté (le plus probable dans votre méthode de didBeginContact)

+0

Merci pour la réponse @E. Huckabee! J'utilise un compteur pour le score ajouté que j'ai mis dans la fonction "didMove". "counter = Timer.scheduledTimer (timeInterval: TimeInterval (1), cible: self, sélecteur:" incrementScore ", userInfo: nil, répète: true)" – Flinigan

+0

puis dans la fonction "incrementScore" ajoutez la fonction "shiftEnemies" pour que le la fonction est appelée chaque fois qu'un score est ajouté –

1

donc, vous voulez commencer par appeler spawnenemies et quand le score passe devant un multiple de 10, passer à appeler spawnPipes et puis retour à spawnEnemies au multiple suivant de 10 etc?

ont tout simplement un bool appelé shouldSpawnEnemies:

var shouldSpawnEnemies = true // Start by spawning enemies 

(si vous voulez commencer par des tuyaux fraie, ce à false initialiser).

Initialiser le score auquel les fonctions doivent changer:

var switchFunctionScore = 10 

Mettez un veilleur de propriété sur votre score. Lorsque le score passe le score 'switch', définissez le booléen indiquant la fonction à utiliser pour false. Ensuite, définissez le score suivant auquel les fonctions doivent être commutées.

var score : int = 0 { 
    didSet { 
     if (score >= switchFunctionScore) && oldValue < switchFunctionScore) { 
     shouldSpawnEnemies = !shouldSpawnEnemies 
     switchFunctionScore += 10 
     } 
    } 

Ensuite, chaque fois que vous avez besoin d'appeler une de ces fonctions; il suffit de vérifier la valeur de shouldSpawnEnemies:

if shouldSpawnenemies { 
    spawnEnemies 
} else { 
    spawnPipes 
} 
+0

Cela fonctionne très bien, mais je voudrais mentionner les problèmes avec l'utilisation de Timer dans un jeu SpriteKit – Knight0fDragon

+0

Yep - ne voit pas cela. Flinigan - n'utilisez pas de minuterie - utilisez un SKAction pour appeler votre fonction à l'intervalle spécifié. Sprite-Kit n'est pas au courant des minuteurs et ils peuvent gâcher la boucle de jeu. –

+0

Cette solution fonctionnerait avec une minuterie, juste besoin de faire une note pour aller sur la route difficile de mettre les minuteurs en pause et de les retirer de la boucle quand les événements se produisent – Knight0fDragon

0

j'éviter d'utiliser la minuterie, la minuterie fonctionne en dehors du système de temps de SpriteKit, donc pour moi de tricher dans votre jeu, je pouvais toujours quitter et retourner l'application, et depuis la minuterie est basé sur le temps réel et non sur le temps de jeu, le temps passé en dehors du jeu sera toujours pris en compte.

Ce que vous voulez faire est d'utiliser SKActionwait(duration:), « séquence , 'run(_ block:)repeatForever et repeat(_:count)

Pour ce faire, vous devez le décomposer en plusieurs étapes:

1er, nous voulons attendre 1 seconde et fonction de tir 1:

let wait1Sec = SKAction.wait(duration:1) 
let function1 = SKAction.run({[weak self] in self?.function1()}) 
let seq1 = SKAction.sequence([wait1Sec,function1]) 

2, nous voulons créer une action qui répète 10 fois:

let repeat1 = SKAction.repeat(seq1,count:10) 

3, nous voulons le faire à nouveau pour la fonction 2:

let function2 = SKAction.run({[weak self] in self?.function2()}) 
let seq2 = SKAction.sequence([wait1Sec,function2]) 
let repeat2 = SKAction.repeat(seq2,count:10) 

Enfin, nous voulons combiner les deux et l'exécuter indefinetely

let seqForever = SKAction.sequence([repeat1,repeat2]) 
let repeatForever = SKAction.repeatForever(seqForever) 

Maintenant que nous avons l'action, nous pouvons l'attacher à la scène une fois

scene.run(repeatForever,withKey:"forever") 

Vous avez maintenant une solution qui tirera constamment un méthode 10 fois en 10 secondes, puis passer à l'autre fonction pendant 10 fois de plus en 10 secondes, en répétant pour toujours.

override func didMove(to view:SKView) 
{ 
    let wait1Sec = SKAction.wait(duration:1) 
    let function1 = SKAction.run({[weak self] in self?.function1()}) 
    let seq1 = SKAction.sequence([wait1Sec,function1]) 
    let repeat1 = SKAction.repeat(seq1,count:10) 

    let function2 = SKAction.run({[weak self] in self?.function2()}) 
    let seq2 = SKAction.sequence([wait1Sec,function2]) 
    let repeat2 = SKAction.repeat(seq2,count:10) 

    let seqForever = SKAction.sequence([repeat1,repeat2]) 
    let repeatForever = SKAction.repeatForever(seqForever) 
    scene.run(repeatForever,withKey:"forever") 
} 
+0

Merci chevalier! J'ai essayé d'ajouter cela dans le code. Je ne sais pas si je l'ai mis correctement. J'ai mis tout le code dans le "shiftEnemies()", mais le résultat est assez différent. Il commence avec l'une des fonctions, et ensuite Il continue de fonctionner avec les deux fonctions et multiplie également, au moins, tous les SKSpriteNodes dans la fonction. – Flinigan

+0

vous ne devriez l'appeler qu'une seule fois – Knight0fDragon

+0

oui je l'ai appelé une fois. Je voulais dire ce qui s'est passé quand j'ai commencé le jeu. – Flinigan