Pierre Courpron
Pierre Courpron

Reputation: 154

turning physics on and off

I'm trying to solving a problem where a sprite node can jump up through a platform but cannot jump back down. I tried using this code:

override func didMove(to view: SKView) {
    if (thePlayer.position.y > stonePlatform1.position.y) ==  true {
        stonePlatform1.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: stonePlatform.size.width * 0.9, height: stonePlatform.size.height * 0.75))
        stonePlatform1.physicsBody!.isDynamic = false
        stonePlatform1.physicsBody!.affectedByGravity = false
        stonePlatform1.physicsBody!.categoryBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.contactTestBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.restitution = 0.4
    }
}

The idea was to turn on the physics body of the platform on when the player is above the platform. However, the physics doesn't work at all when I use this code. In fact I tried using this code:

override func didMove(to view: SKView) {
    if (thePlayer.position.y < stonePlatform1.position.y) ==  true {
        stonePlatform1.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: stonePlatform.size.width * 0.9, height: stonePlatform.size.height * 0.75))
        stonePlatform1.physicsBody!.isDynamic = false
        stonePlatform1.physicsBody!.affectedByGravity = false
        stonePlatform1.physicsBody!.categoryBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.contactTestBitMask = BodyType.object.rawValue
        stonePlatform1.physicsBody!.restitution = 0.4
    }
}

and the physics doesn't turn on either. If the IF statement isn't there, the physics does work all of the time.

Upvotes: 0

Views: 202

Answers (2)

Maetschl
Maetschl

Reputation: 1339

You can use the node velocity for this platforms, like this:

SpriteKit - Swift 3 code:

private var up1 : SKSpriteNode!
private var down1 : SKSpriteNode!
private var down2 : SKSpriteNode!
private var player : SKSpriteNode!

override func didMove(to view: SKView) {
    up1 = self.childNode(withName: "up1") as! SKSpriteNode
    down1 = self.childNode(withName: "down1") as! SKSpriteNode
    down2 = self.childNode(withName: "down2") as! SKSpriteNode
    player = self.childNode(withName: "player") as! SKSpriteNode
    up1.physicsBody?.categoryBitMask = 0b0001 // Mask for UoPlatforms
    down1.physicsBody?.categoryBitMask = 0b0010 // Mask for downPlatforms
    down2.physicsBody?.categoryBitMask = 0b0010 // Same mask
}

override func update(_ currentTime: TimeInterval) {
    player.physicsBody?.collisionBitMask = 0b0000 // Reset the mask

    // For UP only Platform
    if (player.physicsBody?.velocity.dy)! < CGFloat(0.0) {
        player.physicsBody?.collisionBitMask |= 0b0001 // The pipe | operator adds the mask by binary operations
    }

    // For Down only platforms
    if (player.physicsBody?.velocity.dy)! > CGFloat(0.0) {
        player.physicsBody?.collisionBitMask |= 0b0010  // The pipe | operator adds the mask by binary operations
    }

}

Source code with example here: https://github.com/Maetschl/SpriteKitExamples/tree/master/PlatformTest

The example show this: Green platforms -> Down Only Red platforms -> Up only

enter image description here

Upvotes: 3

TheValyreanGroup
TheValyreanGroup

Reputation: 3599

You could try just starting with the physics body as nil and then set the physics values to it after the player is above it. Also, this kind of code should be in the update function. Having it in didMove only lets it get called once.

override func update(_ currentTime: TimeInterval){
 if (thePlayer.position.y < stonePlatform1.position.y) && stonePlatform1.physicsBody != nil {
       stonePlatform1.physicsBody = nil
 }else if (thePlayer.position.y > stonePlatform1.position.y) && stonePlatform1.physicsBody == nil{
    setPhysicsOnPlatform(stonePlatform1)
 }
}

func setPhysicsOnPlatform(_ platform: SKSpriteNode){
   platform.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: stonePlatform.size.width * 0.9, height: stonePlatform.size.height * 0.75))
   ...
   //the rest of your physics settings
}

You should also do some handling for the height of the player and your anchorPoint. Otherwise if your anchorPoint is (0,0) and the player is halfway through the platform, the physics will be applied and a undesirable result will occur.

Upvotes: 0

Related Questions