且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 SpriteKit 中模糊场景?

更新时间:2022-06-23 06:04:31

您正在寻找的是一个 SKEffectNode.它将 CoreImage 过滤器应用于自身(以及所有子节点).只需将其设为场景的根视图,为其添加 CoreImage 的模糊滤镜之一,即可完成设置.

What you're looking for is an SKEffectNode. It applies a CoreImage filter to itself (and thus all subnodes). Just make it the root view of your scene, give it one of CoreImage's blur filters, and you're set.

例如,我设置了一个 SKScene,其中一个 SKEffectNode 作为它的第一个子节点和一个属性,root 包含一个弱引用给它:

For example, I set up an SKScene with an SKEffectNode as it's first child node and a property, root that holds a weak reference to it:

-(void)createLayers{
  SKEffectNode *node = [SKEffectNode node];
  [node setShouldEnableEffects:NO];
  CIFilter *blur = [CIFilter filterWithName:@"CIGaussianBlur" keysAndValues:@"inputRadius", @1.0f, nil];
  [node setFilter:blur];
  [self setRoot:node];
}

这是我用来(动画!)我的场景模糊的方法:

And here's the method I use to (animate!) the blur of my scene:

-(void)blurWithCompletion:(void (^)())handler{
  CGFloat duration = 0.5f;
  [[self root] setShouldRasterize:YES];
  [[self root] setShouldEnableEffects:YES];
  [[self root] runAction:[SKAction customActionWithDuration:duration actionBlock:^(SKNode *node, CGFloat elapsedTime){
    NSNumber *radius = [NSNumber numberWithFloat:(elapsedTime/duration) * 10.0];
    [[(SKEffectNode *)node filter] setValue:radius forKey:@"inputRadius"];
  }] completion:handler];
}

请注意,和您一样,我将其用作暂停屏幕,因此我将场景栅格化.如果您希望您的场景在模糊时进行动画处理,您可能应该将 setShouldResterize: 设置为 NO.

Note that, like you, I'm using this as a pause screen, so I rasterize the scene. If you want your scene to animate while blurred, you should probably setShouldResterize: to NO.

如果你对动画过渡到模糊不感兴趣,你总是可以将滤镜设置为 10.0f 左右的初始半径,然后执行一个简单的 setShouldEnableEffects:YES 当你想打开它时.

And if you're not interested in animating the transition to the blur, you could always just set the filter to an initial radius of 10.0f or so and do a simple setShouldEnableEffects:YES when you want to switch it on.

另请参阅:SKEffectNode 类参考

更新:
请参阅下面的马库斯评论.他指出 SKScene 实际上是 SKEffectNode 的子类,所以你真的应该能够在场景本身上调用所有这些,而不是随意插入一个节点树中的效果节点.

UPDATE:
See Markus's comment below. He points out that SKScene is, in fact, a subclass of SKEffectNode, so you really ought to be able to call all of this on the scene itself rather than arbitrarily inserting an effect node in your node tree.