I have a SpriteKit game I am building and I am loading a level from a multidimensional array. The loadlevel function works the first time. It does fail if I do a println of the physicsBody above the physicsBody assignment (after the initialization of the physicBody). When I remove all the tiles with removeChildrenInArray the secondtime I run load level it throws an error saying fatal error: unexpectedly found nil while unwrapping an Optional and it points to line right below the println below. And the println indicates that it is the physicsBody that is nil. In my mind there is no reason a freshly initialize PhysicsBody should ever be nil. The println prints physicsBody nil. I have no idea why the physicsBody would be nil. I am just trying to reset the level by removing all block nodes and adding new ones in the original place according to the level map.
func loadLevel() {
var levels = Levels().data
var frameSize = view.frame.size
var thisLevel = levels[currentLevel]
println("running load level")
for (rowIndex,row) in enumerate(thisLevel) {
for (colIndex,col) in enumerate(row) {
if col == 4 {
continue
}
println("COL: \(col)")
var tile = SKSpriteNode(texture: SKTexture(imageNamed: "brick_\(tileMap[col])"))
tile.name = "tile_\(rowIndex)_\(colIndex)"
tile.position.y = frameSize.height - (tile.size.height * CGFloat(rowIndex)) - (tile.size.height/2)
tile.position.x = tile.size.width * CGFloat(colIndex) + (tile.size.width/2)
var physicsBody = SKPhysicsBody(rectangleOfSize: tile.size)
tile.physicsBody = physicsBody
tile.physicsBody.affectedByGravity = false
tile.physicsBody.categoryBitMask = ColliderType.Block.toRaw()
tile.physicsBody.contactTestBitMask = ColliderType.Ball.toRaw()
tile.physicsBody.collisionBitMask = ColliderType.Ball.toRaw()
scene.addChild(tile)
tileCount++
}
}
}
Here is my ColliderType
enum ColliderType:UInt32 {
case Paddle = 1
case Block = 2
case Wall = 3
case Ball = 4
}
This is my reset function contents:
func reset() {
tileCount = 0
var removeTiles = [SKSpriteNode]()
// remove all the tiles
for child in scene.children {
var a_tile = child as SKSpriteNode
if a_tile.name.hasPrefix("tile_") {
a_tile.removeFromParent()
a_tile.name = ""
removeTiles.append(a_tile)
}
}
removeTiles.removeAll(keepCapacity: false)
ball!.position = CGPoint(x: 200, y: 200)
ballVel = CGPoint(x: 0, y: -5)
currentLevel++
loadLevel()
lost = false
won = false
}
Here is my Level structs
struct Tile {
let map = ["blue","green","purple","red"]
}
struct Levels {
let data = [
[
[4,4,0,4,0,4,0,4,0,4,0,4,0,0,4,4],
[4,4,1,4,1,4,1,4,1,4,1,4,1,1,4,4],
[4,4,2,4,2,4,2,4,2,4,2,4,2,2,4,4],
[4,4,3,4,3,4,3,4,3,4,3,4,3,3,4,4]
],
[
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[2,2,2,2,2,2,2,4,2,2,2,2,2,2,2,2],
[3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3]
]
]
}
If this is a bug in Swift I am trying to figure out a way around so I can just make this work.
Looks like SKPhysicsBody is instantiated with an empty size. Try to create the physics body object with an explicit size, like so:
var physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(100, 100))
Alternatively, you can set the size directly on the SKSpriteNode or use one of its constructors that take a CGSize construct like initWithTexture:color:size:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With