Physics of node not working.(Sprite kit) - ios

I am making a spritekit game where you need to move the player back and forth to catch objects falling down the screen. (You gain a point when the player collides with the falling object.)Recently I added restart button function. Before the restart button comes up everything works fine but when I restart the scene and the objects fall to hit the player the player falls off the screen once they make contact. This is odd because I have already set it to make the player (or person) not affected by gravity and not to be dynamic. Again before I press the button it works fine. Why are the characteristics of the person not there once I restart the scene. If you could take a look at my code and tell me why this is happening I would greatly appreciate it.
import SpriteKit
struct physicsCatagory {
static let person : UInt32 = 0x1 << 1
static let Ice : UInt32 = 0x1 << 2
static let IceTwo : UInt32 = 0x1 << 3
static let IceThree : UInt32 = 0x1 << 4
static let Score : UInt32 = 0x1 << 5
}
class GameScene: SKScene, SKPhysicsContactDelegate {
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
scorenumber = 0
lifenumber = 0
createScene()
random()
//spawnThirdIce()
Died = false
}
func createScene(){
physicsWorld.contactDelegate = self
lifenumber = 0
SpeedNumber = 1
BackGround.size = CGSize(width: self.frame.width, height: self.frame.height)
BackGround.position = CGPointMake(self.size.width / 2, self.size.height / 2)
BackGround.zPosition = -5
self.addChild(BackGround)
Score.size = CGSize(width: 2563, height: 1)
Score.position = CGPoint(x: 320, y: -20)
Score.physicsBody = SKPhysicsBody(rectangleOfSize: Score.size)
Score.physicsBody?.affectedByGravity = false
Score.physicsBody?.dynamic = false
Score.physicsBody?.categoryBitMask = physicsCatagory.Score
Score.physicsBody?.collisionBitMask = 0
Score.physicsBody?.contactTestBitMask = physicsCatagory.IceThree
Score.color = SKColor.blueColor()
Score.zPosition = -5
self.addChild(Score)
person.zPosition = 1
person.position = CGPointMake(self.size.width/2, self.size.height/10)
person.setScale(0.6)
person.physicsBody = SKPhysicsBody (rectangleOfSize: CGSize(width: 40, height: 50))
person.physicsBody?.affectedByGravity = false
person.physicsBody?.categoryBitMask = physicsCatagory.person
person.physicsBody?.contactTestBitMask = physicsCatagory.Ice
person.physicsBody?.collisionBitMask = physicsCatagory.Ice
person.physicsBody?.dynamic = false
person.physicsBody?.affectedByGravity = false
ScoreLable = SKLabelNode(fontNamed: "Zapfino")
ScoreLable.position = CGPoint(x: self.frame.width / 2, y: 1700)
ScoreLable.text = "\(scorenumber)"
ScoreLable.fontColor = UIColor.yellowColor()
ScoreLable.fontSize = 150
ScoreLable.fontName = "Zapfino "
self.addChild(ScoreLable)
self.addChild(person)
}
func random() -> CGFloat{
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min min: CGFloat, max: CGFloat) -> CGFloat{
return random() * (max - min) + min
}
var gameArea: CGRect
override init(size: CGSize) {
let maxAspectRatio: CGFloat = 16.0/9.0
let playableWidth = size.height / maxAspectRatio
let margin = (size.width - playableWidth) / 2
gameArea = CGRect(x: margin, y: 0, width: playableWidth, height: size.height)
super.init(size: size)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var timeOfLastSpawn: CFTimeInterval = 0.0
var timePerSpawn: CFTimeInterval = 1.2
var scorenumber = Int()
var lifenumber = Int()
var SpeedNumber : Double = 0.5
var person = SKSpriteNode(imageNamed: "Person1")
let Score = SKSpriteNode()
var ScoreLable = SKLabelNode()
let BackGround = SKSpriteNode (imageNamed: "BackGround")
var restartButton = SKSpriteNode()
var Died = Bool()
override func didMoveToView(view: SKView) {
createScene()
}
func createButton(){
restartButton = SKSpriteNode(color: SKColor.blueColor(), size: CGSize(width: 200, height: 100))
restartButton.position = CGPoint(x: self.gameArea.width/2, y: self.gameArea.height/2)
restartButton.zPosition = 6
self.addChild(restartButton)
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.person && secondBody.categoryBitMask == physicsCatagory.IceThree || firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.person{
scorenumber++
if scorenumber == 20 {
timePerSpawn = 1.0
}
if scorenumber == 40{
timePerSpawn = 0.89
}
if scorenumber == 60{
timePerSpawn = 0.6
}
if scorenumber == 80{
timePerSpawn = 0.5
}
if scorenumber == 100{
timePerSpawn = 0.4
}
if scorenumber == 120{
timePerSpawn = 0.3
}
ScoreLable.text = "\(scorenumber)"
CollisionWithPerson(firstBody.node as! SKSpriteNode, Person: secondBody.node as! SKSpriteNode)
}
if firstBody.categoryBitMask == physicsCatagory.Score && secondBody.categoryBitMask == physicsCatagory.IceThree ||
firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.Score{
lifenumber++
if lifenumber == 1{
//person.texture
person.texture = SKTexture (imageNamed: "Flower#2")
}
if lifenumber == 2{
person.texture = SKTexture (imageNamed: "Flower #3")
}
if lifenumber == 3{
createButton()
// self.view?.presentScene(EndScene())
Died = true
}
}
}
func CollisionWithPerson (Ice: SKSpriteNode, Person: SKSpriteNode){
Person.removeFromParent()
}
func spawnThirdIce(){
var Ice = SKSpriteNode(imageNamed: "Ice")
Ice.zPosition = 2
Ice.setScale(1.5)
Ice.physicsBody = SKPhysicsBody(rectangleOfSize: Ice.size)
Ice.physicsBody?.categoryBitMask = physicsCatagory.IceThree
Ice.physicsBody?.contactTestBitMask = physicsCatagory.person | physicsCatagory.Score
Ice.physicsBody?.affectedByGravity = false
Ice.physicsBody?.dynamic = true
let randomXStart = random(min:CGRectGetMinX(gameArea), max: CGRectGetMaxX(gameArea))
let randomXend = random(min:CGRectGetMinX(gameArea),max: CGRectGetMaxX(gameArea))
let startPoint = CGPoint(x: randomXStart, y: self.size.height * 1.2)
let endpoint = CGPoint(x: randomXend, y: -self.size.height * 0.2)
Ice.position = startPoint
let moveEnemy = SKAction.moveTo(endpoint, duration: 2.0)
let deleteEnemy = SKAction.removeFromParent()
let enemySequence = SKAction.sequence([moveEnemy , deleteEnemy])
Ice.runAction(enemySequence)
self.addChild(Ice)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches{
let location = touch.locationInNode(self)
if Died == true{
if restartButton.containsPoint(location){
restartScene()
}
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
if Died == true {
}
else{
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousTouch = touch.previousLocationInNode(self)
let ammountDragged = location.x - previousTouch.x
person.position.x += ammountDragged
if person.position.x > CGRectGetMaxX(gameArea) - person.size.width/2{
person.position.x = CGRectGetMaxX(gameArea) - person.size.width/2
}
if person.position.x < CGRectGetMinX(gameArea) + person.size.width/2{
person.position.x = CGRectGetMinX(gameArea) + person.size.width/2
}
}
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (currentTime - timeOfLastSpawn > timePerSpawn) {
spawnThirdIce()
self.timeOfLastSpawn = currentTime
}
}
}

Related

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()
}
}

Keeping an Object from moving beyond a certain point

Im am making a game in sprite kit that requires the user to move the player across the x axis to catch things. I am trying to make it impossible for the player to move off the screen because that looks bad. I have tried to do this with an if statement saying if it moves past a certain point teleport it back to the correct point but am not sure how to do this. That might be the right way to do this but i'm not sure. Please tell / show me what I should do to make this work. I will post the code below.
import SpriteKit
struct physicsCatagory {
static let person : UInt32 = 0x1 << 1
static let Ice : UInt32 = 0x1 << 2
static let IceTwo : UInt32 = 0x1 << 3
static let IceThree : UInt32 = 0x1 << 4
static let Score : UInt32 = 0x1 << 5
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var timeOfLastSpawn: CFTimeInterval = 0.0
var timePerSpawn: CFTimeInterval = 1.2
var scorenumber = Int()
var lifenumber = Int()
var SpeedNumber : Double = 0.5
var person = SKSpriteNode(imageNamed: "Person1")
let Score = SKSpriteNode()
var ScoreLable = SKLabelNode()
let BackGround = SKSpriteNode (imageNamed: "BackGround")
override func didMoveToView(view: SKView) {
self.scene?.backgroundColor = UIColor.blueColor()
physicsWorld.contactDelegate = self
self.scene?.size = CGSize(width: 640, height: 1136)
lifenumber = 0
SpeedNumber = 1
BackGround.size = CGSize(width: self.frame.width, height: self.frame.height)
BackGround.position = CGPointMake(self.size.width / 2, self.size.height / 2)
BackGround.zPosition = -5
self.addChild(BackGround)
Score.size = CGSize(width: 648, height: 1)
Score.position = CGPoint(x: 320, y: -90)
Score.physicsBody = SKPhysicsBody(rectangleOfSize: Score.size)
Score.physicsBody?.affectedByGravity = false
Score.physicsBody?.dynamic = false
Score.physicsBody?.categoryBitMask = physicsCatagory.Score
Score.physicsBody?.collisionBitMask = 0
Score.physicsBody?.contactTestBitMask = physicsCatagory.IceThree
Score.color = SKColor.blueColor()
self.addChild(Score)
person.zPosition = 1
person.position = CGPointMake(self.size.width/2, self.size.height/10)
person.setScale(0.32)
person.physicsBody = SKPhysicsBody (rectangleOfSize: CGSize(width: 40, height: 50))
person.physicsBody?.affectedByGravity = false
person.physicsBody?.categoryBitMask = physicsCatagory.person
person.physicsBody?.contactTestBitMask = physicsCatagory.Ice
person.physicsBody?.collisionBitMask = physicsCatagory.Ice
person.physicsBody?.dynamic = false
ScoreLable = SKLabelNode(fontNamed: "Zapfino")
ScoreLable.position = CGPoint(x: self.frame.width / 2, y: 1000)
ScoreLable.text = "\(scorenumber)"
ScoreLable.fontColor = UIColor.yellowColor()
ScoreLable.fontSize = 100
ScoreLable.fontName = "Zapfino "
self.addChild(ScoreLable)
self.addChild(person)
}
func didBeginContact(contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.person && secondBody.categoryBitMask == physicsCatagory.IceThree || firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.person{
scorenumber++
if scorenumber == 20 {
timePerSpawn = 1.0
}
if scorenumber == 40{
timePerSpawn = 0.89
}
if scorenumber == 60{
timePerSpawn = 0.6
}
if scorenumber == 80{
timePerSpawn = 0.5
}
if scorenumber == 100{
timePerSpawn = 0.4
}
if scorenumber == 120{
timePerSpawn = 0.3
}
ScoreLable.text = "\(scorenumber)"
CollisionWithPerson(firstBody.node as! SKSpriteNode, Person: secondBody.node as! SKSpriteNode)
}
if firstBody.categoryBitMask == physicsCatagory.Score && secondBody.categoryBitMask == physicsCatagory.IceThree ||
firstBody.categoryBitMask == physicsCatagory.IceThree && secondBody.categoryBitMask == physicsCatagory.Score{
lifenumber++
if lifenumber == 1{
//person.texture
person.texture = SKTexture (imageNamed: "Flower#2")
}
if lifenumber == 2{
person.texture = SKTexture (imageNamed: "Flower #3")
}
if lifenumber == 3{
self.view?.presentScene(EndScene())
}
}
}
func CollisionWithPerson (Ice: SKSpriteNode, Person: SKSpriteNode){
Person.removeFromParent()
}
func spawnThirdIce(){
var Ice = SKSpriteNode(imageNamed: "Ice")
Ice.zPosition = 2
Ice.setScale(0.9)
Ice.physicsBody = SKPhysicsBody(rectangleOfSize: Ice.size)
Ice.physicsBody?.categoryBitMask = physicsCatagory.IceThree
Ice.physicsBody?.contactTestBitMask = physicsCatagory.person | physicsCatagory.Score
Ice.physicsBody?.affectedByGravity = false
Ice.physicsBody?.dynamic = true
let MinValue = self.size.width / 8
let MaxValue = self.size.width - 20
let SpawnPoint = UInt32(MaxValue - MinValue)
Ice.position = CGPoint(x: CGFloat(arc4random_uniform(SpawnPoint)), y: self.size.height)
self.addChild(Ice)
let action = SKAction.moveToY(-85, duration: 2.0)
let actionDone = SKAction.removeFromParent()
Ice.runAction(SKAction.sequence([action,actionDone]))
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch: AnyObject in touches {
let location = touch.locationInNode(self)
let previousTouch = touch.previousLocationInNode(self)
let ammountDragged = location.x - previousTouch.x
person.position.x += ammountDragged
}
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
if (currentTime - timeOfLastSpawn > timePerSpawn) {
spawnThirdIce()
self.timeOfLastSpawn = currentTime
}
}
}
You might do something like:
if node.position.x > scene.width {
node.position.x = scene.width
}
if node.position.x < 0 {
node.position.x = 0
}

SpriteKit + Swift - Not Firing on contact

So I am playing around with Swift and SpriteKit. I decided to create a simple game where a character will walk to a chest of coins and get all the treasure.
I am trying to detect when the two objects contact eachother, however nothing seems to be happening.
What I did:
1) I set the delegate:
SKPhysicsContactDelegate
2) Created the scene:
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.whiteColor()
physicsWorld.contactDelegate = self
let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
sceneBody.friction = 0
background.zPosition = -20
background.anchorPoint = CGPointZero
background.position = CGPointZero
backgroundRepeated.zPosition = -20
backgroundRepeated.anchorPoint = CGPointZero
backgroundRepeated.position = CGPointMake(background.size.width-1,0)
addChest()
addCharacter()
addChild(background)
addChild(backgroundRepeated)
}
3) Created the items:
func addChest() {
chestOfCoins.anchorPoint = CGPointZero
chestOfCoins.size = CGSize(width: 200,height: 200)
chestOfCoins.position = CGPoint(x: self.frame.width-1, y: 300)
chestOfCoins.zPosition = 20
chestOfCoins.physicsBody = SKPhysicsBody(rectangleOfSize: chestOfCoins.size)
chestOfCoins.physicsBody?.affectedByGravity = false
chestOfCoins.physicsBody?.dynamic = false
chestOfCoins.physicsBody?.categoryBitMask = physicsCategory.chests
chestOfCoins.physicsBody?.collisionBitMask = 0
chestOfCoins.physicsBody?.contactTestBitMask = physicsCategory.character
addChild(chestOfCoins)
}
func addCharacter() {
character.anchorPoint = CGPointZero
character.position = CGPoint(x: 300, y: 300)
character.zPosition = 20
character.size = CGSize(width: 200, height: 200)
character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
character.physicsBody?.affectedByGravity = false
character.physicsBody?.dynamic = false
character.physicsBody?.categoryBitMask = physicsCategory.character
character.physicsBody?.contactTestBitMask = physicsCategory.chests
character.physicsBody?.collisionBitMask = 0
addChild(character)
}
4) created didBeginContact:
func didBeginContact(contact: SKPhysicsContact) {
var contactBody1: SKPhysicsBody
var contactBody2: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
contactBody1 = contact.bodyA
contactBody2 = contact.bodyB
} else {
contactBody1 = contact.bodyB
contactBody2 = contact.bodyA
}
if((contactBody1.categoryBitMask == 1) && (contactBody2.categoryBitMask == 2)) {
print("touched")
} else {
print("not these two")
}
}
FYI, this IF if((contactBody1.categoryBitMask == 1) && (contactBody2.categoryBitMask == 2)) does not output Either the main if block or the else.
5) I created the category physics :
struct physicsCategory {
static let none: UInt32 = 0 //0
static let character: UInt32 = 0b1 //1
static let chests: UInt32 = 0b10 //2
static let snake: UInt32 = 0b100 //4
}
Full GameScene.Swift:
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
struct physicsCategory {
static let none: UInt32 = 0 //0
static let character: UInt32 = 0b1 //1
static let chests: UInt32 = 0b10 //2
static let snake: UInt32 = 0b100 //4
static let all: UInt32 = UInt32.max
}
let background = SKSpriteNode(imageNamed: "Backgrounds")
let backgroundRepeated = SKSpriteNode(imageNamed: "Backgrounds")
let chestOfCoins = SKSpriteNode(imageNamed: "chest")
let character = SKSpriteNode(imageNamed: "character")
let gameActions = NSUserDefaults.standardUserDefaults()
func addChest() {
chestOfCoins.anchorPoint = CGPointZero
chestOfCoins.size = CGSize(width: 200,height: 200)
chestOfCoins.position = CGPoint(x: self.frame.width-1, y: 300)
chestOfCoins.zPosition = 20
chestOfCoins.physicsBody = SKPhysicsBody(rectangleOfSize: chestOfCoins.size)
chestOfCoins.physicsBody?.affectedByGravity = false
chestOfCoins.physicsBody?.dynamic = false
chestOfCoins.physicsBody?.categoryBitMask = physicsCategory.chests
chestOfCoins.physicsBody?.collisionBitMask = 0
chestOfCoins.physicsBody?.contactTestBitMask = physicsCategory.character
addChild(chestOfCoins)
}
func addCharacter() {
character.anchorPoint = CGPointZero
character.position = CGPoint(x: 300, y: 300)
character.zPosition = 20
character.size = CGSize(width: 200, height: 200)
character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
character.physicsBody?.affectedByGravity = false
character.physicsBody?.dynamic = false
character.physicsBody?.categoryBitMask = physicsCategory.character
character.physicsBody?.contactTestBitMask = physicsCategory.chests
character.physicsBody?.collisionBitMask = 0
addChild(character)
}
override func didMoveToView(view: SKView) {
backgroundColor = SKColor.whiteColor()
physicsWorld.contactDelegate = self
let sceneBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
sceneBody.friction = 0
background.zPosition = -20
background.anchorPoint = CGPointZero
background.position = CGPointZero
backgroundRepeated.zPosition = -20
backgroundRepeated.anchorPoint = CGPointZero
backgroundRepeated.position = CGPointMake(background.size.width-1,0)
addChest()
addCharacter()
addChild(background)
addChild(backgroundRepeated)
}
func didBeginContact(contact: SKPhysicsContact) {
var contactBody1: SKPhysicsBody
var contactBody2: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
contactBody1 = contact.bodyA
contactBody2 = contact.bodyB
} else {
contactBody1 = contact.bodyB
contactBody2 = contact.bodyA
}
if((contactBody1.categoryBitMask == 1) && (contactBody2.categoryBitMask == 2)) {
print("touched")
} else {
print("not these two")
}
}
override func update(currentTime: NSTimeInterval) {
let startWalking = gameActions.boolForKey("Walking")
if (startWalking == true) {
chestOfCoins.position = CGPoint(x: chestOfCoins.position.x - 5, y: chestOfCoins.position.y)
background.position = CGPoint(x: background.position.x - 5, y: background.position.y)
backgroundRepeated.position = CGPoint(x: backgroundRepeated.position.x - 5, y: backgroundRepeated.position.y)
if (background.position.x < -background.size.width) {
background.position = CGPointMake(backgroundRepeated.position.x + backgroundRepeated.size.width, background.position.y)
}
if (backgroundRepeated.position.x < -backgroundRepeated.size.width) {
backgroundRepeated.position = CGPointMake(background.position.x + background.size.width, backgroundRepeated.position.y)
}
}
}
}
Question
Can anyone tell me why, when the screen starts scrolling and those two items come into contact nothing happens and tell me how to fix it?
One also seems to go behind even though I set the zPosition of both to the same
Here is a pic, Don't judge about images :(
set either your chest or your other thingies property to dynamic = true
two non-dynamic physics bodies wont register contacts

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.

save score in game with NSUserDefaults

i am creating a game , but the high score doesn't want to display in the gameScene
and the score is calculated in the playScene , and there in a class called MLPointsLabel to create the label's name and font....etc.
heres my code for the playScene class :
//
// PlayScene.swift
// WalkRun
//
// Created by naeim on 7/10/15.
// Copyright (c) 2015 naeim. All rights reserved.
//
import Foundation
import SpriteKit
class PlayScene: SKScene, SKPhysicsContactDelegate{
var ball = SKSpriteNode(imageNamed: "ball")
var bg = SKSpriteNode(imageNamed: "bg")
var wall = SKNode()
var wallRight = SKNode()
var ballSpeed = CGFloat()
let ballCatogary:UInt32 = 0x1 << 0
let objectsCatogary:UInt32 = 0x1 << 1
let bottomWallCatogary:UInt32 = 0x1 << 3
var endOfScreenRight = CGFloat()
var gameOver = 0
var movingObjects = SKNode()
var score = 0
var scoreLabel = SKLabelNode()
var ballPositionY:CGFloat = 120
var bigWall = SKSpriteNode()
var tallWall = SKSpriteNode()
var levelHardnes:Double = 0.6
let reveal = SKTransition.flipHorizontalWithDuration(0.5)
var num = 0
var highScore = ""
override func didMoveToView(view: SKView) {
//create background
createBackGround()
self.physicsWorld.contactDelegate = self
self.physicsWorld.gravity = CGVectorMake(-9,0)
self.addChild(movingObjects)
//creating the ball
ball.position = CGPointMake(CGRectGetMidX(self.frame), ballPositionY)
ball.physicsBody = SKPhysicsBody(circleOfRadius: self.ball.size.width / 2)
ball.zPosition = 10
ball.physicsBody?.categoryBitMask = ballCatogary
ball.physicsBody?.collisionBitMask = objectsCatogary
ball.physicsBody?.contactTestBitMask = objectsCatogary
self.addChild(ball)
//creating the wall of the left
wall.position = CGPointMake(CGRectGetMinX(self.frame),CGRectGetMinY(self.frame))
wall.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
wall.physicsBody?.dynamic = false
wall.physicsBody?.categoryBitMask = objectsCatogary
self.addChild(wall)
//creating the wall of the right
wallRight.position = CGPointMake(CGRectGetMaxX(self.frame), CGRectGetMinY(self.frame))
wallRight.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(2, self.frame.size.height * 2.0))
wallRight.physicsBody?.dynamic = false
wallRight.physicsBody?.categoryBitMask = objectsCatogary
self.addChild(wallRight)
//creating the label
scoreLabel.fontName = "Helvetica"
scoreLabel.fontSize = 60
scoreLabel.text = "0"
scoreLabel.zPosition = 8
scoreLabel.name = "pointsLabel"
scoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame) )
self.addChild(scoreLabel)
//bottom wall
var bottomWall = SKNode()
bottomWall.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMinY(self.frame) + ball.size.width * 1.5 )
bottomWall.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(self.frame.size.width , 1))
bottomWall.physicsBody?.dynamic = false
bottomWall.physicsBody?.affectedByGravity = false
bottomWall.physicsBody?.categoryBitMask = bottomWallCatogary
bottomWall.physicsBody?.collisionBitMask = objectsCatogary
bottomWall.physicsBody?.contactTestBitMask = objectsCatogary
loadHighScoew()
self.addChild(bottomWall)
var timer = NSTimer.scheduledTimerWithTimeInterval(levelHardnes, target: self, selector: Selector("randObject"), userInfo: nil, repeats: true)
}
func loadHighScoew(){
let defaults = NSUserDefaults.standardUserDefaults()
let highscoreLabel = childNodeWithName("highscoreLabel") as? MLPointLabel
highscoreLabel?.setTo(defaults.integerForKey("highscore"))
}
func createBackGround(){
bg.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bg.size.width = self.frame.size.width
bg.size.height = self.frame.size.height
self.addChild(bg)
}
func increaseScore(){
score++
println(score)
scoreLabel.text = "\(score)"
}
//function to randomly choose which object
func randObject(){
if gameOver == 0{
var rand = arc4random_uniform(6)+1
switch(rand){
case 1:
leftObject()
case 2:
middleObject()
case 3:
rightObject()
case 4:
LeftAndMiddleObject()
case 5:
rightAndLeftObject()
case 6:
rightAndMiddleObject()
default:
println("error !! non a number other than 0, 1, 2 has been choosen .")
}
}
}
//function that creates a Bigwall
func createBigWall(PositionX:CGFloat , PositionY:CGFloat){
bigWall = SKSpriteNode(imageNamed: "shortwall")
bigWall.position = CGPointMake(PositionX, PositionY)
bigWall.physicsBody = SKPhysicsBody(rectangleOfSize: self.bigWall.size)
bigWall.physicsBody?.dynamic = true
bigWall.physicsBody?.affectedByGravity = false
bigWall.physicsBody?.categoryBitMask = objectsCatogary
bigWall.physicsBody?.collisionBitMask = ballCatogary
bigWall.physicsBody?.contactTestBitMask = ballCatogary
bigWall.physicsBody?.collisionBitMask = 0
bigWall.physicsBody?.contactTestBitMask = bottomWallCatogary
bigWall.zPosition = 12
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
bigWall.runAction(moveAndRemoveObjects)
movingObjects.addChild(bigWall)
}
//function that creates a Tallwall
func createTallWall(PositionX:CGFloat , PositionY:CGFloat ){
tallWall = SKSpriteNode(imageNamed: "tallwall")
tallWall.position = CGPointMake(PositionX, PositionY)
tallWall.physicsBody = SKPhysicsBody(rectangleOfSize: self.tallWall.size)
tallWall.physicsBody?.dynamic = true
tallWall.physicsBody?.affectedByGravity = false
tallWall.physicsBody?.categoryBitMask = objectsCatogary
tallWall.physicsBody?.collisionBitMask = ballCatogary
tallWall.physicsBody?.contactTestBitMask = ballCatogary
tallWall.physicsBody?.collisionBitMask = 0
tallWall.physicsBody?.contactTestBitMask = bottomWallCatogary
tallWall.zPosition = 12
var moveObjects = SKAction.moveByX(0, y: -self.frame.size.height * 2, duration: NSTimeInterval(self.frame.size.height / 100))
var removeObjects = SKAction.removeFromParent()
var moveAndRemoveObjects = SKAction.sequence([moveObjects,removeObjects])
tallWall.runAction(moveAndRemoveObjects)
movingObjects.addChild(tallWall)
}
//function to create the left objects
func leftObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
createBigWall(CGRectGetMinX(self.frame) + 30, PositionY: CGRectGetMaxY(self.frame))
}
else
{
createTallWall(CGRectGetMinX(self.frame) - 60, PositionY: CGRectGetMaxY(self.frame))
}
}
//function to create the middle objects
func middleObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
createBigWall(CGRectGetMidX(self.frame) , PositionY: CGRectGetMaxY(self.frame))
}
else
{
createTallWall(CGRectGetMidX(self.frame), PositionY: CGRectGetMaxY(self.frame))
}
}
//function to create the right objects
func rightObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
createBigWall(CGRectGetMaxX(self.frame) - 30, PositionY: CGRectGetMaxY(self.frame))
}
else
{
createTallWall(CGRectGetMaxX(self.frame) - 60, PositionY: CGRectGetMaxY(self.frame))
}
}
//function to create a right and left object
func rightAndLeftObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
createBigWall(CGRectGetMaxX(self.frame) - 30 , PositionY: CGRectGetMaxY(self.frame))
createTallWall(CGRectGetMinX(self.frame) + 60, PositionY: CGRectGetMaxY(self.frame))
}
else
{
createBigWall(CGRectGetMinX(self.frame) - 30, PositionY: CGRectGetMaxY(self.frame))
createTallWall(CGRectGetMaxX(self.frame) + 60, PositionY: CGRectGetMaxY(self.frame))
}
}
func rightAndMiddleObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
createBigWall(CGRectGetMidX(self.frame) - 30, PositionY: CGRectGetMaxY(self.frame))
createTallWall(CGRectGetMaxX(self.frame) + 60, PositionY: CGRectGetMaxY(self.frame))
}
else
{
createBigWall(CGRectGetMaxX(self.frame) - 30, PositionY: CGRectGetMaxY(self.frame))
createTallWall(CGRectGetMinX(self.frame) + 60, PositionY: CGRectGetMaxY(self.frame))
}
}
func LeftAndMiddleObject(){
var rand = arc4random_uniform(2) + 1
if rand == 1
{
createBigWall(CGRectGetMinX(self.frame) - 30, PositionY: CGRectGetMaxY(self.frame))
createTallWall(CGRectGetMidX(self.frame) + 60, PositionY: CGRectGetMaxY(self.frame))
}
else
{
createBigWall(CGRectGetMidX(self.frame) - 30, PositionY: CGRectGetMaxY(self.frame))
createTallWall(CGRectGetMinX(self.frame) + 60, PositionY: CGRectGetMaxY(self.frame))
}
}
func sendHighScore()->String{
return highScore
}
func gameOverDisplay(){
gameOver = 1
movingObjects.speed = 0
if num < score{
num = score
highScore = "\(num)"
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(num, forKey: "highscore")
}
//creating the game Over label
let gameOverScene = GameOverScene(size: self.size, won: false)
self.view?.presentScene(gameOverScene, transition: reveal)
}
func didBeginContact(contact: SKPhysicsContact) {
// 1. Create local variables for two physics bodies
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
// 2. Assign the two physics bodies so that the one with the lower category is always stored in firstBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 3. react to the contact between ball and bottom
if firstBody.categoryBitMask == ballCatogary && secondBody.categoryBitMask == objectsCatogary {
gameOverDisplay()
}
else if firstBody.categoryBitMask == objectsCatogary || secondBody.categoryBitMask == bottomWallCatogary{
increaseScore()
}
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if gameOver == 0 {
ball.physicsBody?.velocity = CGVectorMake(0, 0)
ball.physicsBody?.applyImpulse(CGVectorMake(50,0))
}
}
override func update(currentTime: NSTimeInterval) {
switch(score){
case 25:
levelHardnes = 0.5
ballPositionY += 55
case 50:
levelHardnes = 0.4
ballPositionY += 55
case 100:
levelHardnes = 0.3
ballPositionY += 55
case 250:
levelHardnes = 0.2
ballPositionY += 55
case 300:
ballPositionY += 55
case 400:
ballPositionY += 55
default:
levelHardnes = 0.1
}
}
}
and here is my GameScene code:
//
// GameScene.swift
// WalkRun
//
// Created by naeim on 7/10/15.
// Copyright (c) 2015 naeim. All rights reserved.
//
import SpriteKit
class GameScene: SKScene {
let playButton = SKSpriteNode(imageNamed: "play")
let bg = SKSpriteNode(imageNamed: "bg")
let labelIntro = SKLabelNode()
let playscene = PlayScene()
override func didMoveToView(view: SKView) {
playButton.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
playButton.zPosition = 3
self.addChild(playButton)
createBackGround()
labelMaker()
playscene.loadHighScoew()
var highScorenum = playscene.sendHighScore()
var highScoreLabel = SKLabelNode()
highScoreLabel.text = "High score : " + highScorenum
highScoreLabel.fontSize = 40
highScoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame) - 220)
highScoreLabel.fontName = "Chalkduster"
highScoreLabel.zPosition = 3
self.addChild(highScoreLabel)
}
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
for touch: AnyObject in touches{
let location = touch.locationInNode(self)
if self.nodeAtPoint(location) == self.playButton{
var scene = PlayScene(size: self.size)
let sKview = self.view
sKview?.ignoresSiblingOrder = true
scene.scaleMode = .ResizeFill
sKview?.presentScene(scene)
}
}
}
func labelMaker(){
labelIntro.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame) - 150)
labelIntro.fontName = "Chalkduster"
labelIntro.fontColor = UIColor(hex:000000)
labelIntro.text = "Wall climp"
labelIntro.fontSize = 60
labelIntro.zPosition = 3
self.addChild(labelIntro)
}
func createBackGround(){
bg.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
bg.size.width = self.frame.size.width
bg.size.height = self.frame.size.height
bg.zPosition = 2
self.addChild(bg)
}
override func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */
}
}
and here is my MLPointLabel class:
//
// MLPointsLabel.swift
// WalkRun
//
// Created by naeim on 7/16/15.
// Copyright (c) 2015 naeim. All rights reserved.
//
import Foundation
import UIKIt
import SpriteKit
class MLPointLabel:SKLabelNode {
var number = 0
var playScene = PlayScene()
init(num: Int){
super.init()
name = "highscore"
fontColor = UIColor.whiteColor()
fontName = "Chalkduster"
fontSize = 40.0
zPosition = 3
var number = num
text = " High Score :" + "\(num)"
}
func setTo(num:Int){
self.number = num
text = "\(self.number)"
}
func increment(){
number++
text = "\(number)"
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
i really cant quite figure it out why , the game when i run it, doesn't give me any errors , instead it doesn't save the high score
Here I made some changes in your code.
GameScene.swift
//read your score this way
func addHighScoreLbl() {
let highScorenum = NSUserDefaults.standardUserDefaults().integerForKey("highscore")
var highScoreLabel = SKLabelNode()
highScoreLabel.text = "High score : \(highScorenum)"
highScoreLabel.fontSize = 40
highScoreLabel.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMaxY(self.frame) - 220)
highScoreLabel.fontName = "Chalkduster"
highScoreLabel.zPosition = 3
self.addChild(highScoreLabel)
}
PlayScene.swift
func didBeginContact(contact: SKPhysicsContact) {
// 1. Create local variables for two physics bodies
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
// 2. Assign the two physics bodies so that the one with the lower category is always stored in firstBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 3. react to the contact between ball and bottom
if firstBody.categoryBitMask == ballCatogary && secondBody.categoryBitMask == objectsCatogary {
let gameOverScene = GameOverScene(size: self.size, won: false)
self.view?.presentScene(gameOverScene, transition: reveal)
}
else if firstBody.categoryBitMask == objectsCatogary || secondBody.categoryBitMask == bottomWallCatogary{
score++
if score > highScore {
//Set your highscore this way.
NSUserDefaults.standardUserDefaults().setInteger(score, forKey: "highscore")
}
scoreLabel.text = "\(score)"
}
}
Try
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setValue(num, forKey: "highscore")
and when you are retrieving your highscore in GameScene, it would be better to retrieve it directly from the NSUserDefaults like
let defaults = NSUserDefaults.standardUserDefaults()
var highScorenum = defaults.valueForKey("highscore")!.stringValue
Hope this may help !

Resources