刮擦SKNode并在其下方展示SKNode,这种效果就像擦拭迷雾玻璃一样

时间:2014-09-27 07:16:17

标签: ios objective-c iphone ipad sprite-kit

基本上我想在SpriteKit中实现这样的事情:https://github.com/moqod/iOS-Scratch-n-See

在SKScene中,我有一个汽车图像,2-3种不同类型的污垢图像,一层肥皂,一层水滴,这些层我的意思是它们都是UIImage形式,等于车架的尺寸(我最终可以用作SKTexture和SKNode)。 上面提到的项目将UIImageView相互添加,而不是擦除图像。 我需要管理很多层,就像选择肥皂工具一样,我想调出污垢图像层,擦除用户触摸的污垢图像,在它下面我将放置肥皂图像(半透明),现在可见在它下面的汽车图像。 合并后(半删除/一半存在的污垢+肥皂+汽车图像)我会得到另一张图像并将其显示在顶部,这样就会给用户留下一个印象,好像他在车上涂肥皂一样去除污垢。 如果你能看到我想要解释的内容。

我想使用上面提到的项目并在SpriteKit上实现这些任务。

我不能使用z-position来提前和移回图像,因为它只适用于SKSpriteNode,上面的例子是在UIKit(UIImages)上编码来擦除图像而不是节点。

我无法互相添加透明的SKScenes,例如Making a SKScene's background transparent not working... is this a bug?,就像在我正在使用IOS 7并希望我的应用程序兼容它时,在该项目上添加UIImageView的方式相同。 最后一招是我需要放弃SpriteKit并在UIKit上工作。

刷过SKSpriteNode并通过更改其alpha值或其他内容使其特定区域滑动区域透明的任何逻辑?

欢迎任何帮助或建议。谢谢。

1 个答案:

答案 0 :(得分:2)

您可以使用Sprite Kit的SKCropNode实现“刮擦并查看”。 SKCropNode将掩码应用于其子节点。掩码用于隐藏部分或全部裁剪节点的子节点。对于这个应用程序,子节点是您想要通过“刮擦”来发现的图像。

基本步骤

  1. 以空图像作为蒙版的纹理开始
  2. 在用户触摸隐藏图像的面具上添加圆圈以显示下面的图片
  3. 以下是如何执行此操作的示例:

    首先,定义这些属性

    @property UIImage *image;
    @property SKSpriteNode *maskNode;
    @property SKNode *node;
    

    然后将场景的内容添加到didMoveToView。

    -(void)didMoveToView:(SKView *)view {
    
        self.node = [SKNode node];
        _node.name = @"tree";
    
        // Create a node that will hold the image that's hidden and later uncovered by "scratching"
        CGPoint position = CGPointMake (CGRectGetWidth(self.frame)/2,CGRectGetHeight(self.frame)/2);
        SKSpriteNode *imageNode = [SKSpriteNode spriteNodeWithImageNamed:@"hidden_pic.png"];
        imageNode.position = CGPointZero;
    
        CGSize size = imageNode.size;
    
        // This is the layer that you "scatch" off
        SKSpriteNode *background = [SKSpriteNode spriteNodeWithColor:[SKColor grayColor] size:size];
        background.position = position;
        background.name = @"background";
        [_node addChild:background];
    
        // This is the mask node. Initialize it with an empty image, so it completely hides the image
        UIImage *image = [self blankImageWithSize:size];
        self.image = image;
        SKTexture *texture = [SKTexture textureWithImage:image];
        SKSpriteNode *maskNode = [SKSpriteNode spriteNodeWithTexture:texture];
        maskNode.position = CGPointZero;
        maskNode.name = @"mask";
        self.maskNode = maskNode;
    
        [_node addChild:maskNode];
    
        // This is the node that crops its children
        SKCropNode *cropNode = [SKCropNode node];
        cropNode.position = position;
        cropNode.maskNode = maskNode;
        cropNode.zPosition = 100;
        cropNode.name = @"crop";
    
        [_node addChild:cropNode];
    
    
        [cropNode addChild:imageNode];
    
        [self addChild:_node];
    }
    

    这会创建一个空图像。它用作初始遮罩图像,以便完全隐藏图片。

    - (UIImage*) blankImageWithSize:(CGSize)size
    {
        UIGraphicsBeginImageContext(size);
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
    

    此方法在指定点的图像上绘制一个圆。它用于更新掩码节点的图像。在面具上绘制的每个圆圈都会发现更多隐藏的图片。

    #define kCircleRadius   22
    
    - (UIImage *)imageByDrawingCircleOnImage:(UIImage *)image atPoint:(CGPoint)point
    {
        UIGraphicsBeginImageContext(image.size);
    
        [image drawAtPoint:CGPointZero];
    
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextScaleCTM(context, 1, -1);
        CGContextTranslateCTM(context, 0, -image.size.height);
    
        CGRect rect = CGRectMake(point.x-kCircleRadius, point.y-kCircleRadius,
                                 kCircleRadius*2, kCircleRadius*2);
        UIBezierPath* roundedRectanglePath = [UIBezierPath bezierPathWithOvalInRect:rect];
        [[UIColor blackColor] setFill];
        [roundedRectanglePath fill];
    
        CGContextAddPath(context, roundedRectanglePath.CGPath);
    
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return newImage;
    }
    

    此方法将指定点转换为蒙版节点的坐标,调用 一种在掩码节点中绘制圆的方法,并更新掩码节点 质地。

    - (void) drawCircleInImageAtPoint:(CGPoint)point
    {
        CGPoint location = [self convertPoint:point toNode:_maskNode];
        location = CGPointMake(location.x+_maskNode.size.width/2, location.y+_maskNode.size.height/2);
        UIImage *newImage = [self imageByDrawingCircleOnImage:_image atPoint:location];
        SKTexture *texture = [SKTexture textureWithImage:newImage];
        self.image = newImage;
        _maskNode.texture = texture;
    }
    

    这些方法处理触摸事件。它将cicles添加到用户触摸屏幕的掩模节点图像。

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
        /* Called when a touch begins */
    
        for (UITouch *touch in touches) {
            CGPoint location = [touch locationInNode:self];
            NSArray *nodes = [self nodesAtPoint:location];
            for (SKNode *node in nodes) {
                if ([node.name isEqualToString:@"crop"]) {
                    [self drawCircleInImageAtPoint:location];
                }
            }
        }
    }
    
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
        /* Called when a touch begins */
    
        for (UITouch *touch in touches) {
            CGPoint location = [touch locationInNode:self];
            NSArray *nodes = [self nodesAtPoint:location];
            for (SKNode *node in nodes) {
                if ([node.name isEqualToString:@"crop"]) {
                    [self drawCircleInImageAtPoint:location];
                }
            }
        }
    }