Ios 如何通过SKEffectNode在精灵周围创建光晕

Ios 如何通过SKEffectNode在精灵周围创建光晕,ios,iphone,sprite-kit,skeffectnode,Ios,Iphone,Sprite Kit,Skeffectnode,我有一个SKSpriteNode,我希望在它的边缘周围有一个蓝色的光晕,以便高亮显示。我猜我需要将我的精灵设置为SKEffectNode的子元素,然后创建/应用某种过滤器 更新:我用所选答案的方法对此进行了大量调查,发现SKEffectNode对性能有很大影响,即使您将其设置为shouldRasterize并定义了“无过滤器”。我的结论是,如果游戏一次需要10个以上的移动对象,即使光栅化,它们也不能包含SKEffectNode 我的解决方案可能涉及预渲染的辉光图像/动画,因为SKEffectNo

我有一个
SKSpriteNode
,我希望在它的边缘周围有一个蓝色的光晕,以便高亮显示。我猜我需要将我的精灵设置为
SKEffectNode
的子元素,然后创建/应用某种过滤器

更新:我用所选答案的方法对此进行了大量调查,发现
SKEffectNode
对性能有很大影响,即使您将其设置为
shouldRasterize
并定义了“无过滤器”。我的结论是,如果游戏一次需要10个以上的移动对象,即使光栅化,它们也不能包含
SKEffectNode

我的解决方案可能涉及预渲染的辉光图像/动画,因为SKEffectNode不会根据我的要求对其进行剪切

如果有人能洞察到我所遗漏的任何东西,我会很高兴听到你所知道的一切


我之所以接受答案,是因为它确实达到了我的要求,但我想向任何希望走这条路线的人添加这些注释,因此,您可以了解使用
SKEffectNode

的一些问题。您可以在精灵后面使用
SKShapeNode
,并使用其
glowWidth
strokeColor
属性定义辉光。如果您的大小和位置正确,这将给您一个辉光的外观。这并没有为您提供许多定制选项,但我认为这比使用带有
SKEffectNode
CIFilter
要容易得多,这可能是您在这方面的另一个逻辑选项。

您可以通过创建一个组成多个内置过滤器的
CIFilter
子类,在核心图像中创建辉光效果。此类过滤器将包括以下步骤:

  • 创建要用作蓝色光晕的图像。也许有一些不错的方法可以做到这一点;一种是使用
    CIColorMatrix
    创建输入图像的单色版本
  • 放大并模糊光晕图像(
    CiAffinetTransform
    +
    CIGaussianBlur
  • 在辉光图像上合成原始输入图像(
    CISourceOverCompositing
  • 一旦你有了一个
    CIFilter
    子类来完成这一切,你就可以将它与
    SKEffectNode
    一起使用,在效果节点的子节点周围实时发光。在这里,它运行在iPad 4上的“精灵工具包游戏”Xcode模板中:

    通过抄袭WWDC 2013场景工具包演示中用于类似效果的自定义过滤器类,我在几分钟内就实现了这一点——从位于的WWDC示例代码包中获取它,然后查找ASCGlowFilter类。(如果您想在iOS上使用该代码,您需要将
    NSAffineTransform
    部分改为使用
    cAffinetransform
    。我还将
    centerX
    centerY
    属性替换为
    inputCenter
    类型的
    CIVector
    参数,以便Sprite工具包可以自动将效果集中在精灵。)

    我说的是“实时”发光吗?是的!这是“真正消耗CPU时间”的缩写。请注意,在屏幕截图中,即使只有一艘宇宙飞船,它也不再固定在每秒60帧的速度上——并且在iOS模拟器上使用OpenGL ES renderer软件,它以幻灯片的速度运行。如果你在Mac上,你可能有多余的硅。。。但如果你想在游戏中做到这一点,请记住以下几点:

    • 可能有一些方法可以提高过滤器本身的性能。使用不同的CI过滤器,您可能会看到一些改进(核心图像中有几个模糊过滤器,其中一些肯定比高斯更快)。还请注意,模糊效果往往是碎片着色器绑定的,因此图像越小,光晕半径越小越好
    • <> LI>如果你想在场景中有多个发光,考虑把所有发光的精灵都放在同一个效果节点上,让它们都变成一个图像,然后应用一次过滤器。
    • 如果要发光的精灵变化不大(例如,如果我们的宇宙飞船没有旋转),则在“效果”节点上设置
      应该光栅化
      。(实际上,在这种情况下,通过旋转效果节点而不是其中的精灵,您可能会得到一些改进。)
    • 你真的需要实时发光吗?与游戏中的许多漂亮的图形效果一样,如果你伪造它,你会获得更好的性能。在您喜爱的图形编辑器中制作一个模糊、蓝色的宇宙飞船,并将其作为另一个精灵放置在场景中

      • @rickster的答案很好。由于我的代表性很低,我显然不允许将此代码添加到他的评论中。我希望这不会违反礼仪规则。我不想以任何方式利用他的代表

        下面是他在回答中描述的代码:

        标题:

        //  ENHGlowFilter.h
        #import <CoreImage/CoreImage.h>
        
        @interface ENHGlowFilter : CIFilter
        
        @property (strong, nonatomic) UIColor *glowColor;
        @property (strong, nonatomic) CIImage *inputImage;
        @property (strong, nonatomic) NSNumber *inputRadius;
        @property (strong, nonatomic) CIVector *inputCenter;
        
        @end
        
        //Based on ASCGLowFilter from Apple
        
        使用中:

        @implementation ENHMyScene //SKScene subclass
        
        -(id)initWithSize:(CGSize)size {    
            if (self = [super initWithSize:size]) {
                /* Setup your scene here */
                [self setAnchorPoint:(CGPoint){0.5, 0.5}];
                self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
        
                SKEffectNode *effectNode = [[SKEffectNode alloc] init];
                ENHGlowFilter *glowFilter = [[ENHGlowFilter alloc] init];
                [glowFilter setGlowColor:[[UIColor redColor] colorWithAlphaComponent:0.5]];
                [effectNode setShouldRasterize:YES];
                [effectNode setFilter:glowFilter];
                [self addChild:effectNode];
                _effectNode = effectNode;
            }
            return self;
        }
        
        -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
            /* Called when a touch begins */
        
            for (UITouch *touch in touches) {
                CGPoint location = [touch locationInNode:self];
                SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
                sprite.position = location;
                [self.effectNode addChild:sprite];
            }
        }
        

        我尝试了一些方法,但还没有找到解决方案-无法使EffectNode“笔划”图像。如何使用SKShapeNode获得效果?你的意思是创建一个与SKspriteNode轮廓相匹配的形状,然后使其发光并将其置于SKspriteNode后面?精灵不是正方形的,有没有办法创建一个与精灵匹配的形状模型?物理引擎能为collison做到这一点吗?正如rickster提到的,这基本上是伪造的,但在这个过程中节省了大量的性能。您将创建精灵的路径,并在
        SKShapeNode
        中的精灵后面使用。我会用一个固定的关节或类似的东西连接它,然后关闭它的物理功能,让它基本上跟随精灵-让精灵处理物理/碰撞。我想问的是,是否有一种方法可以创建一个SKSpriteNode的SKShapeNode路径。最好有一种方法来创建一个遵循SKSpriteNode轮廓的SKShapeNode路径。不,没有自动的方法。有一些外部工具可以渲染到
        @implementation ENHMyScene //SKScene subclass
        
        -(id)initWithSize:(CGSize)size {    
            if (self = [super initWithSize:size]) {
                /* Setup your scene here */
                [self setAnchorPoint:(CGPoint){0.5, 0.5}];
                self.backgroundColor = [SKColor colorWithRed:0.15 green:0.15 blue:0.3 alpha:1.0];
        
                SKEffectNode *effectNode = [[SKEffectNode alloc] init];
                ENHGlowFilter *glowFilter = [[ENHGlowFilter alloc] init];
                [glowFilter setGlowColor:[[UIColor redColor] colorWithAlphaComponent:0.5]];
                [effectNode setShouldRasterize:YES];
                [effectNode setFilter:glowFilter];
                [self addChild:effectNode];
                _effectNode = effectNode;
            }
            return self;
        }
        
        -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
            /* Called when a touch begins */
        
            for (UITouch *touch in touches) {
                CGPoint location = [touch locationInNode:self];
                SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:@"Spaceship"];
                sprite.position = location;
                [self.effectNode addChild:sprite];
            }
        }