简体   繁体   English

在SpriteKit中,SKCropNode对SKShapeNode没有影响

[英]In SpriteKit, SKCropNode has no effect over a SKShapeNode

I've been trying to apply a mask to a SKShapeNode using SKCropNode, and so far without success. 我一直在尝试使用SKCropNode将掩码应用于SKShapeNode,到目前为止还没有成功。 Thinking that it's a SpriteKit bug - Here is the code snippet: 认为这是一个SpriteKit错误 - 这是代码片段:

SKNode* contentNode = [SKNode node];

// picture - use an image bigger than 50x50
SKSpriteNode *pictureNode = [SKSpriteNode spriteNodeWithImageNamed:@"tree"];

// triangle
SKShapeNode* triangleNode = [SKShapeNode node];
UIBezierPath* triangleNodeBezierPath = [[UIBezierPath alloc] init];
[triangleNodeBezierPath moveToPoint:CGPointMake(0.0, 0.0)];
[triangleNodeBezierPath addLineToPoint:CGPointMake(0.0, 100.0)];
[triangleNodeBezierPath addLineToPoint:CGPointMake(50.0, 100.0)];
[triangleNodeBezierPath closePath];

triangleNode.path = triangleNodeBezierPath.CGPath;
triangleNode.fillColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1];

// create a mask
SKSpriteNode *mask = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor] size: CGSizeMake(50, 50)]; //50 by 50 is the size of the mask

// create a SKCropNode
SKCropNode *cropNode = [SKCropNode node];

[cropNode addChild: contentNode];
[cropNode setMaskNode: mask];

[self addChild: cropNode];
[contentNode addChild:pictureNode]; // pictureNode is being cropped
[contentNode addChild:triangleNode]; // triangleNode is not

cropNode.position = CGPointMake( CGRectGetMidX (self.frame), CGRectGetMidY (self.frame));

Does anyone have a workaround about this issue? 有没有人有关于这个问题的解决方法? Thanks a lot! 非常感谢!

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 . 我曾计划创建一个类似于Tony Chamblee的优秀TCProgressTimer的计时器。 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. 我的解决方案是将SKShapeNode对象转换为SKSpriteNode对象。 I ended up having to go back to basics and use Core Graphics to do the heavy lifting. 我最终不得不回到基础并使用Core Graphics来完成繁重的任务。 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 . 这是一种相当混乱的做事方式,我敢肯定,但我希望快速结果动态创建类似于使用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. 现在,生成的精灵可以按预期被SKCropNode屏蔽。 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 -DC

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 创建具有所需路径的SKShapeNode

  2. retrieve a SKTexture from it using SKView method textureFromNode:crop: 使用SKView方法textureFromNode:crop:从中检索SKTexture textureFromNode:crop:

  3. create a SKSpriteNode from that texture. 从该纹理创建一个SKSpriteNode。

  4. use SKSprite node as a mask. 使用SKSprite节点作为掩码。

Your title is correct. 你的头衔是对的。 I've also discovered having a ShapeNode in the CropNode's hierarchy affects the children above it as well. 我还发现在CropNode的层次结构中有一个ShapeNode也会影响它上面的子节点。 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. 通过注释掉addChild:shapeContent线之一,您可以看到它如何影响太空飞船图像的裁剪。

As DoctorClod points out the current solution seems to be making sure all children of the cropNode are SpriteNodes. 正如DoctorClod指出的那样,当前的解决方案似乎是确保cropNode的所有子节点都是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];
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM