Declaring SKSpriteNode outside spawn function returns SIGABRT in Swift - ios

I have a game that I am making where I have a player and an unlimited number of enemies that's spawn at a given position in a certain amount of time. These enemies are shooting bullets at the player. I need to be able to access the Enemy variable outside the SpawnEnemies() function so that I can use it in my SpawnBullets() function. I tried declaring the Enemy variable outside the SpawnEnemies() function but it returned Sigabrt and I don't know how to access the Enemy variable outside the function without getting this error.
Enemy declaration:
var Enemy = SKSpriteNode(imageNamed: "Enemy.png")
SpawnEnemies function:
func SpawnEnemies() {
let MinValue = self.size.width/8
let MaxValue = self.size.width-20
let SpawnPoint = UInt32(MaxValue-MinValue)
self.Enemy.position = CGPoint(x: CGFloat(arc4random_uniform(SpawnPoint)), y: self.size.height)
let action = SKAction.moveToY(-70, duration: 3.0)
self.Enemy.runAction(SKAction.repeatActionForever(action))
self.addChild(Enemy)
}
SpawnBullets function:
func SpawnBullets(){
let Bullet = SKSpriteNode(imageNamed: "bullet.png")
Bullet.zPosition = -5
Bullet.position = CGPointMake(Enemy.position.x, Enemy.position.y)
let action = SKAction.moveToY(self.size.height + 30, duration: 1.0)
Bullet.runAction(SKAction.repeatActionForever(action))
self.addChild(Bullet)
}
Call SpawnEnemies function in didMoveToView():
var EnemyTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("SpawnEnemies"),userInfo: nil, repeats: true)
Call SpawnBullets function in didMoveToView():
var BulletTimer = NSTimer.scheduledTimerWithTimeInterval(0.2, target: self, selector: Selector("SpawnBullets"),userInfo: nil, repeats: true)
I get this error which is a sigabrt but I used a breakpoint to figure out exactly where the error was and what it was:
Attemped to add a SKNode which already has a parent: <SKSpriteNode> name:'(null)' texture:[<SKTexture> 'Enemy.png' (60 x 80)] position:{132, 1024} scale:{1.00, 1.00} size:{60, 80} anchor:{0.5, 0.5} rotation:0.00

Adding children to a scene already is "infinite", you just need to use it to your advantage.
First rework your bullet function like this so that you are passing in an enemy.
func SpawnBullets(enemy : SKSpriteNode){
let Bullet = SKSpriteNode(imageNamed: "bullet.png")
Bullet.zPosition = -5
Bullet.position = CGPointMake(enemy.position.x, enemy.position.y)
let action = SKAction.moveToY(-self.size.height - 70, duration: 1.0)
Bullet.runAction(SKAction.repeatActionForever(action))
self.addChild(Bullet)
}
Then rework your enemy function so that overtime you call it you spawn a new enemy.
func SpawnEnemies() {
var Enemy = SKSpriteNode(imageNamed: "Enemy.png")
Enemy.name = "enemy";
let MinValue = self.size.width/8
let MaxValue = self.size.width-20
let SpawnPoint = UInt32(MaxValue-MinValue)
Enemy.position = CGPoint(x: CGFloat(arc4random_uniform(SpawnPoint)), y: self.size.height)
let action = SKAction.moveToY(-70, duration: 3.0)
Enemy.runAction(SKAction.repeatActionForever(action))
self.addChild(Enemy)
}
In the function didMoveToView, lets add actions to the scene that handles our timing so that we do not use NSTimer
{
...
let spawnEnemy = SKAction.sequence([SKAction.runBlock(
{
[unowned self] in
self.SpawnEnemies();
}),SKAction.waitForDuration(1)]);
let spawnBullet = SKAction.sequence([SKAction.runBlock(
{
[unowned self] in
self.enumerateChildNodesWithName("enemy", usingBlock:
{
(enemy : SKNode,stop: UnsafeMutablePointer <ObjCBool>) in
  self.SpawnBullets(enemy as! SKSpriteNode);
});
}),SKAction.waitForDuration(0.2)]);
let group = SKAction.group([spawnEnemy, spawnBullet])
self.runAction(SKAction.repeatActionForever(group))
}
This code is not tested so let me know if I need to update anything.

Related

SpriteKit Collision Detection Not Working Properly

I have three nodes in my game-
The Player -
This is a boat that you drag around using a joystick.
let collisionPlayer : UInt32 = 0x1 << 1
let apple = SKSpriteNode(texture: texture)
apple.position = position
apple.physicsBody = SKPhysicsBody(circleOfRadius: apple.size.width / 2.0)
apple.physicsBody?.affectedByGravity = false
apple.physicsBody?.isDynamic = true
apple.setScale(0.1)
addChild(apple)
("apple" is the boat)
The Enemy Boat -
This is a CPU boat that randomly follows the player around.
let collisionNPC : UInt32 = 0x1 << 0
appleNPC.position = position
appleNPC.physicsBody = SKPhysicsBody(circleOfRadius: appleNPC.size.width / 2.0)
appleNPC.physicsBody?.isDynamic = true
appleNPC.physicsBody?.affectedByGravity = false
appleNPC.position = CGPoint(x: 600, y: 200)
appleNPC.setScale(0.1)
addChild(appleNPC)
The Bullet
(self-explanatory)
let collisionBullet : UInt32 = 0x1 << 2
(The following code is in TouchesEnded)
bullet?.name = "Bullet"
bullet?.position = (appleNode?.position)!
bullet?.setScale(0.05)
bullet?.zPosition = 1
bullet?.physicsBody = SKPhysicsBody(circleOfRadius: (bullet?.size.width)!/2)
bullet?.physicsBody?.isDynamic = true
bullet?.physicsBody?.affectedByGravity = false
bullet?.physicsBody?.usesPreciseCollisionDetection = true
To move the bullet I use the code:
// Your code with delay
if bulletNumbers > 0 {
let offset = CGPoint(x: touchLocation.x - (bullet?.position.x)! , y: touchLocation.y - (bullet?.position.y)!)
//Stops Bullet from shooting backwards
//Get the direction of where to shoot
let direction = offset
//Make it shoot far enough to be guaranteed off screen
let shootAmount = CGPoint(x: direction.x * 10, y: direction.y * 10)
//Add the shoot amount to the current position
let realDest = CGPoint(x: shootAmount.x + (bullet?.position.x)!, y: shootAmount.y + (bullet?.position.y)!)
//Create the actions
addChild(bullet!)
self.bulletNumbers -= 1
let distance = sqrt(pow(realDest.x - (appleNode?.position.x)!, 2) +
pow(realDest.y - (appleNode?.position.y)!, 2))
// run the sequence of actions for the firing
let duration = TimeInterval(distance / PlayerMissileSpeed)
let missileMoveAction = SKAction.move(to: realDest, duration: duration)
let when = DispatchTime.now() + 10 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) { self.bulletNumbers += 1
}
bullet?.run(missileMoveAction) {
self.bullet?.isHidden = true
self.bullet?.removeFromParent()
print("\(self.bulletNumbers)")
}}
else if bulletNumbers <= 0 {
print("reload")
let when = DispatchTime.now() + 2 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
}
}
}
func didBegin(_ contact: SKPhysicsContact) {
print("test")
}
func setRandomStickColor() {
let randomColor = UIColor.random()
moveAnalogStick.stick.color = randomColor
}
func setRandomSubstrateColor() {
let randomColor = UIColor.random()
moveAnalogStick.substrate.color = randomColor
}
override func update(_ currentTime: TimeInterval) {
/* Called before each frame is rendered */
super.update(currentTime)
let _:UInt32 = arc4random_uniform(1) //
appleNodeCpuSpeed = CGFloat(1)
var locationx : CGFloat
var locationy: CGFloat
locationx = (appleNode?.position.x)!
locationy = (appleNode?.position.y)!
let dx = locationx - (appleNodeNPC?.position.x)!
let dy = locationy - (appleNodeNPC?.position.y)!
let angle = atan2(dy, dx)
let vx = cos(angle) * appleNodeCpuSpeed
let vy = sin(angle) * appleNodeCpuSpeed
self.appleNodeNPC?.position.x += vx
self.appleNodeNPC?.position.y += vy
let when = DispatchTime.now() + 0.25 // change 2 to desired number of seconds
DispatchQueue.main.asyncAfter(deadline: when) {
self.appleNodeNPC?.zRotation = angle + 90
}
//2
This works fine. The bullet is launched from the boat to the touch location, however, things start to go wrong when I tried to introduce collisions. Here is my code below:
appleNode?.physicsBody?.categoryBitMask = collisionPlayer
appleNode?.physicsBody?.collisionBitMask = collisionNPC
appleNode?.physicsBody?.contactTestBitMask = 0
appleNodeNPC?.physicsBody?.categoryBitMask = collisionNPC
appleNodeNPC?.physicsBody?.collisionBitMask = collisionPlayer
appleNodeNPC?.physicsBody?.contactTestBitMask = collisionBullet
bullet?.physicsBody?.categoryBitMask = collisionBullet
bullet?.physicsBody?.collisionBitMask = 0
bullet?.physicsBody?.contactTestBitMask = collisionNPC
physicsWorld.contactDelegate = self
view.showsPhysics = true
Then in my didBegin function I have:
func didBegin(_ contact: SKPhysicsContact) {
print("test")
}
Let's start from the beginning. I tap the screen and the bullet is launched. The bullet does not collide with the Player, which is what I originally wanted. However, when the bullet makes contact with the Enemy ship it DOES collide. It goes around the ship and keeps going on to its original destination. I want the bullet to contact the ship and nothing else - no collisions. I would hope to assume that my error here is because of my code for moving the bullet, but i'm not sure. Any help is appreciated.
Define unique categories, ensure your class is a SKPhysicsContactDelegate and make yourself the physics contact delegate:
//Physics categories
let appleCategory: UInt32 = 1 << 0
let enemyCategory: UInt32 = 1 << 1
let bulletCategory: UInt32 = 1 << 2
class GameScene: SKScene, SKPhysicsContactDelegate {
physicsWorld.contactDelegate = self
Assign the categories (usually in didMove(to view:) :
apple.physicsBody.catgeoryBitMask = appleCategory
enemy.physicsBody.catgeoryBitMask = enemyCategory
bullet.physicsBody.catgeoryBitMask = bulletCategory
(Make sure you've created physics bodies for each node)
Set up collisions:
apple.physicsBody?.collisionBitMask = 0 // apple/player collides with nothing
enemy.physicsBody?.collisionBitMask = 0 // enemy collides with nothing
bullet.physicsBody?.collisionBitMask = 0 // bullet collides with nothing
or even:
for node in [apple, enemy, bullet] {
node.physicsBody?.collisionBitMask = 0 // collides with nothing
}
Set up contacts
bullet.physicsBody?.collisionBitMask = enemyCategory // bullet contacts enemy
Make sure that at least one of the objects involved in each potential contact has the isDynamic property on its physics body set to true, or no contact will be generated. It is not necessary for both of the objects to be dynamic.
You should now get didBegin called when the bullet and the enemy make contact. You could code didBegin like this:
func didBegin(_ contact: SKPhysicsContact) {
print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch contactMask {
case bulletCategory | enemyCategory:
print("bullet and enemy have contacted.")
let bulletNode = contact.bodyA.categoryBitMask == bulletCategory ? contact.bodyA.node : contact.bodyB.node
enemyHealth -= 10
bulletNode.removeFromParent
default:
print("Some other contact occurred")
}
}

"lldb" crash with XCODE & ARKIT : 0 __ UpdateAudioTransform

I have written a game using ARKIT that pops up random nodes (with drones) in the 3d space around the player, using ARKIT, and I get an incomprehensible crash, as only thing in the console is "lldb" , and the rest of the crash details are on the screenshot attached (I am still a newbie in Swift so not able to debug it).
The crash happens when there's a lot of nodes on the screen (maybe 20-30) and the FPS drops - ie happens "mid - game" and the FPS drops a lot.
Can someone point me to the right direction for this crash?
The part of the code that is in my opinion relevant is the function that spawns the random 3d nodes (they also have SCNActions attached that play sounds when they're tapped - perhaps this could be relevant as the left hand side debugger opens with that line highlighted when the crash occurs, as per the photo attached). In case it is also relevant, the program uses some SCNParticleSystem calls as well. Attaching relevant code, and also the snapshot of the crash screen:
var droneSound : SCNAudioSource()
override func viewDidLoad() {
super.viewDidLoad()
droneSound = SCNAudioSource(named: "Sounds/drone1.wav")!
playDroneSound = SCNAction.playAudio(self.droneSound, waitForCompletion: true)
}
func startGame() {
DispatchQueue.main.async {
self.spawnTimer = Timer.scheduledTimer(timeInterval: TimeInterval(self.randomFloat(min: 2.5, max: 5)), target: self, selector: #selector(self.spawnDronesInterim), userInfo: nil, repeats: true)
}
}
#objc func spawnDronesInterim() {
for _ in 0...5 {
spawnDrone()
}
}
#objc func spawnDrone() {
let newDroneScene = SCNScene(named: "Ar.scnassets/DroneScene.scn")!
var newDroneNode = newDroneScene.rootNode.childNode(withName: "Drone", recursively: false)!
newDroneNode.name = "Drone\(self.droneCounter)"
newDroneNode = newDroneScene.rootNode.childNode(withName: "Drone\(self.droneCounter)", recursively: false)!
newDroneNode.position.x = newDroneNode.presentation.position.x + self.randomFloat(min: -10, max: 10)
newDroneNode.position.y = newDroneNode.presentation.position.y + self.randomFloat(min: -1, max: 5)
newDroneNode.position.z = newDroneNode.presentation.position.z + self.randomFloat(min: -10, max: 10)
let move1 = SCNAction.move(to: SCNVector3((self.randomFloat(min: -7, max: 7)), (self.randomFloat(min: 1, max: 5)), (self.randomFloat(min: -7, max: 7))), duration: 15)
let disappearMove = SCNAction.move(to: SCNVector3((self.randomFloat(min: -10, max: 10)), (self.randomFloat(min: 1, max: 5)), (self.randomFloat(min: -10, max: 10))), duration: 3)
let rotateAction = SCNAction.run { (SCNNode) in
let rotate = SCNAction.rotateBy(x: 0, y: CGFloat(360.degreesToRadians), z: 0, duration: 2)
newDroneNode.runAction(rotate)
}
let removeIt = SCNAction.removeFromParentNode()
let sequence = SCNAction.sequence([waitFive,move1,rotateAction,waitFive,disappearMove,waitTwo,removeIt])
newDroneNode.runAction(sequence)
self.sceneView.scene.rootNode.addChildNode(newDroneNode)
if self.droneCounter >= 5 {
self.sceneView.scene.rootNode.childNode(withName: "Drone\(self.droneCounter)", recursively: true)!.runAction(SCNAction.repeatForever(self.playDroneSound))
}
self.droneCounter += 1
}
when user taps on one of the 3d nodes, this gets called:
func handleExplosion (node : SCNNode) {
self.sceneView.scene.rootNode.childNode(withName: node.name!, recursively: true)!.runAction(self.playExplosionSound)
node.opacity = 0
print (self.sceneView.scene.rootNode.position)
let confetti = SCNParticleSystem(named: "Ar.scnassets/confetti.scnp", inDirectory: nil)
confetti?.loops = false
confetti?.particleLifeSpan = 1.5
confetti?.emitterShape = node.geometry
let confettiNode = SCNNode()
confettiNode.addParticleSystem(confetti!)
confettiNode.position = node.presentation.position
self.sceneView.scene.rootNode.addChildNode(confettiNode)
let fire = SCNParticleSystem(named: "Ar.scnassets/fire", inDirectory: nil)
fire?.loops = false
fire?.particleLifeSpan = 0.1
fire?.emitterShape = node.geometry
let fireNode = SCNNode()
fireNode.addParticleSystem(fire!)
fireNode.position = node.presentation.position
self.sceneView.scene.rootNode.addChildNode(fireNode)
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
node.removeFromParentNode()
self.killedLabel.text = "Killed: \(self.killedCount)"
self.dronesOut -= 1
}
}
Any pointer to the right direction for solving this crash would be greatly appreciated]1

timeInterval Variable won't work

I'm trying to change the timeInterval in a scheduledTimer. I'm trying to do this by changing a variable to the interval and than setting the timeInterval to this variable. I don't get any errors but the timeInterval won't change. Can someone help me?
var enemyTimer = Timer()
var playTime = 0
var enemySpawnTime: Double = 3
enemyTimer = Timer.scheduledTimer(timeInterval: Double(enemySpawnTime), target: self, selector: #selector(GameScene.enemySpawn), userInfo: nil, repeats: true)
playTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(GameScene.ingameTimer), userInfo: nil, repeats: true)
func enemySpawn() {
let enemy = SKSpriteNode(imageNamed: "Enemy")
let minValue = self.size.width / 8
let maxValue = self.size.width - 20
let spawnPoint = UInt32(maxValue - minValue)
enemy.position = CGPoint(x: CGFloat(arc4random_uniform(spawnPoint)), y: self.size.height)
let action = SKAction.moveTo(y: -70, duration: 5)
enemy.run(action)
self.addChild(enemy)
}
func ingameTimer() {
playTime += 1
if(playTime >= 10 && playTime < 30){
enemySpawnTime = 2
print(enemySpawnTime)
}else
if(playTime >= 30 && playTime < 60){
enemySpawnTime = 1
print(enemySpawnTime)
}else
if(playTime >= 60 && playTime < 120){
enemySpawnTime = 0.75
print(enemySpawnTime)
}else
if(playTime >= 120 && playTime < 180){
enemySpawnTime = 0.5
print(enemySpawnTime)
}else
if(playTime >= 180 && playTime < 240){
enemySpawnTime = 0.25
print(enemySpawnTime)
}
}
I hope someone can help me!
Thanks!
The reason why your code doesn't work is because the Timer object doesn't know that its interval needs to be in sync with your enemySpawnTime. The solution is simple, just recreate the timer when you change the enemy spawn time.
But...
You should NEVER use Timer (NSTimer prior to Swift 3) or GCD to delay stuff when you're using SpriteKit. See this for more details.
The correct way to do this is to create a sequence of SKActions.
Assuming self is a subclass of SKScene, you can do this:
override func didMove(to view: SKView) {
let waitAction = SKAction.wait(forDuration: enemySpawnTime)
let enemySpawnAction = SKAction.run { self.enemySpawn() }
let sequence = SKAction.sequence([waitAction, enemySpawnAction])
somePlaceholderNode.run(SKAction.repeatForever(sequence))
}
where somePlaceholderNode is just a node that does nothing but run the action. I'll explain this later.
And you should do this for the other timer as well.
Now whenever you change the timer interval, also do this:
somePlaceholderNode.removeAllActions()
let waitAction = SKAction.wait(forDuration: enemySpawnTime)
let enemySpawnAction = SKAction.run { self.enemySpawn() }
let sequence = SKAction.sequence([waitAction, enemySpawnAction])
somePlaceholderNode.run(SKAction.repeatForever(sequence))
Here I first remove the action that the node was running, and tell it to run almost the same action, but with a different time interval. You can add this block of code to the didSet block of enemySpawnTime:
var enemySpawnTime: Double = 3 {
didSet {
let waitAction = SKAction.wait(forDuration: enemySpawnTime)
let enemySpawnAction = SKAction.run { self.enemySpawn() }
let sequence = SKAction.sequence([waitAction, enemySpawnAction])
somePlaceholderNode.run(SKAction.repeatForever(sequence))
}
}
Now your code should work!
The reason why we want a placeholder node here is because when we remove the action by calling removeAllActions, we don't want to remove all the actions that is running.

"Attemped to add a SKNode which already has a parent" error when trying to spawn a node

The error that I keep getting is this one: Attemped to add a SKNode which already has a parent. I have tried to take out the spawn function and it works without it. Can someone please help me ?
func spawnTrolls(){
let minValue = self.size.width / 10
let maxValue = self.size.width - 30
let spawnpoint = UInt32(maxValue - minValue)
Troll.position = CGPointMake(CGFloat(arc4random_uniform(spawnpoint)), self.size.height)
self.addChild(Troll)
let action = SKAction.moveToY(-70, duration: 2)
let actionDone = SKAction.removeFromParent()
Troll.runAction(SKAction.sequence([action, actionDone]))
Troll.physicsBody? = SKPhysicsBody(rectangleOfSize: Troll.size)
Troll.physicsBody?.categoryBitMask = physicsCategory.Troll
Troll.physicsBody?.contactTestBitMask = physicsCategory.Rocket
Troll.physicsBody?.affectedByGravity = false
Troll.physicsBody?.dynamic = true
}
_ = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: Selector("spawnTrolls"), userInfo: nil, repeats: true)

How do I make my enemySprite respawn as new bad guy once its been killed?

I am having trouble with my game, I've managed to have my enemySprites all shoot at the hero in a synchronized matter and I've gotten them to play the "killed" animation once they've been hit. Although I've run into a rather small matter which I was really hoping you guys could help me with. The problem I have is that when my badGuy is killed they move off the screen and I don't know how I can program it so that a 'new' badGuy appears forever until the Hero sprite is killed.
This is my function to spawn my enemy:
func spawnEnemy(targetSprite: SKNode) -> SKSpriteNode {
if !gamePaused{
// create a new enemy sprite
let main = GameScene()
newEnemy = SKSpriteNode(imageNamed:"BNG1_1.png")
enemySprite.append(newEnemy)//ADD TO THE LIBRARY OF BADGUYS
newEnemy.xScale = 1.2
newEnemy.yScale = 0.6
newEnemy.physicsBody?.dynamic = true
newEnemy.physicsBody = SKPhysicsBody(texture: newEnemy.texture, size: newEnemy.size)
newEnemy.physicsBody?.affectedByGravity = false
newEnemy.physicsBody?.categoryBitMask = BodyType.badguyCollision.rawValue
newEnemy.physicsBody?.contactTestBitMask = BodyType.beamCollison.rawValue
newEnemy.physicsBody?.collisionBitMask = 0x0
let muv : UInt32 = (200 + (arc4random()%500))
let actualDuration = NSTimeInterval(random(min: CGFloat(3.0), max: CGFloat(4.0)))
let randomNum = CGPoint(x:Int (muv), y:Int (arc4random()%500))
// Create the actions
var actionMove = SKAction.moveTo(randomNum, duration: NSTimeInterval(actualDuration))
newEnemy.runAction(SKAction.sequence([actionMove]))
// position new sprite at a random position on the screen
var posX = arc4random_uniform(UInt32(sizeRect.size.width))
var posY = arc4random_uniform(UInt32(sizeRect.size.height))
newEnemy.position = CGPoint(x: screenSize.width*2 + newEnemy.size.width, y: random(min: newEnemy.size.height, max: screenSize.height - newEnemy.size.height))
let atlas = SKTextureAtlas(named: "BG1.atlas")
let anime = SKAction.animateWithTextures([atlas.textureNamed("BG1_1.png"), atlas.textureNamed("BG1_2.png"),
atlas.textureNamed("BG1_3.png"),
atlas.textureNamed("BG1_2.png"),
atlas.textureNamed("BG1_1.png")], timePerFrame: 0.1)
dinoRun = SKAction.repeatActionForever(anime)
newEnemy.runAction(dinoRun)
}
return newEnemy
}
And this is my function for once they are hit (this function is called when the collisionTest between my hero's laser and the badguy is recognized):
func deadBadGuy(){
//animation
var dinoRun:SKAction
var newdes = CGPoint(x: Int(arc4random()%500), y:0)
var actionMoov = SKAction.moveTo(newdes, duration: 3)
var goaway = SKAction.removeFromParent()
let aTlas = SKTextureAtlas(named: "dedBG.atlas")
let anime = SKAction.animateWithTextures([aTlas.textureNamed("deadBG1.png"), aTlas.textureNamed("deadBG2.png"),
aTlas.textureNamed("deadBG3.png"),
aTlas.textureNamed("deadBG2.png"),
aTlas.textureNamed("deadBG1.png")], timePerFrame: 0.1)
dinoRun = SKAction.repeatActionForever(anime)
newEnemy.runAction(dinoRun)
newEnemy.runAction(SKAction.sequence([actionMoov,goaway]))
score++
self.scoreNode.text = String(score)
enemySprites.newPlace(neewEnemy)
dead = true //i created this Boolean because the sprite keeps shooting even if its dead
}
This is the way I called for the collisionTest in my program in case you need it for more information:
func didBeginContact(contact:SKPhysicsContact){
if !gamePaused {
let firstNode = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
switch(firstNode){
case BodyType.beamCollison.rawValue | BodyType.badguyCollision.rawValue:
deadBadGuy()
//enemySprites.spawnEnemy(sprite)
default:
print("hit")
}
Note: I tried having the func spawnEnemy being called during the collisionTest but that results in the BadGuy staying off screen shooting at my hero.
Update : I found out how to add a new enemy sprite once the other is dead all i had to do was
newEnemy.runAction(SKAction.sequence([actionMoov,goaway]), completion: {
self.addChild(self.enemySprites.spawnEnemy(sprite))
})
in the deadBadGuy function(the spawnEnemy function is in another class which I named enemySprites as a variable). However now I've run into a new issue and that is that it adds 10 enemySprites instead of one. How can I change that?
Update 2 : I figured out that issue too, I just needed to remove to dead Boolean method in the deadBadGuy function.
I found my answer and all I had to do was add this line to my deadBadGuy function and remove the dead boolean methods
newEnemy.runAction(SKAction.sequence([actionMoov,goaway]), completion: {
self.addChild(self.enemySprites.spawnEnemy(sprite))
})

Resources