Asteroid Battle Game Keep Crashing - ios

So I keep getting this error at random times during the play of the game, "fatal error: unexpectedly found nil while unwrapping an Optional value" in my asteroid battle game. I'll post the code here and if anyone could help figure it out I would appreciate it. If you don't understand any part you can ask me
import SpriteKit
import Darwin
struct PhysicsCatagory {
static let Asteroids : UInt32 = 1 //00000000000000000000000000000001
static let Bullet : UInt32 = 2 //0000000000000000000000000000010
static let Fighter : UInt32 = 3 //0000000000000000000000000000100
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var Score = Int()
var scoreLabel = UILabel()
var Fighter = SKSpriteNode(imageNamed: "Fighter")
override func didMoveToView(view: SKView) {
/* Setup your scene here */
physicsWorld.contactDelegate = self
Fighter.position = CGPointMake(self.size.width / 2, self.size.height / 7)
Fighter.physicsBody = SKPhysicsBody(rectangleOfSize: Fighter.size)
Fighter.physicsBody?.affectedByGravity = false
Fighter.physicsBody?.categoryBitMask = PhysicsCatagory.Fighter
Fighter.physicsBody?.contactTestBitMask = PhysicsCatagory.Asteroids
Fighter.physicsBody?.dynamic = false
var Timer = NSTimer.scheduledTimerWithTimeInterval(0.25, target: self, selector: Selector("spawnBullets"), userInfo: nil, repeats: true)
var asteriodsTimer = NSTimer.scheduledTimerWithTimeInterval(0.35 , target: self, selector: Selector("spawnAsteroids"), userInfo: nil, repeats: true)
var furiousAsteriodsTimer = NSTimer.scheduledTimerWithTimeInterval(0.9 , target: self, selector: Selector("spawnFuriousAsteroids"), userInfo: nil, repeats: true)
self.addChild(Fighter)
scoreLabel.text = "\(Score)"
scoreLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
scoreLabel.backgroundColor = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 0.3)
scoreLabel.textColor = UIColor.whiteColor()
self.view?.addSubview(scoreLabel)
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody : SKPhysicsBody = contact.bodyA
let secondBody : SKPhysicsBody = contact.bodyB
if ((firstBody.categoryBitMask == PhysicsCatagory.Asteroids) && (secondBody.categoryBitMask == PhysicsCatagory.Bullet) || (firstBody.categoryBitMask == PhysicsCatagory.Bullet) && (secondBody.categoryBitMask == PhysicsCatagory.Asteroids)){
bulletHitAsteroids(firstBody.node as! SKSpriteNode, Bullet: secondBody.node as! SKSpriteNode)
}
}
func bulletHitAsteroids(Asteroids: SKSpriteNode, Bullet: SKSpriteNode){
Asteroids.removeFromParent()
Bullet.removeFromParent()
Score++
scoreLabel.text = "\(Score)"
}
func bulletHitFuriousAsteroids(FuriousAsteroids: SKSpriteNode, Bullet: SKSpriteNode){
FuriousAsteroids.removeFromParent()
Bullet.removeFromParent()
Score = Score + 2
scoreLabel.text = "\(Score)"
}
func spawnBullets(){
let Bullet = SKSpriteNode(imageNamed: "Bullet")
Bullet.zPosition = -5
Bullet.position = CGPointMake(Fighter.position.x, Fighter.position.y)
let action = SKAction.moveToY(self.size.height + 30, duration: 0.9)
let actionDone = SKAction.removeFromParent()
Bullet.runAction(SKAction.sequence([action, actionDone]))
Bullet.physicsBody = SKPhysicsBody(rectangleOfSize: Bullet.size)
Bullet.physicsBody?.categoryBitMask = PhysicsCatagory.Bullet
Bullet.physicsBody?.contactTestBitMask = PhysicsCatagory.Asteroids
Bullet.physicsBody?.affectedByGravity = false
Bullet.physicsBody?.dynamic = false
self.addChild(Bullet)
}
func spawnAsteroids(){
let Asteroids = SKSpriteNode(imageNamed: "Asteroid")
let minValue = self.size.width / 8
let maxValue = self.size.width - 20
let spawnPoint = UInt32(maxValue - minValue)
Asteroids.position = CGPoint(x: CGFloat(arc4random_uniform(spawnPoint)) , y: self.size.height)
Asteroids.physicsBody = SKPhysicsBody(rectangleOfSize: Asteroids.size)
Asteroids.physicsBody?.categoryBitMask = PhysicsCatagory.Asteroids
Asteroids.physicsBody?.contactTestBitMask = PhysicsCatagory.Bullet
Asteroids.physicsBody?.affectedByGravity = false
Asteroids.physicsBody?.dynamic = true
let action = SKAction.moveToY(-50, duration: 2.5)
let actionDone = SKAction.removeFromParent()
Asteroids.runAction(SKAction.sequence([action, actionDone]))
self.addChild(Asteroids)
}
func spawnFuriousAsteroids(){
let FuriousAsteroids = SKSpriteNode(imageNamed: "FuriousAsteroid")
let minValue = self.size.width / 8
let maxValue = self.size.width - 20
let spawnPoint = UInt32(maxValue - minValue)
FuriousAsteroids.position = CGPoint(x: CGFloat(arc4random_uniform(spawnPoint)) , y: self.size.height)
FuriousAsteroids.physicsBody = SKPhysicsBody(rectangleOfSize: FuriousAsteroids.size)
FuriousAsteroids.physicsBody?.categoryBitMask = PhysicsCatagory.Asteroids
FuriousAsteroids.physicsBody?.contactTestBitMask = PhysicsCatagory.Bullet
FuriousAsteroids.physicsBody?.affectedByGravity = false
FuriousAsteroids.physicsBody?.dynamic = true
let action = SKAction.moveToY(-50, duration: 1.5)
let actionDone = SKAction.removeFromParent()
FuriousAsteroids.runAction(SKAction.sequence([action, actionDone]))
self.addChild(FuriousAsteroids)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
Fighter.position.x = location.x
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
Fighter.position.x = location.x
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}

It is crashing because one of the bodies doesn't have its node. When crash happen, try to type something like this in debugger console :
po firstBody.node, or po secondBody.node. One of these two will be nil.
This is happening when more than two bodies make contact as in your example, where you can have a situation where bullet and a two asteroids might be in a contact at the same time. Because SpriteKit can check for a contact only between two bodies at the time, something like this will happen:
didBeginContact is invoked with two physicsBodies passed in (bullet and first asteroide)
now, you are force unwrapping nodes associated with those bodies and removing the asteroid and the bullet from its parent
then, because there are more contacts occurred
didBeginContact is invoked again, with another two physics bodies, but one of those physicsBodies is bullet's physics body again. Another body is , let say furious asteroid.
now, again you are force unwrapping nodes associated with those two physics bodies, but one of them (bullet) is nil.
Solution would be something like this in your didBeginContact method:
if let firstNode = firstBody.node as? SKSpriteNode, let secondNode = secondBody.node as? SKSpriteNode {
bulletHitAsteroids(firstNode, Bullet: secondNode)
}
This way, one bullet will destroy only one asteroid. Which I guess is what you want and what make sense after all.

Related

SKSpriteNode disappear in GameScene

I'm facing some problem with spritekit in swift.
I was following closely to online tutorials (combining different tutorials into 1 project), trying out the code when I realised my SKSpriteNodes (my "player" and "enemy") sometimes go missing when I try it out on simulator or my iphone.
My situation is kinda similar to this user's problem here, but I don't think my problem lies with the size.
Can anyone enlighten me? Thank you!
Here's my code.
var player : SKSpriteNode!
var backdrop : SKSpriteNode!
var gameTimer : Timer!
var possibleEnemies = ["enemy01", "enemy02", "enemy03"]
let bulletsCategory : UInt32 = 0x1 << 0
let enemyCategory : UInt32 = 0x1 << 1
override func didMove(to view: SKView) {
player = SKSpriteNode(imageNamed: "bird.png")
player.position = CGPoint(x: 0, y: (player.size.height / 2) )
self.addChild(player)
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.physicsWorld.contactDelegate = self
self.anchorPoint = CGPoint (x: 0.5 , y: 0)
createBackdrop()
scoreLabel = SKLabelNode(text: "Score: 0")
scoreLabel.position = CGPoint(x: 260, y: self.frame.size.height - 90)
scoreLabel.fontName = "Avenir Book"
scoreLabel.fontSize = 35
scoreLabel.fontColor = UIColor.gray
score = 0
self.addChild(scoreLabel)
gameTimer = Timer.scheduledTimer(timeInterval: 0.75, target: self, selector: #selector(addEnemies), userInfo: nil, repeats: true)
}
#objc func addEnemies() {
possibleEnemies = GKRandomSource.sharedRandom().arrayByShufflingObjects(in: possibleEnemies) as! [String]
let enemy = SKSpriteNode(imageNamed: possibleEnemies[0])
let randomEnemyPosition = GKRandomDistribution(lowestValue: -360, highestValue: 360)
let position = CGFloat(randomEnemyPosition.nextInt())
enemy.position = CGPoint(x: position, y: self.frame.size.height + enemy.size.height)
enemy.physicsBody = SKPhysicsBody(rectangleOf: enemy.size)
enemy.physicsBody?.isDynamic = true
enemy.physicsBody?.categoryBitMask = enemyCategory
enemy.physicsBody?.contactTestBitMask = bulletsCategory
enemy.physicsBody?.collisionBitMask = 0
self.addChild(enemy)
let animationDuration : TimeInterval = 6
var actionArray = [SKAction]()
actionArray.append(SKAction.move(to: CGPoint(x: position, y: -enemy.size.height), duration: animationDuration))
actionArray.append(SKAction.removeFromParent())
enemy.run(SKAction.sequence(actionArray))
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
fireBullets()
}
func fireBullets() {
self.run(SKAction.playSoundFileNamed("shoot.wav", waitForCompletion: false))
let bullets = SKSpriteNode(imageNamed: "bullet.png")
bullets.position = player.position
bullets.position.y += 5
bullets.physicsBody = SKPhysicsBody(rectangleOf: bullets.size)
bullets.physicsBody?.isDynamic = true
bullets.physicsBody?.categoryBitMask = bulletsCategory
bullets.physicsBody?.contactTestBitMask = enemyCategory
bullets.physicsBody?.collisionBitMask = 0
bullets.physicsBody?.usesPreciseCollisionDetection = true
self.addChild(bullets)
let animationDuration : TimeInterval = 0.3
var actionArray = [SKAction]()
actionArray.append(SKAction.move(to: CGPoint(x: player.position.x, y: self.frame.size.height + 10), duration: animationDuration))
actionArray.append(SKAction.removeFromParent())
bullets.run(SKAction.sequence(actionArray))
}
func didBegin(_ contact: SKPhysicsContact) {
var firstBody : SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if (firstBody.categoryBitMask & bulletsCategory) != 0 && (secondBody.categoryBitMask & enemyCategory) != 0 {
hitByBullets(bulletNode: firstBody.node as! SKSpriteNode, enemyNode: secondBody.node as! SKSpriteNode)
}
}
func hitByBullets (bulletNode: SKSpriteNode, enemyNode: SKSpriteNode) {
let shot = SKEmitterNode(fileNamed: "Magic01")!
shot.position = enemyNode.position
self.addChild(shot)
self.run(SKAction.playSoundFileNamed("shot.mp3", waitForCompletion: false))
bulletNode.removeFromParent()
enemyNode.removeFromParent()
self.run(SKAction.wait(forDuration: 2)) {
shot.removeFromParent()
}
score += 1
}
func touchDown(atPoint pos : CGPoint) {
player.position = pos
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
moveBackdrop()
}
the issue for you sprites not showing up is that none of your objects have a zPosition set on them. You need to layer the objects as you expect them to show in the scene.
for example...
background.zPosition = 1
player.zPosition = 1
enemy.zPosition = 1
bullet.zPosition = 2
scoreLabel.zPosition = 100
In my opinion you shouldn't be using timers to generate your enemies. Spritekit has it's own timing functionality built into the update function. Which you are already using to control the timing of the backgrounds.
You had waaaaay to much code in your question, you need to look at how I've tailored the code down to only relevant code to your question. Including all of your code in your question actually makes it more unlikely that you will get the help or answers you need because it is harder to go through all the code to figure out what is happening. Also don't include so many spaces in your code in your question scrolling through hundreds of lines even if a lot of them are spaces is very tedious.
Didn't realised the importance of zPosition since my items show up perfectly on screen some of the times. Added the following in their respective place and they stop disappearing intermittently.
player.zPosition = 3
scoreLabel.zPosition = 100
enemy.zPosition = 3
bullets.zPosition = 2
backdrop.zPosition = 1
shot.zPosition = 3

having a node follow at a constant speed

I'm trying to make a small mini game where you drag a ball around the screen and every 10 seconds a ball gets added in that follows you. so far the you can drag a ball around the screen and a ball follows you, but when another ball gets added in the balls group together. I think this is because the ball is following me depending on how fast I'm going. so is there a certain way in which I can have the balls follow me at a certain speed constantly, like 10 pixels a second or something, and that should prevent the balls from grouping together.
I am currently working on the score so it should soon go up every second you survive. and you die if you touch one of the balls.
below is the code and a short gif of my current code
!(https://gyazo.com/1d6a56527bfd0884e8a26cff730f4e03)
import SpriteKit
import GameplayKit
struct physicsCatagory{
static let me : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2
}
class GameScene: SKScene, SKPhysicsContactDelegate {
private func makeEnemyName() -> String {
enemyCounter += 1
return "enemy\(enemyCounter)"
}
private func addEnemyToDict(enemy: SKSpriteNode, target: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = (enemy, target) }
else { print("enemy not found") }
}
private func removeEnemyFromDict(enemy: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = nil }
else { print("enemy not removed from dictionary!") }
}
private func moveFollowerToTarget(_ sprites: FollowerAndTarget) {
let action = SKAction.move(to: sprites.target.position, duration: 1)
sprites.follower.run(action)
}
private func allEnemiesMoveToTarget() {
for sprites in spriteDictionary.values {
moveFollowerToTarget(sprites)
}
}
let enemySpeed: CGFloat = 300
var me = SKSpriteNode()
// Tuple to keep track of enemy objects:
typealias FollowerAndTarget = (follower: SKSpriteNode, target: SKSpriteNode)
// [followerName: (followerSprite, targetSprite):
var spriteDictionary: [String: FollowerAndTarget] = [:]
// Give each enemy a unique name for the dictionary:
var enemyCounter = 0
var died = Bool()
override func didMove(to view: SKView) {
createScene()
}
func createEnemy () {
if died == true{
}
else {
let enemy = SKSpriteNode(imageNamed: "enemy1")
enemy.name = makeEnemyName()
addEnemyToDict(enemy: enemy, target: me)
moveFollowerToTarget((follower: enemy, target: me))
enemy.size = CGSize(width: 60, height: 60)
enemy.position = CGPoint(x:667, y: 200)
enemy.physicsBody?.restitution = 0.5
enemy.physicsBody = SKPhysicsBody(circleOfRadius: 60)
enemy.physicsBody?.affectedByGravity = false
enemy.zPosition = 2
enemy.physicsBody?.linearDamping = 0
enemy.physicsBody?.isDynamic = true
enemy.physicsBody?.categoryBitMask = physicsCatagory.enemy
enemy.physicsBody?.collisionBitMask = physicsCatagory.me
enemy.physicsBody?.contactTestBitMask = physicsCatagory.me
addChild(enemy)
}
}
func didBegin(_ contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.me && secondBody.categoryBitMask == physicsCatagory.enemy || firstBody.categoryBitMask == physicsCatagory.enemy && secondBody.categoryBitMask == physicsCatagory.me {
died = true
restartScene()
}
}
var lose: SKLabelNode!
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
died = false
if let nextScene = GameScene(fileNamed: "menuScene"){
nextScene.scaleMode = self.scaleMode
let transition = SKTransition.fade(withDuration: 1)
view?.presentScene(nextScene, transition: transition)
}
}
func createScene(){
me = self.childNode(withName: "me") as! SKSpriteNode
me.physicsBody = SKPhysicsBody(circleOfRadius: 20)
me.physicsBody?.affectedByGravity = false
me.physicsBody?.categoryBitMask = physicsCatagory.me
me.physicsBody?.collisionBitMask = physicsCatagory.enemy
me.zPosition = 2
self.physicsWorld.contactDelegate = self
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createEnemy), SKAction.wait(forDuration: 4.0)])))
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func update(_ currentTime: TimeInterval) {
// Will iterate through dictonary and then call moveFollowerToTarget()
// thus giving each enemy a new movement action to follow.
allEnemiesMoveToTarget()
}
}
Here you go:
import SpriteKit
import GameplayKit
struct physicsCatagory{
static let me : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2
static let coin : UInt32 = 0x1 << 3
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var lose: SKLabelNode!
var me = SKSpriteNode()
// Tuple to keep track of enemy objects:
typealias FollowerAndTarget = (follower: SKSpriteNode, target: SKSpriteNode)
// [followerName: (followerSprite, targetSprite):
var spriteDictionary: [String: FollowerAndTarget] = [:]
// Give each enemy a unique name for the dictionary:
var enemyCounter = 0
let enemySpeed: CGFloat = 3
var died = Bool()
var timer = SKLabelNode()
var timerValue: Int = 0 {
didSet {
timer.text = "\(timerValue)"
}
}
private func makeEnemyName() -> String {
enemyCounter += 1
return "enemy\(enemyCounter)"
}
private func addEnemyToDict(enemy: SKSpriteNode, target: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = (enemy, target) }
else { print("enemy not found") }
}
private func removeEnemyFromDict(enemy: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = nil }
else { print("enemy not removed from dictionary!") }
}
// dont change anything outside of this, this is what makes the enemy follow you, so i have to have the enemy follow me at a constant speed
private func moveFollowerToTarget(_ sprites: FollowerAndTarget) {
let location = me.position
// Aim
let dx = location.x - sprites.follower.position.x
let dy = location.y - sprites.follower.position.y
let angle = atan2(dy, dx)
sprites.follower.zRotation = angle
// Seek
let vx = cos(angle) * enemySpeed
let vy = sin(angle) * enemySpeed
sprites.follower.position.x += vx
sprites.follower.position.y += vy
}
private func allEnemiesMoveToTarget() {
for sprites in spriteDictionary.values {
moveFollowerToTarget(sprites)
}
}
private func keepEnemiesSeparated() {
for sprites in spriteDictionary.values {
let iterator = sprites.follower
iterator.constraints = []
// get every other follower:
var otherFollowers: [SKSpriteNode] = []
for sprites in spriteDictionary.values {
if sprites.follower == iterator { continue }
else { otherFollowers.append(sprites.follower) }
}
// Assign constrain
for follower in otherFollowers {
let distanceBetween = CGFloat(60)
let constraint = SKConstraint.distance(SKRange(lowerLimit: distanceBetween), to: follower)
iterator.constraints!.append(constraint)
}
}
}
func createEnemy () {
if died { return }
let enemy = SKSpriteNode(color: .green, size: CGSize(width: 60, height: 60))
enemy.size = CGSize(width: 60, height: 60)
enemy.zPosition = 2
enemy.position.y -= size.height / 2
enemy.physicsBody = {
let pb = SKPhysicsBody(circleOfRadius: 30)
pb.restitution = 0.5
pb.affectedByGravity = false
pb.linearDamping = 0
pb.isDynamic = true
pb.categoryBitMask = physicsCatagory.enemy
pb.collisionBitMask = physicsCatagory.me
pb.contactTestBitMask = physicsCatagory.me
return pb
}()
enemy.name = makeEnemyName()
addEnemyToDict(enemy: enemy, target: me)
moveFollowerToTarget((follower: enemy, target: me))
keepEnemiesSeparated()
addChild(enemy)
}
func createCoin () {
let coin = SKSpriteNode(color: .yellow, size: CGSize(width: 20, height: 20))
let height = self.view!.frame.height
let width = self.view!.frame.width
let randomPosition = CGPoint( x:CGFloat( arc4random_uniform( UInt32( floor( width ) ) ) ),
y:CGFloat( arc4random_uniform( UInt32( floor( height ) ) ) )
)
coin.position = randomPosition
addChild(coin)
}
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
died = false
let nextScene = GameScene(size: self.size)
nextScene.scaleMode = self.scaleMode
let transition = SKTransition.fade(withDuration: 1)
view?.presentScene(nextScene, transition: transition)
}
func createScene(){
me = SKSpriteNode(color: .blue, size: CGSize(width: 60, height: 60))
me.physicsBody = SKPhysicsBody(circleOfRadius: 30)
me.physicsBody?.affectedByGravity = false
me.physicsBody?.categoryBitMask = physicsCatagory.me
me.physicsBody?.collisionBitMask = physicsCatagory.enemy
me.zPosition = 2
timer = SKLabelNode(fontNamed: "Chalkduster")
timer.text = "\(timerValue)"
addChild(me)
addChild(timer)
let wait = SKAction.wait(forDuration: 1)
let block = SKAction.run({
[unowned self] in
if self.timerValue >= 0{
self.timerValue += 1
}else{
self.removeAction(forKey: "countdown")
}
})
let sequence = SKAction.sequence([wait,block])
run(SKAction.repeatForever(sequence), withKey: "countdown")
self.physicsWorld.contactDelegate = self
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createEnemy), SKAction.wait(forDuration: 2.0)])))
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createCoin), SKAction.wait(forDuration: TimeInterval(arc4random_uniform(11) + 5))])))
}
override func didMove(to view: SKView) {
scene?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
createScene()
}
func didBegin(_ contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.me && secondBody.categoryBitMask == physicsCatagory.enemy
|| firstBody.categoryBitMask == physicsCatagory.enemy && secondBody.categoryBitMask == physicsCatagory.me {
died = true
restartScene()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func update(_ currentTime: TimeInterval) {
// Will iterate through dictonary and then call moveFollowerToTarget()
// thus giving each enemy a new movement action to follow.
allEnemiesMoveToTarget()
}
}

Moving objects to the center of the screen

I'm having a coding issue right now. I have a two walls/blocks moving to the center of the screen, but when they reach the center they don't stop once they reached the center. How do I make them stop after they reach/touch each other/the center.
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
/* Called when a touch begins */
for touch in touches {
let location = touch.locationInNode(self)
if (playButton.containsPoint(location))
{
playButton.removeFromParent()
title.removeFromParent()
//Wall Timer
wallTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: ("walls"), userInfo: nil, repeats: false)
//Physics World
self.physicsWorld.gravity = CGVectorMake(0.0, -5.0)
}
else
{}
}
}
func didBeginContact(contact: SKPhysicsContact)
{
if contact.bodyA.node != nil && contact.bodyB.node != nil {
let firstBody = contact.bodyA.node as! SKSpriteNode
let secondBody = contact.bodyB.node as! SKSpriteNode
if ((firstBody.name == "leftWall") && (secondBody.name == "rightWall")) {
collisionWalls(firstBody, rightWall: secondBody)
}
else if ((firstBody.name == "rightWall") && (secondBody.name == "leftWall")) {
collisionWalls(secondBody, rightWall: firstBody)
}
}
}
func collisionWalls(leftWall : SKSpriteNode, rightWall : SKSpriteNode)
{
leftWall.removeAllActions()
rightWall.removeAllActions()
}
func walls() {
let leftWall = SKSpriteNode(imageNamed: "blue background1")
let rightWall = SKSpriteNode(imageNamed: "blue background1")
//Left Wall Code
leftWall.size = CGSizeMake(300, 90)
leftWall.position = CGPoint(x: scene!.frame.width / 6, y: scene!.frame.height / 6)
leftWall.zPosition = 1.0
leftWall.physicsBody = SKPhysicsBody(rectangleOfSize: leftWall.size)
leftWall.physicsBody?.affectedByGravity = false
leftWall.physicsBody?.dynamic = false
leftWall.name = "leftWall"
leftWall.physicsBody?.categoryBitMask = PhysicsCatagory.leftWall
leftWall.physicsBody?.collisionBitMask = PhysicsCatagory.rightWall
leftWall.physicsBody?.contactTestBitMask = PhysicsCatagory.rightWall
leftWall.removeFromParent()
self.addChild(leftWall)
//Right Wall Code
rightWall.size = CGSizeMake(300, 90)
rightWall.position = CGPointMake(self.size.width * 0.87, scene!.frame.height / 6)
rightWall.zPosition = 1.0
rightWall.physicsBody = SKPhysicsBody(rectangleOfSize: rightWall.size)
rightWall.physicsBody?.affectedByGravity = false
rightWall.physicsBody?.dynamic = false
rightWall.name = "rightWall"
rightWall.physicsBody?.categoryBitMask = PhysicsCatagory.rightWall
rightWall.physicsBody?.collisionBitMask = PhysicsCatagory.leftWall
rightWall.physicsBody?.contactTestBitMask = PhysicsCatagory.leftWall
rightWall.removeFromParent()
self.addChild(rightWall)
//Right and Left Wall actions
let moveLeft = SKAction.moveToX(scene!.frame.width * 1.35, duration: 5.0)
let moveRight = SKAction.moveToX(self.size.width * -0.59, duration: 5.0)
leftWall.runAction(SKAction.sequence([moveLeft]))
rightWall.runAction(SKAction.sequence([moveRight]))
}
The SKActions are not stopping at the middle of the screen. Try this:
let moveLeft = SKAction.moveToX(scene!.frame.width / 2, duration: 5.0)
let moveRight = SKAction.moveToX(scene!.frame.width / 2, duration: 5.0)
Have you tested to see if func didBeginContact(contact: SKPhysicsContact) gets fired?If it does not, than this is a problem I once had, Until I realized that this class (the one that contains func didBeginContact(contact: SKPhysicsContact)) must be set as the SKScene's contactdelegateafter that it should work.(if not please say so)
Or in your case: you should make sure self.contactdelegate = self.

Game stops working when restart button clicked

I have just started programming this past week and have been trying to make a simple game app for IOS. Everything had worked properly regarding what I want the game to be doing when playing it. However, after I lose and get taken to my end scene, when I click the restart button, the app appears to take me back to the game scene but instead opens up a dark brown screen and just stays there for a few seconds before going back to the end scene. Then, if I click the restart button again after being taken back to the end scene, it repeats.
It also appears that how long the brown screen lasts is dependent on the sharkTimer with the fastest time interval. So if the fastest on is generating a shark every half a second, the brown screen lasts for half a second before transferring to the end scene.
The game is really simple as the character is a fish that swims up and down and the goal of the game to eat little things called food and to avoid other things called sharks that swim toward you.
Here is a link to my project:
https://www.dropbox.com/sh/z8o3iunz9rng6na/AACDGGOTR-QhqbQc402y4sgRa?dl=0
This is what I've got so far in my GameScene.swift file:
import SpriteKit
import UIKit
struct physicsCategory
{
static let shark: UInt32 = 1
static let food: UInt32 = 2
static let fish: UInt32 = 3
}
class GameScene: SKScene, SKPhysicsContactDelegate
{
var score = Int()
var scoreLabel = UILabel()
var fish = SKSpriteNode(imageNamed: "fish1 copy.png")
var shark = SKSpriteNode(imageNamed: "shark1 copy.png")
var food = SKSpriteNode(imageNamed: "fish game point copy.png")
override func didMoveToView(view: SKView)
{
physicsWorld.contactDelegate = self
self.scene?.backgroundColor = UIColor(red: 117/255.0, green: 208/255.0, blue: 224/255.0, alpha: 1.0)
fish.setScale(0.15)
fish.position = CGPointMake(self.frame.size.width * 0.1, self.frame.size.height * 0.5)
fish.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(35, 40))
fish.physicsBody?.affectedByGravity = false
fish.physicsBody?.categoryBitMask = physicsCategory.fish
fish.physicsBody?.contactTestBitMask = physicsCategory.shark
fish.physicsBody?.contactTestBitMask = physicsCategory.food
fish.physicsBody?.dynamic = false
self.addChild(fish)
var sharkTimer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("SpawnShark"), userInfo: nil, repeats: true)
var sharkTimer2 = NSTimer.scheduledTimerWithTimeInterval(2.33, target: self, selector: Selector("SpawnShark"), userInfo: nil, repeats: true)
var sharkTimer3 = NSTimer.scheduledTimerWithTimeInterval(2.79, target: self, selector: Selector("SpawnShark"), userInfo: nil, repeats: true)
var foodTimer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: Selector("SpawnFood"), userInfo: nil, repeats: true)
scoreLabel.text = "\(score)"
scoreLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
scoreLabel.backgroundColor = UIColor(red: 0.1, green: 0.1, blue: 0.1, alpha: 0.3)
scoreLabel.textColor = UIColor.whiteColor()
self.view?.addSubview(scoreLabel)
}
func SpawnShark()
{
var shark = SKSpriteNode(imageNamed: "shark1 copy.png")
shark.setScale(0.33)
var MinValue = self.size.height - self.size.height
var MaxValue = self.size.height
var SpawnPoint = UInt32(MaxValue - MinValue)
shark.position = CGPoint(x: self.size.width , y: CGFloat(arc4random_uniform(SpawnPoint)))
let action = SKAction.moveToX(-70, duration: 3.0)
shark.runAction(SKAction.repeatActionForever(action))
let actionDone = SKAction.removeFromParent()
shark.runAction(SKAction.sequence([action, actionDone]))
shark.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(100, 20))
shark.physicsBody?.affectedByGravity = false
shark.physicsBody?.categoryBitMask = physicsCategory.shark
shark.physicsBody?.contactTestBitMask = physicsCategory.fish
shark.physicsBody?.dynamic = true
self.addChild(shark)
}
func SpawnFood()
{
var food = SKSpriteNode(imageNamed: "fish game point copy.png")
food.setScale(0.1)
var MinValue = self.size.height - self.size.height + 10
var MaxValue = self.size.height - 10
var SpawnPoint = UInt32(MaxValue - MinValue)
food.position = CGPoint(x: self.size.width , y: CGFloat(arc4random_uniform(SpawnPoint)))
let action = SKAction.moveToX(-70, duration: 5.0)
food.runAction(SKAction.repeatActionForever(action))
let actionDone = SKAction.removeFromParent()
food.runAction(SKAction.sequence([action, actionDone]))
food.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(10, 10))
food.physicsBody?.affectedByGravity = false
food.physicsBody?.categoryBitMask = physicsCategory.food
food.physicsBody?.contactTestBitMask = physicsCategory.fish
food.physicsBody?.dynamic = true
self.addChild(food)
}
func didBeginContact(contact: SKPhysicsContact)
{
var firstBody: SKPhysicsBody = contact.bodyA
var secondBody: SKPhysicsBody = contact.bodyB
if (firstBody.categoryBitMask == physicsCategory.fish) && (secondBody.categoryBitMask == physicsCategory.food) ||
(firstBody.categoryBitMask == physicsCategory.food) && (secondBody.categoryBitMask == physicsCategory.fish)
{
CollisionWithFood(firstBody.node as! SKSpriteNode, food: secondBody.node as! SKSpriteNode)
}
else if (firstBody.categoryBitMask == physicsCategory.shark) && (secondBody.categoryBitMask == physicsCategory.fish) ||
(firstBody.categoryBitMask == physicsCategory.fish) && (secondBody.categoryBitMask == physicsCategory.shark)
{
CollisionWithFish(firstBody.node as! SKSpriteNode, fish: secondBody.node as! SKSpriteNode)
}
}
func CollisionWithFood(fish: SKSpriteNode, food: SKSpriteNode)
{
food.removeFromParent()
score++
scoreLabel.text = "\(score)"
}
func CollisionWithFish(shark: SKSpriteNode, fish: SKSpriteNode)
{
fish.removeFromParent()
scoreLabel.removeFromSuperview()
self.view?.presentScene(EndScene())
self.view?.presentScene(EndScene(), transition: SKTransition.crossFadeWithDuration(1.0))
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent)
{
for touch: AnyObject in touches
{
let location = touch.locationInNode(self)
fish.position.y = location.y
}
}
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
for touch: AnyObject in touches
{
let location = touch.locationInNode(self)
fish.position.y = location.y
}
}
override func update(currentTime: CFTimeInterval)
{
/* Called before each frame is rendered */
}
}
My second file called EndScene.swift is where the program goes to if the shark gets you and the game ends. Its a white screen with a little restart button in the upper middle of the screen that when you press it, should take you back to the game scene, but instead takes you to a dark brown one.
Here is my EndScene.swift file:
import Foundation
import SpriteKit
class EndScene: SKScene
{
var restartButton: UIButton!
override func didMoveToView(view: SKView)
{
scene?.backgroundColor = UIColor.whiteColor()
restartButton = UIButton(frame: CGRect(x: 0, y: 0, width: view.frame.size.width / 3, height: 30))
restartButton.center = CGPoint(x: view.frame.size.width / 2, y: view.frame.size.width / 7)
restartButton.setTitle("Restart", forState: UIControlState.Normal)
restartButton.setTitleColor(UIColor.darkGrayColor(), forState: UIControlState.Normal)
restartButton.addTarget(self, action: Selector("Restart"), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(restartButton)
}
func Restart()
{
self.view?.presentScene(GameScene(), transition: SKTransition.crossFadeWithDuration(0.3))
restartButton.removeFromSuperview()
}
}
You should add self.view to GameScene init when presenting the scene
func Restart()
{
self.view?.presentScene(GameScene(size: view.frame.size), transition: SKTransition.crossFadeWithDuration(0.3))
restartButton.removeFromSuperview()
}

Swift Physics-fatal error: unexpectedly found nil while unwrapping an Optional value when two characters collide

Background on game: Basically you control a character that moves right and left and try to dodge falling blocks. There are three players spawned. One in the middle of the screen, and two exactly size.width away from the middle player on either sides.
This error only happens once in around 10 collisions with the playerRight or playerLeft or Player and falling blocks. As you can see by the screenshot below, the player does not seem to be touching the falling block when it crashes.
Error Code and Screenshots:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_l386_INVOP, subcode=0x0)
How the game scene stopped
I'm thinking it has something to do with how I built the "infinitely" horizontal scrolling player. Basically I have three separate characters and once the middle character goes past size.width or below 0 his position on the screen is changed to the opposite side of the screen essentially making it infinite. Maybe the Player is teleported inside of a block and it gives a nil error. Not really sure but it looks like it has something to do with that. Anyway, heres the relevant code from GameScene.
import SpriteKit
import Foundation
import UIKit
//Collisions
struct PhysicsCategory {
static let Enemy : UInt32 = 1
static let Player : UInt32 = 2
static let PlayerRight : UInt32 = 3
static let PlayerLeft : UInt32 = 4
static let EnemyRight : UInt32 = 5
}
var transition:SKTransition = SKTransition.fadeWithDuration(0.5)
class GameScene: SKScene, SKPhysicsContactDelegate {
//Highscore Variable
var Highscore = Int()
//Score
var Score : Int = 0
var ScoreLabel = UILabel()
//Main Character
var Player = SKSpriteNode(imageNamed: "mainPlayer.png")
//Right-far character
var PlayerRight = SKSpriteNode(imageNamed: "mainPlayer.png")
//Left-far character
var PlayerLeft = SKSpriteNode(imageNamed: "mainPlayer.png")
//Holding vs Tapping Movement of Player
var isTouching = false
var touchXPosition:CGFloat = 0
override func didMoveToView(view: SKView) {
/* Setup your scene here */
//Highscore
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
if (HighscoreDefault.valueForKey("Highscore") != nil) {
Highscore = HighscoreDefault.valueForKey("Highscore") as! NSInteger
}
else {
Highscore = 0
}
//Collisions/Physics
physicsWorld.contactDelegate = self
//Background Color
scene?.backgroundColor = UIColor.blackColor()
//Spawn timer for enemy blocks
var timer = NSTimer.scheduledTimerWithTimeInterval(0.4, target: self, selector: Selector("spawnEnemies"), userInfo: nil, repeats: true)
//Timer for keeping score
var scoretimer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("scoreCounter"), userInfo: nil, repeats: true)
//Player coordinates
Player.position.x = size.width * 0.5
Player.position.y = size.width * 0.11 / 2
//Setting Player Sizes
Player.size.width = size.width * 0.11
Player.size.height = size.width * 0.11
PlayerRight.size.width = size.width * 0.11
PlayerRight.size.height = size.width * 0.11
PlayerLeft.size.width = size.width * 0.11
PlayerLeft.size.height = size.width * 0.11
//Initial position of player
Player.position = CGPoint(x: Player.position.x, y: Player.position.y)
//Initial position of far-right player
PlayerRight.position = CGPoint(x: Player.position.x + size.width, y: Player.position.y)
//Initial position of far-left player
PlayerLeft.position = CGPoint(x: Player.position.x - size.width, y: Player.position.y)
//Adding Physics/Collisions to Player
Player.physicsBody = SKPhysicsBody (rectangleOfSize: Player.size)
Player.physicsBody?.affectedByGravity = false
Player.physicsBody?.categoryBitMask = PhysicsCategory.Player
Player.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
Player.physicsBody?.dynamic = false
//Adding Physics/Collisions to PlayerRight
PlayerRight.physicsBody = SKPhysicsBody (rectangleOfSize: PlayerRight.size)
PlayerRight.physicsBody?.affectedByGravity = false
PlayerRight.physicsBody?.categoryBitMask = PhysicsCategory.PlayerRight
PlayerRight.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
PlayerRight.physicsBody?.dynamic = false
//Adding Physics/Collisions to PlayerLeft
PlayerLeft.physicsBody = SKPhysicsBody (rectangleOfSize: PlayerRight.size)
PlayerLeft.physicsBody?.affectedByGravity = false
PlayerLeft.physicsBody?.categoryBitMask = PhysicsCategory.PlayerLeft
PlayerLeft.physicsBody?.contactTestBitMask = PhysicsCategory.Enemy
PlayerLeft.physicsBody?.dynamic = false
//Making Players visible
self.addChild(Player)
self.addChild(PlayerRight)
self.addChild(PlayerLeft)
//Making Score Visible
ScoreLabel.text = "\(Score)"
ScoreLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20))
ScoreLabel.font = UIFont(name: ScoreLabel.font.fontName, size:20)
ScoreLabel.textColor = UIColor.whiteColor()
self.view?.addSubview(ScoreLabel)
}
func scoreCounter() {
//Setting score
Score += 1
ScoreLabel.text = "\(Score)"
}
func didBeginContact(contact: SKPhysicsContact) {
var firstBody : SKPhysicsBody = contact.bodyA
var secondBody : SKPhysicsBody = contact.bodyB
//Checking for Player to enemy collisions
if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.Player)){
CollisionWithEnemy(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)
}
else if (firstBody.categoryBitMask == PhysicsCategory.Player) && (secondBody.categoryBitMask == PhysicsCategory.Enemy) {
CollisionWithEnemy2(firstBody.node as! SKSpriteNode, Enemy: secondBody.node as! SKShapeNode)
}
//Checking for PlayerRight to enemy collisions
if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.PlayerRight)){
CollisionWithEnemy(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)
}
else if (firstBody.categoryBitMask == PhysicsCategory.PlayerRight) && (secondBody.categoryBitMask == PhysicsCategory.Enemy) {
CollisionWithEnemy2(firstBody.node as! SKSpriteNode, Enemy: secondBody.node as! SKShapeNode)
}
//Checking for PlayerLeft to enemy collisions
if ((firstBody.categoryBitMask == PhysicsCategory.Enemy) && (secondBody.categoryBitMask == PhysicsCategory.PlayerLeft)){
CollisionWithEnemy(firstBody.node as! SKShapeNode, Player: secondBody.node as! SKSpriteNode)
}
else if (firstBody.categoryBitMask == PhysicsCategory.PlayerLeft) && (secondBody.categoryBitMask == PhysicsCategory.Enemy) {
CollisionWithEnemy2(firstBody.node as! SKSpriteNode, Enemy: secondBody.node as! SKShapeNode)
}
}
func CollisionWithEnemy(Enemy: SKShapeNode, Player: SKSpriteNode) {
//Highscore
var ScoreDefault = NSUserDefaults.standardUserDefaults()
ScoreDefault.setValue(Score, forKey: "Score")
ScoreDefault.synchronize()
if (Score > Highscore) {
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
HighscoreDefault.setValue(Score, forKey: "Highscore")
}
//var gameOver:SKScene = GameOverScene(size: self.size)
//ScoreLabel.removeFromSuperview()
Enemy.removeFromParent()
//Player.removeFromParent()
//self.view?.presentScene(gameOver, transition: transition)
}
func CollisionWithEnemy2(Player: SKSpriteNode, Enemy: SKShapeNode) {
//Highscore
var ScoreDefault = NSUserDefaults.standardUserDefaults()
ScoreDefault.setValue(Score, forKey: "Score")
ScoreDefault.synchronize()
if (Score > Highscore) {
var HighscoreDefault = NSUserDefaults.standardUserDefaults()
HighscoreDefault.setValue(Score, forKey: "Highscore")
}
//var gameOver:SKScene = GameOverScene(size: self.size)
//ScoreLabel.removeFromSuperview()
Enemy.removeFromParent()
//Player.removeFromParent()
//self.view?.presentScene(gameOver, transition: transition)
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
/* Called when a touch begins */
isTouching = true
for touch in (touches as! Set<UITouch>) {
let location = touch.locationInNode(self)
touchXPosition = location.x
}
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
isTouching = false
}
func spawnEnemies() {
//Randomizing width of blocks
var blockWidth = Int(arc4random_uniform(UInt32(size.width / 3)) + UInt32(size.width / 5))
//Min and Max position of blocks
var minPosition : UInt32 = UInt32(blockWidth / 2)
var maxPosition : UInt32 = UInt32(size.width - CGFloat(blockWidth / 2))
//Randomizing Block Position
var blockXPosition = arc4random_uniform(maxPosition - minPosition) + minPosition
//Making Blocks
var Enemy = SKShapeNode(rectOfSize: CGSize(width: blockWidth, height: 5))
Enemy.position = CGPointMake (CGFloat(blockXPosition), CGFloat(size.height+50))
//Coloring Blocks
Enemy.fillColor = SKColor.whiteColor()
//Moving Blocks
let action = SKAction.moveToY(-50, duration: 2.5)
//Removing blocks once off screen
let actionDone = SKAction.removeFromParent()
//Running the above actions
Enemy.runAction(SKAction.sequence([action, actionDone]))
//Physics/Collisions
Enemy.physicsBody = SKPhysicsBody(rectangleOfSize: CGSize (width: blockWidth, height: 1))
Enemy.physicsBody?.categoryBitMask = PhysicsCategory.Enemy
Enemy.physicsBody?.affectedByGravity = false
Enemy.physicsBody?.dynamic = true
//Adding enemy to scene
self.addChild(Enemy)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
var offsetLeft = 0 - (Player.position.x - 25)
Player.position = CGPoint(x: Player.position.x, y: Player.position.y)
PlayerRight.position = CGPoint(x: Player.position.x + size.width, y: Player.position.y)
PlayerLeft.position = CGPoint(x: Player.position.x - size.width, y: Player.position.y)
if isTouching {
if touchXPosition > self.size.width / 2 {
// move character to the right.
Player.position.x += 10
}
if touchXPosition < self.size.width / 2 {
// move character to the left.
Player.position.x -= 10
}
}
if Player.position.x < 0 {
Player.position.x = size.width
}
if Player.position.x > size.width {
Player.position.x = 0
}
}
}
Everything is commented fairly well but if you have any questions about whats what let me know. Any help with this would be greatly appreciated!
static let PlayerRight : UInt32 = 3 //00000000000000000000000000000100
static let PlayerLeft : UInt32 = 4 //00000000000000000000000000001000
static let EnemyRight : UInt32 = 5 //00000000000000000000000000010000
Do you really believe that 3 is binary 100 and that 4 is binary 1000 (and so on)? Because if you do, and if you need that to be true, you are going to be in huge trouble later if you try to use these values as actual bitmasks.

Resources