2014-03-18 51 views
19

如何在SpriteKit的SKScene中爲所有節點添加高斯模糊(沒有固定數量的節點)?稍後會在場景頂部添加標籤,這將是我的暫停菜單。 幾乎任何事情都會有所幫助!如何在SpriteKit中模糊場景?

像這樣的東西是什麼,我去爲: Gaussian pause menu

+0

您可能會發現此鏈接有用:[http://eppz.eu/blog/create-ios-7-blur-effect/](http://eppz.eu/blog/create-ios-7-blur -effect /) – JKallio

+0

不,我不想導入任何東西,我希望它是全部SKScene,我不能使用UIView中的任何東西 –

回答

30

什麼你要找的是一個SKEffectNode。它將CoreImage過濾器應用於自身(以及所有子節點)。只要將它作爲場景的根視圖,給它一個CoreImage的模糊濾鏡,然後設置好。

例如,我建立了一個SKSceneSKEffectNode,因爲它是第一個子節點和屬性,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的一個子類,所以你真的應該能夠在場景中調用所有這些,而不是在節點樹中任意插入一個效果節點。

+0

你是如何將節點添加爲孩子的? [self addChild:node]; //它會拋出一個錯誤=>(lldb) 是否將示例輸入到ViewController? –

+0

我真的不明白錯誤在哪裏。 這是我的代碼,http://postimg.org/image/bg8qb70rp/ 它不顯示任何錯誤,但它也不顯示任何操作。 –

+0

哦,我發現這個問題,它不適用於我Restarized YES .. –

9

這是我對暫停屏幕的解決方案。 它會截圖,模糊它,然後用動畫顯示它。 我認爲你應該這樣做,如果你不想浪費到太多的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; 
} 
+2

有點太晚的項目,但我會保留它以備將來參考:) 非常感謝! –

+0

歡迎您:) –

+0

完美作品,謝謝! – StackBuddy

11

要使用@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) 

} 
+2

查克,標籤上寫着objective-c。 –

2

這是獲得此斯威夫特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") 

})) 

}

1

斯威夫特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) 

} 
0

斯威夫特4:當你想用它

let blur = CIFilter(name:"CIGaussianBlur",withInputParameters: ["inputRadius": 10.0]) 
     self.filter = blur 
     self.shouldRasterize = true 
     self.shouldEnableEffects = false 

變化self.shouldEnableEffects =真:

這一點,如果你想在場景中的一切模糊添加到您的gameScene 。