【问题标题】:How to making a spotlight effect with SpriteKit?如何使用 SpriteKit 制作聚光灯效果?
【发布时间】:2017-12-02 16:03:35
【问题描述】:

在我问这个问题之前,我已经仔细检查了以下问题和示例:

  1. SKCropNode not working on device while working on simulator

  2. Swift 3: cut a hole in a SKSpriteNode

以上方法在所有模拟器上都可以正常工作,但在真实设备上却不行。

我在 ObjetiveC 中的代码:

SKSpriteNode* mask = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:size];
mask.position = CGPointMake(size.width/2, size.height/2);
mask.name = @"Mask";
mask.alpha = 0.5;
mask.zPosition = 3;

SKSpriteNode* node = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:size];
node.position = CGPointMake(size.width/2, size.height/2);
node.name = @"circleMask";
node.zPosition = 1;
node.alpha = 1;
SKShapeNode* circleNode = [SKShapeNode shapeNodeWithCircleOfRadius:100/2+20];
circleNode.fillColor = [UIColor whiteColor];
circleNode.lineWidth = 0;
circleNode.alpha = 1;
circleNode.position = CGPointMake(80, -200);
circleNode.name = @"circleNode";
circleNode.zPosition = 1;
circleNode.blendMode = SKBlendModeSubtract;
[node addChild:circleNode];

SKCropNode* cropNode = [[SKCropNode alloc] init];
cropNode.name = @"cropNode";
cropNode.position = CGPointZero;
cropNode.zPosition = 2;
[cropNode setMaskNode: node];
[cropNode addChild:mask];
[scene addChild:cropNode];

我想知道是否有人使用上述类似方法成功实现了该功能,如果是,请稍微澄清一下,如果没有,您可以发布您的解决方案吗?非常感谢。

我附上了一张图片来显示在模拟器和 iPhone 6 上运行的相同代码: Picture to show the issue

我的计划:

我将不使用 SKCropNode,而是以编程方式在正确位置创建一个带有孔的 UIImage,并将其渲染为 SKSpriteNode 的纹理。我已经通过使用创建的 UIImage 初始化 SKSpriteNode 来实现该功能:

-(instancetype)init{
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
    CGRect spotLightRect = CGRectMake(100,100,200,200); // adjust this as desired!
    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0);
    CGContextRef c = UIGraphicsGetCurrentContext();
    UIColor*bColor = [UIColor colorWithRed:0 green:0.0 blue:0 alpha:0.5];
    CGContextSetFillColorWithColor(c, bColor.CGColor);
    CGContextFillRect(c, rect); //the mask
    UIColor*aColor = [UIColor colorWithRed:0 green:0.0 blue:0 alpha:1];
    CGContextSetFillColorWithColor(c, aColor.CGColor);
    CGContextSetBlendMode(c, kCGBlendModeClear);
    CGContextFillEllipseInRect(c, spotLightRect); //the hole
    UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    SKTexture* texture = [SKTexture textureWithImage:image];
    self = [super initWithTexture:texture];
    return self;
}

【问题讨论】:

  • 为什么你的掩码 alpha 是 0.5?

标签: ios sprite-kit


【解决方案1】:

你的位置和数学有问题,我会分解它

离开:

SKSpriteNode* mask = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:size];

删除:

mask.position = CGPointMake(size.width/2, size.height/2);

离开:

mask.name = @"Mask";
mask.alpha = 0.5;

删除:

mask.zPosition = 3;

离开:

SKSpriteNode* node = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:size];

删除:

node.position = CGPointMake(size.width/2, size.height/2);

离开:

node.name = @"circleMask";

删除:

node.zPosition = 1;

离开:

node.alpha = 1;
SKShapeNode* circleNode = [SKShapeNode shapeNodeWithCircleOfRadius:100/2 + 20];
circleNode.fillColor = [UIColor whiteColor];
circleNode.lineWidth = 0;
circleNode.alpha = 1;
circleNode.position = CGPointMake(80, -200);
circleNode.name = @"circleNode";

删除:

circleNode.zPosition = 1;

离开:

circleNode.blendMode = SKBlendModeSubtract;
[node addChild:circleNode];

SKCropNode* cropNode = [[SKCropNode alloc] init];
cropNode.name = @"cropNode";
cropNode.position = CGPointZero;
cropNode.zPosition = 2;
[cropNode setMaskNode: node];
[cropNode addChild:mask];
[scene addChild:cropNode];

最终结果:

SKSpriteNode* mask = [SKSpriteNode spriteNodeWithColor:[UIColor blackColor] size:size];
mask.name = @"Mask";
mask.alpha = 0.5;

SKSpriteNode* node = [SKSpriteNode spriteNodeWithColor:[UIColor whiteColor] size:size];
node.name = @"circleMask";
node.alpha = 1;
SKShapeNode* circleNode = [SKShapeNode shapeNodeWithCircleOfRadius:100/2+20];
circleNode.fillColor = [UIColor whiteColor];
circleNode.lineWidth = 0;
circleNode.alpha = 1;
circleNode.position = CGPointMake(80, -200);
circleNode.name = @"circleNode";
circleNode.blendMode = SKBlendModeSubtract;
[node addChild:circleNode];

SKCropNode* cropNode = [[SKCropNode alloc] init];
cropNode.name = @"cropNode";
cropNode.position = CGPointZero;
cropNode.zPosition = 2;
[cropNode setMaskNode: node];
[cropNode addChild:mask];
[scene addChild:cropNode];

你现在应该有一个黑屏,在 80,-200 处有一个洞

【讨论】:

  • @KnightOfDragon 非常感谢您的及时回复。我尝试了您的最终示例代码,不幸的是,它不能在真实设备上打洞,我在 iPhone 6、iPhone 5s、iPhone 7 和 IOS 10、11 上进行了测试。但它确实适用于所有模拟器。你还有什么想法吗?
  • 你用什么方法做这个?
  • 我刚刚创建了一个非常简单的 SK 项目,其中只有您的代码。只有一个 SKView、一个 SKScene 和一个 SKSpriteNode。但它不起作用。
  • 我不太确定你的问题是什么,我只是把它放在我的 ViewController 中的 viewDidLoad 中,在那里我初始化了一个 SKView 、一个 SKScene 和一个 SKSpriteNode。