【问题标题】:Horizontally mirror a SKSpriteNode texture水平镜像 SKSpriteNode 纹理
【发布时间】:2013-10-10 08:49:18
【问题描述】:

我正在使用名为 Sprite Kit 的新 API 开发一款 iOS7 游戏。我想水平旋转 SKSpriteNode 图像/纹理。我已经尝试过首先镜像图像,然后创建一个 SKTexture,最后将它应用到 SKSpriteNode 但它不起作用。有没有办法做到这一点?或者我应该使用不同的图像?

【问题讨论】:

    标签: objective-c swift image ios7 sprite-kit


    【解决方案1】:

    如果你只是想沿轴翻转精灵,你可以这样做:

    sprite.xScale = -1.0;
    

    【讨论】:

    • 如果您将子节点添加到节点,这将不起作用 - 它们也会被镜像。因此,如果您有文本或命中点标签等内​​容,它们也会得到反映。
    • 如果更改锚点似乎也不起作用。有什么办法可以做到这两点?
    • @Greg 这样做 xScale = -1.0 使我的 SKSpriteNode 掉到地上(在缩放之前它通常站在地上)。任何想法为什么? (7.1)
    • 这破坏了 iOS 7.1 中的物理碰撞检测。非常令人惊讶的是它会破裂。
    • 如果这不起作用,只需创建一个翻转图像,您甚至可以在代码中执行此操作。如果设置纹理属性,只需先创建一个翻转图像,然后使用翻转的图像设置纹理图像。然后你可能想要一个 SKSpriteNode 的子类,它的属性指示它所面对的方向。这可以通过枚举来完成。
    【解决方案2】:

    您可以使用此代码在 x 轴之间翻转:

    spriteNode.xScale = spriteNode.xScale * -1;
    

    但要小心,你可能会失去一些物理体的属性,我强烈建议你以这种方式使用 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;
    

    【讨论】:

    • 这不会禁用精灵批处理吗?
    【解决方案3】:

    我将它用于我的右手或左手精灵:

    这里有一些帮助 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"];
    }
    

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

    【讨论】:

    • 然后你像往常一样设置你的物理。
    【解决方案4】:

    这是我用 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)
    

    P.S.:如果您想要相同的功能但要使用portrait 模式,请参考此answer

    【讨论】:

      猜你喜欢
      • 2010-10-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-18
      • 2013-12-30
      • 1970-01-01
      • 2013-09-07
      • 2015-07-10
      相关资源
      最近更新 更多