28

I'm developing an iOS7 game with the new API called Sprite Kit. I'd like to horizontally rotated a SKSpriteNode image/texture. I've tried it by first mirroring the image, then creating a SKTexture and finally applying it to the SKSpriteNode but it doesn't work. Is there some way to do this? Or I should have to different images?

Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133
Marti Serra Vivancos
  • 1,195
  • 5
  • 17
  • 33

4 Answers4

38

If you're just trying to flip the sprite along an axis, you can do something like this:

sprite.xScale = -1.0;
Greg
  • 33,450
  • 15
  • 93
  • 100
  • 1
    This does not work if you have children added to the node - they get mirrored as well. So if you have stuff like text or hit points labels, they get reflected as well. – Alex Stone Jan 17 '14 at 18:21
  • 2
    Also does not seem to work if you change the anchor point. Any way to do both? – Kudit Jan 25 '14 at 22:51
  • 2
    @Greg doing this xScale = -1.0 makes my SKSpriteNode fall through the ground (before scaling it normally stood on the ground). any ideas why? (7.1) – Zephyer Mar 11 '14 at 07:15
  • 1
    This broke physics collision detection in iOS 7.1. Very surprising that it would just break. – Genki Mar 11 '14 at 17:19
  • 1
    If this is not working, just create a flipped image, you can even do this in code. If you set the texture property, just first create a flipped image then set the texture image with the flipped one. Then you'll probably want a subclass of SKSpriteNode with a property indicating the direction it is facing. This can be done with an enum. – uchuugaka Jul 07 '14 at 03:52
  • Works 100% to me. Thanks! I needed this for my game. – Hedylove Oct 10 '15 at 01:56
26

You can use this code to flip among x-axis:

spriteNode.xScale = spriteNode.xScale * -1;

but be careful you can lose some of physicsbody's property, I highly suggest u to use xScale in this way:

spriteNodeBody = [SKNode node];
spriteNodeBody.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:spriteNode.size];
spriteNodeBody.physicsBody.categoryBitMask = CNPhysicsCategoryPlayer;
spriteNodeBody.physicsBody.collisionBitMask = CNPhysicsCategoryBall;

[spriteNodeBody addChild:spriteNode];
[self addChild:spriteNodeBody];

And now you can safely use:

    spriteNode.xScale = spriteNode.xScale * -1;
0

I use this for my rightHanded or leftHanded sprites:

with some help from here Horizontal Flip of a frame in Objective-C

BOOL leftHanded = YES;

SKSpriteNode *sprite;

if (leftHanded) {  //my textures point east, so I flip vertically
    SKTexture *texture = [SKTexture textureWithImageNamed:@"figure-step0"];
    CIFilter *filter = [CIFilter filterWithName:@"CIAffineTransform"];
    [filter setValue:[CIImage imageWithCGImage:[texture CGImage]] forKey:kCIInputImageKey];

#ifdef IOS_BLOCK  //set these up with defines
    CGAffineTransform flipTransform = CGAffineTransformMakeScale(1.0f, -1.0f); // vert
    [filter setValue:[NSValue valueWithBytes:&flipTransform
                                objCType:@encode(CGAffineTransform)]
                                forKey:@"inputTransform"];
#else //OSX_BLOCK
    NSAffineTransform* flipTransform = [NSAffineTransform transform];
    [flipTransform scaleXBy:1.0f yBy: -1.0f]; // vert
    [filter setValue:flipTransform forKey:@"inputTransform"];
#endif
    sprite = [SKSpriteNode spriteNodeWithTexture:
                     [texture textureByApplyingCIFilter:filter]];
} else {
    sprite = [SKSpriteNode spriteNodeWithImageNamed:@"figure-step0"];
}

You can do the same for animation frames likewise. Works for iOS or OS X.

Community
  • 1
  • 1
rezwits
  • 835
  • 7
  • 12
0

This is my solution written in Swift 2.x, usually I prefeer to use landscape mode for my games, so I write this extension:

extension SKTexture {
    class func flipImage(name:String,flipHoriz:Bool,flipVert:Bool)->SKTexture {
        if !flipHoriz && !flipVert {
            return SKTexture.init(imageNamed: name)
        }
        let image = UIImage(named:name)

        UIGraphicsBeginImageContext(image!.size)
        let context = UIGraphicsGetCurrentContext()

        if !flipHoriz && flipVert {
            // Do nothing, X is flipped normally in a Core Graphics Context 
            // but in landscape is inverted so this is Y
        } else
        if flipHoriz && !flipVert{
            // fix X axis but is inverted so fix Y axis
            CGContextTranslateCTM(context, 0, image!.size.height)
            CGContextScaleCTM(context, 1.0, -1.0)
            // flip Y but is inverted so flip X here
            CGContextTranslateCTM(context, image!.size.width, 0)
            CGContextScaleCTM(context, -1.0, 1.0)
        } else
        if flipHoriz && flipVert {
            // flip Y but is inverted so flip X here
            CGContextTranslateCTM(context, image!.size.width, 0)
            CGContextScaleCTM(context, -1.0, 1.0)
        }

        CGContextDrawImage(context, CGRectMake(0.0, 0.0, image!.size.width, image!.size.height), image!.CGImage)

        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();
        return SKTexture(image: newImage)
    }
}

Usage:

let spriteTxt = SKTexture.flipImage(imageName, flipHoriz: true, flipVert: false)

P.S.: If you want the same function but to portrait mode please refeer to this answer

Community
  • 1
  • 1
Alessandro Ornano
  • 34,887
  • 11
  • 106
  • 133