我一直在尝试使用SKCropNode将掩码应用于SKShapeNode,到目前为止还没有成功。认为这是一个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));
是否有人对此问题有解决方法?非常感谢!
答案 0 :(得分:9)
这一天大部分时间一直困扰着我。我曾计划创建一个类似于优秀TCProgressTimer by Tony Chamblee的计时器。但是,由于我的应用程序使用多个进度计时器,因此我不想设计数十种不同大小的精灵,以便在不同的分辨率下使用。
我的解决方案是将SKShapeNode
个对象转换为SKSpriteNode
个对象。我最终不得不回到基础并使用Core Graphics来完成繁重的任务。这是一种相当混乱的做事方式,我敢肯定,但我希望快速结果动态创建与使用SKShapeNode
时获得的结果相似的对象。
我目前只对制作圆形物品感兴趣,所以我这样做了:
-(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;
}
生成的精灵现在可以按预期被SKCropNode
屏蔽。由于这些精灵都是在场景开始之前生成的,所以我没有注意到性能受到影响。但是,如果你动态生成多个节点,我认为这种方法效率很低。
我很想听听其他用户的解答。希望有所帮助。
-DC
答案 1 :(得分:5)
我的应用程序中有类似的任务。我需要根据用户输入绘制多个不规则形状,然后将它们用作裁剪节点的蒙版。
对我有用的解决方案是:
使用所需路径创建SKShapeNode
使用SKView方法textureFromNode:crop:
从该纹理创建SKSpriteNode。
使用SKSprite节点作为掩码。
答案 2 :(得分:2)
你的头衔是对的。我还发现在CropNode的层次结构中有一个ShapeNode也会影响它上面的子节点。我创建了一个快速实验。您可以创建一个新的游戏项目并亲自尝试。通过注释掉addChild:shapeContent线之一,您可以看到它如何影响太空飞船图像的裁剪。
正如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];
}