Hi I\'m trying to fix this bug with spritekit\'s physics shape appearing upside down.
[SKPhysicsBody bodyWithTexture:monsterTexture size:monsterTexture.size]
I think it is a bug in Spritekit on iOS8. My suspicion is that the bug occurs when the texture for the physicsbody is retrieved from the internal cache. It might be incorrectly flipping the image to try to correct co-ordinate systems from CoreGraphics.
Use bodyWithBodies instead. Bummer, I really like this feature.
The solution was to hold a strong reference to the atlas instead of the textures themselves. This also simplified my code sine I'm already preloading all my atlases with [SKTextureAtlas preloadTextureAtlases:textureAtlases withCompletionHandler:^{ ... }];
at the beginning of my scene. This seems to use the same amount of memory (if not less), and it does not produce the upside-down physics body bug anymore. The comments on this question (should I cache textures in properties in sprite kit?) helped me discover this as I was refactoring my code.
// In Game Scene
@property (nonatomic, strong) SKTextureAtlas * monsterAtlas;
...
- (id)initWithSize:(CGSize)size
{
self.monsterAtlas = [SKTextureAtlas atlasNamed:monsterAtlasName];
NSArray * textureAtlases = @[self.monsterAtlas];
[SKTextureAtlas preloadTextureAtlases:textureAtlases withCompletionHandler:^{ ... }];
}
// In Monster Class
- (Monster *)monster:(NSDictionary *)settings
{
...
SKTextureAtlas * atlas = [SKTextureAtlas atlasNamed:monsterAtlasName];
NSString * textureName = monsterConfig[TEXTURE] ? monsterConfig[TEXTURE] : monsterDefaults[TEXTURE];
Monster * monster = [Monster spriteNodeWithTexture:[atlas textureNamed:textureName]];
...
}
I was able to solve this problem in my code by creating an SKPhysicsBody array in my didMoveToView array from the available textures I needed. Instead of recreating the SKPhysicsBody when it needed changed for my given SKSpriteNode, I was able to reference the already created SKPhysicsBody in the array. This kept the texture from being flipped upside down. Hope this approach can help others stuck on this one.
// variable declared in SKScene
var myPhysicsBodies: [SKPhysicsBody]()
// put in didMoveToView
for var i = 0; i <= 6; i++ {
self.myPhysicsBodies.append(SKPhysicsBody(texture: self.myTextureFrames[i], size: self.myObject.size))
}
// used when changing physicsBody
self.myObject.physicsBody = self.myPhysicsBodies[self.frameIndex]
UPDATE: This was working all well and good until iOS 9 SDK. I found that my 0th and 6th physics bodies would work but the others would not appear. I was able to extract the texture.plist from device and found that textures 1 through 5 were rotated (ie, textureRotated = YES in the plist). I assume the rotation is used to decrease the overall image size for the atlas. It appears that since the images in the texture atlas are being rotated, this somehow affects the ability to generate a physics body from the texture.