SKSpriteNode纹理水平镜像

28

我正在使用名为Sprite Kit的新API开发iOS7游戏。我希望能够水平旋转SKSpriteNode图像/纹理。我尝试通过首先镜像图像,然后创建一个SKTexture,并最终将其应用于SKSpriteNode来实现,但是它不起作用。有没有什么方法可以做到这一点?或者我应该有两张不同的图片?

4个回答

38

如果您只是想翻转精灵沿着一个轴,您可以这样做:

sprite.xScale = -1.0;

1
如果您将子节点添加到节点,则此方法无法正常工作-它们也会被镜像。因此,如果您有文本或命中点标签之类的内容,它们也会被反射。 - Alex Stone
2
似乎如果更改锚点也无法正常工作。有没有办法两者都做到? - Kudit
2
@Greg,我把xScale设为-1.0后,我的SKSpriteNode掉到了地面下面(在正常缩放之前它是站在地面上的)。你有什么想法吗?(7.1) - Zephyer
1
这个问题破坏了iOS 7.1中的物理碰撞检测。令人惊讶的是它会突然出现问题。 - Genki
1
如果这个方法无效,只需创建一个翻转图像,甚至可以在代码中完成。如果你设置了纹理属性,只需要先创建一个翻转图像,然后使用翻转后的图像设置纹理图像。接下来,您可能需要一个SKSpriteNode的子类,该子类具有指示其朝向的属性。这可以用一个枚举来实现。 - uchuugaka
对我来说百分之百有效。谢谢!我需要这个来制作我的游戏。 - Hedylove

27
您可以使用以下代码在x轴上进行翻转:
spriteNode.xScale = spriteNode.xScale * -1;

但是请注意,这样做可能会丢失一些physicsbody的属性。我强烈建议您按照以下方式使用xScale:

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

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

现在您可以安全使用:

    spriteNode.xScale = spriteNode.xScale * -1;

这会禁用精灵批处理吗? - Zmey

1

这是我使用Swift 2.x编写的解决方案,通常我更喜欢在游戏中使用landscape模式,因此我编写了这个扩展:

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)
    }
}

用法:

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

附言:如果您想要相同的功能,但是在竖屏模式下,请参考此答案


0

我用这个来处理我的右手或左手的精灵:

在这里得到了一些帮助 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"];
}

你同样可以对动画帧执行相同的操作。适用于iOS或OS X。


然后,您只需像平常一样设置物理引擎即可。 - rezwits

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接