In SpriteKit, SKCropNode has no effect over a SKShapeNode

前端 未结 3 1251
面向向阳花
面向向阳花 2020-12-31 14:15

I\'ve been trying to apply a mask to a SKShapeNode using SKCropNode, and so far without success. Thinking that it\'s a SpriteKit bug - Here is the code snippet:



        
相关标签:
3条回答
  • 2020-12-31 14:56

    This had been bugging me for most of the day. I had planned to create a timer similar to the excellent TCProgressTimer by Tony Chamblee. However, as my application uses multiple progress timers I didn't want to have to design dozens of different sized sprites for use at different resolutions.

    My solution was to convert SKShapeNode objects to SKSpriteNode objects. I ended up having to go back to basics and use Core Graphics to do the heavy lifting. This is a rather messy way of doing things, I'm sure, but I wanted quick results to dynamically create objects that would resemble the results obtained when using SKShapeNode.

    I am only interested in making circle objects at present, so I did it like this:

    -(SKSpriteNode *)createSpriteMatchingSKShapeNodeWithRadius:(float)radius color:(SKColor *)color {
        CALayer *drawingLayer = [CALayer layer];
        CALayer *circleLayer = [CALayer layer];
        circleLayer.frame = CGRectMake(0,0,radius*2.0f,radius*2.0f);
        circleLayer.backgroundColor = color.CGColor;
        circleLayer.cornerRadius = circleLayer.frame.size.width/2.0;
        circleLayer.masksToBounds = YES;
    
    
        [drawingLayer addSublayer:circleLayer];
    
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(circleLayer.frame.size.width, circleLayer.frame.size.height), NO, [UIScreen mainScreen].scale);
        CGContextSetAllowsAntialiasing(UIGraphicsGetCurrentContext(), TRUE);
        CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor clearColor].CGColor);
        CGContextFillRect(UIGraphicsGetCurrentContext(), CGRectMake(0,0,circleLayer.frame.size.width,circleLayer.frame.size.height));
        [drawingLayer renderInContext: UIGraphicsGetCurrentContext()];
    
        UIImage *layerImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImage:layerImage]];
    
    
        return sprite;
    }
    

    The resulting sprite can now be masked by an SKCropNode as expected. As these sprites are all generated before the scene begins, I do not notice a performance hit. However, I would imagine this method is highly inefficient if you are generating multiple nodes on the fly.

    I would be eager to hear solutions from other users. Hope that helps.

    -DC

    0 讨论(0)
  • 2020-12-31 14:56

    I have the similar task in my app. I need to draw multiple irregular shapes based on user input and then use them as crop node's masks.

    The solution that works for me is to:

    1. create a SKShapeNode with the required path

    2. retrieve a SKTexture from it using SKView method textureFromNode:crop:

    3. create a SKSpriteNode from that texture.

    4. use SKSprite node as a mask.

    0 讨论(0)
  • 2020-12-31 15:02

    Your title is correct. I've also discovered having a ShapeNode in the CropNode's hierarchy affects the children above it as well. I created a quick experiment. You can create a new game project and try it yourself. By commenting out one of the addChild:shapeContent lines you can see how it affects the cropping of the spaceship image.

    As DoctorClod points out the current solution seems to be making sure all children of the cropNode are SpriteNodes.

    -(void)didMoveToView:(SKView *)view {
    
    SKSpriteNode* colorBackground = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(800, 600)];
    
    SKSpriteNode *spaceshipImage = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
    
    SKShapeNode* shapeContent = [SKShapeNode shapeNodeWithRect:CGRectMake(0, 0, 200, 100)];
    shapeContent.fillColor = [SKColor greenColor];
    
    SKSpriteNode *maskShape  = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size:CGSizeMake(500, 100)];
    
    SKCropNode *cropNode = [SKCropNode new];
    
    [cropNode addChild:colorBackground];
    [cropNode addChild:shapeContent];     // comment this one out
    [cropNode addChild:spaceshipImage];
    [cropNode addChild:shapeContent];     // or comment this one out
    
    [cropNode setMaskNode:maskShape];
    
    cropNode.position = CGPointMake(CGRectGetMidX (self.frame), CGRectGetMidY(self.frame));
    [self addChild:cropNode];
    }
    
    0 讨论(0)
提交回复
热议问题