iCod3r iCod3r - 4 months ago 9
iOS Question

SpriteKit & Swift, make Platforms nil if a condition is true wont work

Hi im making a simple 2d sidescroller game in spritekit with swift and im facing a problem that i cant solve. I have a function called (createPlatforms) to spawn some platforms (each one above the other) and the Platforms are going form right to left. I also added a Bool variable called isJumping, i want that if the variable isJumping is true that the platforms physicsbody's gets nil so that the player can jump above it and land on it. I kinda managed to do that. It works on the first platform but not on the others. The Player jumps above the first Platform and lands on it but he cant jump above the second or third platform. Sometimes like 10% of the time it works on all platforms and he can jump above and land on them but most of the time it doesnt work.

Thank you in advance.

My jump method:

func jump() {

isJumping = true

let jumpBlock = SKAction.runBlock({
() in
self.Dragon.physicsBody?.velocity = CGVectorMake(0, 0)
self.Dragon.physicsBody?.applyImpulse(CGVectorMake(0, 140)) // Jump Impulse
})

self.runAction(jumpBlock)

runAfterDelay(0.3) { /* 0.3 Seconds */
self.isJumping = false
}
}
//Delay function
func runAfterDelay(delay: NSTimeInterval, block: dispatch_block_t) {
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(time, dispatch_get_main_queue(), block)
}


}

Method for spawning platforms:

func createPlatforms() {

Platform1 = SKSpriteNode(imageNamed:"Platform")
Platform2 = SKSpriteNode(imageNamed:"Platform")
Platform3 = SKSpriteNode(imageNamed:"Platform-Small")

Platform1.size = CGSize(width: frame.width / 3, height: frame.height / 25)
Platform2.size = CGSize(width: frame.width / 3, height: frame.height / 25)
Platform3.size = CGSize(width: frame.width / 6, height: frame.height / 25)
Platform1.position = CGPoint(x: self.frame.width + 330, y: self.frame.height - 285)
Platform2.position = CGPoint(x: self.frame.width + 500, y: self.frame.height - 210)
Platform3.position = CGPoint(x: self.frame.width + 570, y: self.frame.height - 135)

Platform1.physicsBody = SKPhysicsBody(rectangleOfSize: Platform1.size)
Platform1.zPosition = 6
Platform1.physicsBody?.categoryBitMask = PhysicsCatagory.Platform1
Platform1.physicsBody?.contactTestBitMask = PhysicsCatagory.Dragon
Platform1.physicsBody?.collisionBitMask = PhysicsCatagory.Dragon
Platform1.physicsBody?.dynamic = false

Platform2.physicsBody = SKPhysicsBody(rectangleOfSize: Platform2.size)
Platform2.zPosition = 7
Platform2.physicsBody?.categoryBitMask = PhysicsCatagory.Platform2
Platform2.physicsBody?.contactTestBitMask = PhysicsCatagory.Dragon
Platform2.physicsBody?.collisionBitMask = PhysicsCatagory.Dragon
Platform2.physicsBody?.dynamic = false

Platform3.physicsBody = SKPhysicsBody(rectangleOfSize: Platform3.size)
Platform3.zPosition = 8
Platform3.physicsBody?.categoryBitMask = PhysicsCatagory.Platform3
Platform3.physicsBody?.contactTestBitMask = PhysicsCatagory.Dragon
Platform3.physicsBody?.collisionBitMask = PhysicsCatagory.Dragon
Platform3.physicsBody?.dynamic = false

Platform1.runAction(moveAndRemove)
Platform2.runAction(moveAndRemove)
Platform3.runAction(moveAndRemove)

self.addChild(Platform1)
self.addChild(Platform2)
self.addChild(Platform3)

let distance = CGFloat(self.frame.width + 1000)
let moveGroundObjects = SKAction.moveByX(-distance * 1.3, y: 0, duration: NSTimeInterval(0.011 * distance))
let removeGroundObjects = SKAction.removeFromParent()
moveAndRemove = SKAction.sequence([moveGroundObjects, removeGroundObjects])


runAfterDelay(7) {
self.createPlatforms()
}
}


Method to make platforms's physicbody's nil:

func makePlatformsNil() {

if isJumping == true {

Platform1.physicsBody = nil
Platform2.physicsBody = nil
Platform3.physicsBody = nil

} else if isJumping == false {

Platform1.physicsBody = SKPhysicsBody(rectangleOfSize: Platform1.size)
Platform1.physicsBody?.categoryBitMask = PhysicsCatagory.Platform1
Platform1.physicsBody?.collisionBitMask = PhysicsCatagory.Dragon
Platform1.physicsBody?.contactTestBitMask = PhysicsCatagory.Dragon
Platform1.physicsBody?.dynamic = false
Platform1.physicsBody?.allowsRotation = false

Platform2.physicsBody = SKPhysicsBody(rectangleOfSize: Platform2.size)
Platform2.physicsBody?.categoryBitMask = PhysicsCatagory.Platform2
Platform2.physicsBody?.collisionBitMask = PhysicsCatagory.Dragon
Platform2.physicsBody?.contactTestBitMask = PhysicsCatagory.Dragon
Platform2.physicsBody?.dynamic = false
Platform2.physicsBody?.affectedByGravity = false

Platform3.physicsBody = SKPhysicsBody(rectangleOfSize: Platform3.size)
Platform3.physicsBody?.categoryBitMask = PhysicsCatagory.Platform3
Platform3.physicsBody?.collisionBitMask = PhysicsCatagory.Dragon
Platform3.physicsBody?.contactTestBitMask = PhysicsCatagory.Dragon
Platform3.physicsBody?.dynamic = false
Platform3.physicsBody?.affectedByGravity = false
}
}


Please can someone help me? Im stuck since three weaks and im really frustrated right now :-/ Im sure my problem can be solved easily by someone with more experience with coding than me

Answer

Here is a lot less code, that is cleaner and easier to manage. (All platforms should share the same category, and Dragon category needs to be less than Platform)

Note: not tested for validation on XCode

func didBeginContact(contact: SKPhysicsContact) {
    let (firstBody,secondBody) = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (contact.bodyA,contact.bodyB) : (contact.bodyB,contact.bodyA) 

    // check if on Platform

    if (firstBody.categoryBitMask == PhysicsCatagory.Dragon && secondBody.categoryBitMask == PhysicsCatagory.Platform)  {

        if firstBody.physicsBody?.velocity.dy < -0.0 {

            secondBody.physicsBody?.collisionBitMask |= physicsCatagory.Dragon
        }

    }



}

func didEndContact(contact: SKPhysicsContact) {
    let (firstBody,secondBody) = (contact.bodyA.categoryBitMask <= contact.bodyB.categoryBitMask) ? (contact.bodyA,contact.bodyB) : (contact.bodyB,contact.bodyA) 

    // check if on Platform

    if (firstBody.categoryBitMask == PhysicsCatagory.Dragon && secondBody.categoryBitMask == PhysicsCatagory.Platform)  {

       //No matter what way dragon is moving, if he is off the platform,  let's turn off the collision

            secondBody.physicsBody?.collisionBitMask &= ~(physicsCatagory.Dragon)


    }

}