Inverted x-scale collision handling (SpriteKit 7.1)

I use the SKNode xScale property to flip my sprites horizontally. Now, after updating iOS to version 7.1, a horizontal flip causes my objects to sink inside the earth. (See Animation below). The problem only occurs with the xScale property. Vertical flips work fine.

// Init { SKSpriteNode* ground = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:CGSizeMake(winSize.width, 150)]; ground.position = CGPointMake(winSize.width/2, ground.size.height/2); ground.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:ground.size center:CGPointZero]; ground.physicsBody.dynamic = NO; ground.physicsBody.categoryBitMask = 0x01; ground.physicsBody.collisionBitMask = 0x02; ground.physicsBody.contactTestBitMask = 0x02; [self.world addChild:ground]; SKSpriteNode* turtle = [SKSpriteNode spriteNodeWithImageNamed:@"turtle.png"]; turtle.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:turtle.size.width/2]; turtle.physicsBody.categoryBitMask = 0x02; turtle.physicsBody.collisionBitMask = 0x01; turtle.physicsBody.contactTestBitMask = 0x01; turtle.position = CGPointMake(winSize.width/2, winSize.height/2); [self.world addChild:turtle]; self.turtle = turtle; } // Somewhere else { self.turtle.xScale *= -1; } 

x-scale flip problem

+8
sprite-kit skphysicsbody
source share
3 answers

I am convinced that this is a bug in SpriteKit.

In any case, here is one solution to the problem (in fact, this is more of a workaround than a real solution, but ...): Wrap the sprite in the node container. In addition, the node container contains the physical device, while the child of the node is just the graphics of the node. This way you can safely flip the sprite with xScale without affecting the physics of the node.

 // Init { SKSpriteNode* turtleSprite = [SKSpriteNode spriteNodeWithImageNamed:@"turtle.png"]; self.turtleSprite = turtleSprite; SKNode* turtleWrapper = [SKNode node]; turtleWrapper.physicsBody = [SKPhysicsBody bodyWithCircleOfRadius:turtleSprite.size.width/2]; turtleWrapper.physicsBody.categoryBitMask = 2; turtleWrapper.physicsBody.collisionBitMask = 1; turtleWrapper.physicsBody.contactTestBitMask = 1; [turtleWrapper addChild:turtleSprite]; [self.world addChild:turtleWrapper]; } // Elsewhere { self.turtleSprite.xScale *= -1; } 
+12
source share

I ran into this problem a couple of days ago. I wanted to invert the sprite based on its movement (right or left) and found that setting xScale disables any collisions / contacts.

However, I used this line every time I set the xScale property, and everything returned to normal.

 node.xScale = -1.0 node.physicsBody = node.physicsBody; 
+6
source share

Alternative solution

In my case, I usually subclass SKSpriteNode to represent the nodes in my scene, and then encapsulate their behavior (animation and movement) in a subclass. The wrap sprite in the node container solution does not work in my case, because I have actions that enliven the sprite texture and also move the sprite in sequence.

For example:

 class Player: SKSpriteNode{ override init() { ... super.init(texture: texture, color: nil, size: texture.size()) physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(70,75)) } func attack(){ let action = SKAction.sequence([ SKAction.moveTo(enemyPosition, duration: 0), SKAction.animateWithTextures(frames, timePerFrame: 0.5) ]) runAction(action) } } 

Bypass

In my case, I solved this by adding these methods to my "Player" class:

 class Player: SKSpriteNode{ private var flipped: Bool ... func flip(){ flipped = !flipped position = CGPointMake(-position.x, position.y) } //MARK: Workaround for iOS7 -xScale physics bugs func willSimulatePhysics(){ xScale = 1 } func didSimulatePhysics(){ xScale = flipped ? -1 : 1 } } 

And then override the SKScene methods:

 class MyScene: SKScene{ ... override func update(currentTime: CFTimeInterval) { super.update(currentTime) player.willSimulatePhysics() } override func didSimulatePhysics() { super.didSimulatePhysics() player.didSimulatePhysics() } } 

This works because the flip node is disabled just before the physics is modeled for the scene. The node flag is then applied immediately before rendering the frame.

0
source share

All Articles