pro*_*cal 20 iphone ios sprite-kit skeffectnode
我有一个SKSpriteNode
我希望在它的边缘有蓝色光晕以突出显示目的.我猜我需要让我的精灵成为a的孩子,SKEffectNode
然后创建/应用某种过滤器.
更新:我已经使用所选答案的方法调查了这一点,并发现SKEffectNode
即使你已经设置为shouldRasterize
"无过滤器"定义,它也会有相当大的性能.我的结论是,如果你的游戏一次需要10个以上的移动物体,SKEffectNode
即使是光栅化也不会涉及到它们.
我的解决方案可能涉及预渲染的发光图像/动画,因为SKEffectNode不会根据我的要求削减它.
如果有人对我失踪的任何事情有所了解,我会很感激你所知道的一切!
我接受了答案,因为它确实实现了我的要求,但是想要将这些笔记添加到任何想要走这条路线的人,这样你就可以了解使用中的一些问题SKEffectNode
.
小智 26
@ rickster的答案很棒.由于我有低代表,我显然不允许将此代码作为评论添加到他的.我希望这不会破坏stackoverflow适当的规则.我不是试图以任何方式使用他的代表.
这里的代码完成了他在答案中描述的内容:
标题:
// 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
Run Code Online (Sandbox Code Playgroud)
执行:
#import "ENHGlowFilter.h"
@implementation ENHGlowFilter
-(id)init
{
self = [super init];
if (self)
{
_glowColor = [UIColor whiteColor];
}
return self;
}
- (NSArray *)attributeKeys {
return @[@"inputRadius", @"inputCenter"];
}
- (CIImage *)outputImage {
CIImage *inputImage = [self valueForKey:@"inputImage"];
if (!inputImage)
return nil;
// Monochrome
CIFilter *monochromeFilter = [CIFilter filterWithName:@"CIColorMatrix"];
CGFloat red = 0.0;
CGFloat green = 0.0;
CGFloat blue = 0.0;
CGFloat alpha = 0.0;
[self.glowColor getRed:&red green:&green blue:&blue alpha:&alpha];
[monochromeFilter setDefaults];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:red] forKey:@"inputRVector"];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:green] forKey:@"inputGVector"];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:blue] forKey:@"inputBVector"];
[monochromeFilter setValue:[CIVector vectorWithX:0 Y:0 Z:0 W:alpha] forKey:@"inputAVector"];
[monochromeFilter setValue:inputImage forKey:@"inputImage"];
CIImage *glowImage = [monochromeFilter valueForKey:@"outputImage"];
// Scale
float centerX = [self.inputCenter X];
float centerY = [self.inputCenter Y];
if (centerX > 0) {
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, centerX, centerY);
transform = CGAffineTransformScale(transform, 1.2, 1.2);
transform = CGAffineTransformTranslate(transform, -centerX, -centerY);
CIFilter *affineTransformFilter = [CIFilter filterWithName:@"CIAffineTransform"];
[affineTransformFilter setDefaults];
[affineTransformFilter setValue:[NSValue valueWithCGAffineTransform:transform] forKey:@"inputTransform"];
[affineTransformFilter setValue:glowImage forKey:@"inputImage"];
glowImage = [affineTransformFilter valueForKey:@"outputImage"];
}
// Blur
CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[gaussianBlurFilter setDefaults];
[gaussianBlurFilter setValue:glowImage forKey:@"inputImage"];
[gaussianBlurFilter setValue:self.inputRadius ?: @10.0 forKey:@"inputRadius"];
glowImage = [gaussianBlurFilter valueForKey:@"outputImage"];
// Blend
CIFilter *blendFilter = [CIFilter filterWithName:@"CISourceOverCompositing"];
[blendFilter setDefaults];
[blendFilter setValue:glowImage forKey:@"inputBackgroundImage"];
[blendFilter setValue:inputImage forKey:@"inputImage"];
glowImage = [blendFilter valueForKey:@"outputImage"];
return glowImage;
}
@end
Run Code Online (Sandbox Code Playgroud)
正在使用:
@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];
}
}
Run Code Online (Sandbox Code Playgroud)
ric*_*ter 22
您可以通过创建CIFilter
组成多个内置过滤器的子类在Core Image中创建发光效果.这样的过滤器将涉及以下步骤:
CIColorMatrix
创建输入图像的单色版本.CIAffineTransform
+ CIGaussianBlur
).CISourceOverCompositing
).一旦你有一个CIFilter
完成所有这些的子类,你可以使用它SKEffectNode
来获得效果节点的子节点周围的实时光晕.它在iPad 4上的"Sprite Kit Game"Xcode模板中运行:
我在几分钟内完成了这项工作,并在WWDC 2013的Scene Kit演示文稿中使用了类似效果的自定义过滤器类 - 从developer.apple.com/downloads上的WWDC示例代码包中获取它,并查看为了ASCGlowFilter
上课.(如果你想在iOS上使用那个代码,你需要更改NSAffineTransform
要使用的部分CGAffineTransform
.我还用类型参数替换了centerX
和centerY
属性,因此Sprite Kit可以自动将效果置于精灵中心.)inputCenter
CIVector
我说"实时"发光吗?对!这是"真正吃掉CPU时间"的缩写.请注意,在屏幕截图中,它不再固定在60 fps,即使只有一个太空飞船 - 并且在iOS模拟器上使用软件OpenGL ES渲染器,它以幻灯片速度运行.如果你在Mac上,你可能还有硅片......但是如果你想在你的游戏中做到这一点,请记住一些事情:
shouldRasterize
到YES
效果节点应该会有很大帮助.(实际上,在这种情况下,您可以通过旋转效果节点而不是其中的精灵来获得一些改进.) 归档时间: |
|
查看次数: |
16353 次 |
最近记录: |