Reputation: 154
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
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
Upvotes: 3
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