如何在SpriteKit的SKScene中爲所有節點添加高斯模糊(沒有固定數量的節點)?稍後會在場景頂部添加標籤,這將是我的暫停菜單。 幾乎任何事情都會有所幫助!如何在SpriteKit中模糊場景?
像這樣的東西是什麼,我去爲:
如何在SpriteKit的SKScene中爲所有節點添加高斯模糊(沒有固定數量的節點)?稍後會在場景頂部添加標籤,這將是我的暫停菜單。 幾乎任何事情都會有所幫助!如何在SpriteKit中模糊場景?
像這樣的東西是什麼,我去爲:
什麼你要找的是一個SKEffectNode
。它將CoreImage過濾器應用於自身(以及所有子節點)。只要將它作爲場景的根視圖,給它一個CoreImage的模糊濾鏡,然後設置好。
例如,我建立了一個SKScene
與SKEffectNode
,因爲它是第一個子節點和屬性,root
保持一個弱引用時:
-(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];
}
這裏是我用來(動畫的方法! )我的場景的模糊:
-(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
。
如果你不感興趣的動畫過渡到模糊,你總是可以只過濾器設置爲10.0f
左右的初始半徑,做一個簡單的setShouldEnableEffects:YES
當你想打開它。
參見:SKEffectNode class reference
更新:下面
見馬庫斯的評論。他指出SKScene
實際上是SKEffectNode
的一個子類,所以你真的應該能夠在場景中調用所有這些,而不是在節點樹中任意插入一個效果節點。
你是如何將節點添加爲孩子的? [self addChild:node]; //它會拋出一個錯誤=>(lldb) 是否將示例輸入到ViewController? –
我真的不明白錯誤在哪裏。 這是我的代碼,http://postimg.org/image/bg8qb70rp/ 它不顯示任何錯誤,但它也不顯示任何操作。 –
哦,我發現這個問題,它不適用於我Restarized YES .. –
這是我對暫停屏幕的解決方案。 它會截圖,模糊它,然後用動畫顯示它。 我認爲你應該這樣做,如果你不想浪費到太多的fps。
-(void)pause {
SKSpriteNode *pauseBG = [SKSpriteNode spriteNodeWithTexture:[SKTexture textureWithImage:[self getBluredScreenshot]]];
pauseBG.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));
pauseBG.alpha = 0;
pauseBG.zPosition = 2;
[pauseBG runAction:[SKAction fadeAlphaTo:1 duration:duration/2]];
[self addChild:pauseBG];
}
這是輔助方法:
- (UIImage *)getBluredScreenshot {
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 1);
[self.view drawViewHierarchyInRect:self.view.frame afterScreenUpdates:YES];
UIImage *ss = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CIFilter *gaussianBlurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[gaussianBlurFilter setDefaults];
[gaussianBlurFilter setValue:[CIImage imageWithCGImage:[ss CGImage]] forKey:kCIInputImageKey];
[gaussianBlurFilter setValue:@10 forKey:kCIInputRadiusKey];
CIImage *outputImage = [gaussianBlurFilter outputImage];
CIContext *context = [CIContext contextWithOptions:nil];
CGRect rect = [outputImage extent];
rect.origin.x += (rect.size.width - ss.size.width)/2;
rect.origin.y += (rect.size.height - ss.size.height)/2;
rect.size = ss.size;
CGImageRef cgimg = [context createCGImage:outputImage fromRect:rect];
UIImage *image = [UIImage imageWithCGImage:cgimg];
CGImageRelease(cgimg);
return image;
}
要使用@Bendegúz的答案和代碼http://www.bytearray.org/?p=5360
我能得到這個在我目前的遊戲工作添加到此這個項目正在IOS 8 Swift中完成。通過返回一個SKSpriteNode而不是一個UIImage來完成一點。另請注意,我的解包currentScene.view!調用是一個弱GameScene引用,但應根據您調用這些方法的位置與self.view.frame一起工作。我的暫停屏幕在單獨的HUD類中被調用,因此爲何如此。
我想這可能會做得更優雅,也許更像是@ jemmons的答案。只是想幫助其他人試圖在所有或某些Swift代碼中編寫SpriteKit項目。
func getBluredScreenshot() -> SKSpriteNode{
create the graphics context
UIGraphicsBeginImageContextWithOptions(CGSize(width: currentScene.view!.frame.size.width, height: currentScene.view!.frame.size.height), true, 1)
currentScene.view!.drawViewHierarchyInRect(currentScene.view!.frame, afterScreenUpdates: true)
// retrieve graphics context
let context = UIGraphicsGetCurrentContext()
// query image from it
let image = UIGraphicsGetImageFromCurrentImageContext()
// create Core Image context
let ciContext = CIContext(options: nil)
// create a CIImage, think of a CIImage as image data for processing, nothing is displayed or can be displayed at this point
let coreImage = CIImage(image: image)
// pick the filter we want
let filter = CIFilter(name: "CIGaussianBlur")
// pass our image as input
filter.setValue(coreImage, forKey: kCIInputImageKey)
//edit the amount of blur
filter.setValue(3, forKey: kCIInputRadiusKey)
//retrieve the processed image
let filteredImageData = filter.valueForKey(kCIOutputImageKey) as CIImage
// return a Quartz image from the Core Image context
let filteredImageRef = ciContext.createCGImage(filteredImageData, fromRect: filteredImageData.extent())
// final UIImage
let filteredImage = UIImage(CGImage: filteredImageRef)
// create a texture, pass the UIImage
let texture = SKTexture(image: filteredImage!)
// wrap it inside a sprite node
let sprite = SKSpriteNode(texture:texture)
// make image the position in the center
sprite.position = CGPointMake(CGRectGetMidX(currentScene.frame), CGRectGetMidY(currentScene.frame))
var scale:CGFloat = UIScreen.mainScreen().scale
sprite.size.width *= scale
sprite.size.height *= scale
return sprite
}
func loadPauseBGScreen(){
let duration = 1.0
let pauseBG:SKSpriteNode = self.getBluredScreenshot()
//pauseBG.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame))
pauseBG.alpha = 0
pauseBG.zPosition = self.zPosition + 1
pauseBG.runAction(SKAction.fadeAlphaTo(1, duration: duration))
self.addChild(pauseBG)
}
查克,標籤上寫着objective-c。 –
這是獲得此斯威夫特2完成,無需層層另一個例子:
func blurWithCompletion() {
let duration: CGFloat = 0.5
let filter: CIFilter = CIFilter(name: "CIGaussianBlur", withInputParameters: ["inputRadius" : NSNumber(double:1.0)])!
scene!.filter = filter
scene!.shouldRasterize = true
scene!.shouldEnableEffects = true
scene!.runAction(SKAction.customActionWithDuration(0.5, actionBlock: { (node: SKNode, elapsedTime: CGFloat) in
let radius = (elapsedTime/duration)*10.0
(node as? SKEffectNode)!.filter!.setValue(radius, forKey: "inputRadius")
}))
}
斯威夫特3更新:這@Chuck加夫尼的回答更新的斯威夫特3 。我知道這個問題被標記爲objective-c,但是這個頁面在Google中名列第二,因爲「swritekit blur」很快。我將currentScene更改爲self。
func getBluredScreenshot() -> SKSpriteNode{
//create the graphics context
UIGraphicsBeginImageContextWithOptions(CGSize(width: self.view!.frame.size.width, height: self.view!.frame.size.height), true, 1)
self.view!.drawHierarchy(in: self.view!.frame, afterScreenUpdates: true)
// retrieve graphics context
_ = UIGraphicsGetCurrentContext()
// query image from it
let image = UIGraphicsGetImageFromCurrentImageContext()
// create Core Image context
let ciContext = CIContext(options: nil)
// create a CIImage, think of a CIImage as image data for processing, nothing is displayed or can be displayed at this point
let coreImage = CIImage(image: image!)
// pick the filter we want
let filter = CIFilter(name: "CIGaussianBlur")
// pass our image as input
filter?.setValue(coreImage, forKey: kCIInputImageKey)
//edit the amount of blur
filter?.setValue(3, forKey: kCIInputRadiusKey)
//retrieve the processed image
let filteredImageData = filter?.value(forKey: kCIOutputImageKey) as! CIImage
// return a Quartz image from the Core Image context
let filteredImageRef = ciContext.createCGImage(filteredImageData, from: filteredImageData.extent)
// final UIImage
let filteredImage = UIImage(cgImage: filteredImageRef!)
// create a texture, pass the UIImage
let texture = SKTexture(image: filteredImage)
// wrap it inside a sprite node
let sprite = SKSpriteNode(texture:texture)
// make image the position in the center
sprite.position = CGPoint(x: self.frame.midX, y: self.frame.midY)
let scale:CGFloat = UIScreen.main.scale
sprite.size.width *= scale
sprite.size.height *= scale
return sprite
}
func loadPauseBGScreen(){
let duration = 1.0
let pauseBG:SKSpriteNode = self.getBluredScreenshot()
pauseBG.alpha = 0
pauseBG.zPosition = self.zPosition + 1
pauseBG.run(SKAction.fadeAlpha(to: 1, duration: duration))
self.addChild(pauseBG)
}
斯威夫特4:當你想用它
let blur = CIFilter(name:"CIGaussianBlur",withInputParameters: ["inputRadius": 10.0])
self.filter = blur
self.shouldRasterize = true
self.shouldEnableEffects = false
變化self.shouldEnableEffects =真:
這一點,如果你想在場景中的一切模糊添加到您的gameScene 。
您可能會發現此鏈接有用:[http://eppz.eu/blog/create-ios-7-blur-effect/](http://eppz.eu/blog/create-ios-7-blur -effect /) – JKallio
不,我不想導入任何東西,我希望它是全部SKScene,我不能使用UIView中的任何東西 –