通过在顶部添加SKScene / SKView或UIView来调暗SKScene无法正常工作

时间:2016-07-26 23:58:49

标签: ios objective-c sprite-kit uikit

我正在编写一个游戏,当用户输掉时,我希望屏幕中间有一个重置按钮,其余部分变暗。出于某种原因,我无法获得透明度。我已经找到了解决方案,但无法让它与我一起工作(有太多的变量没有定义)我无法评论,因为我没有足够的代表:

Making a SKScene's background transparent not working... is this a bug?

我有一个扩展SKScene的gamecene,我将所有SKNode添加到mainView节点。我已经尝试将透明度设置为YES并在其上添加一个带有clearColor的新skscene,但它只显示一个黑屏:

SKView *dimView = [[SKView alloc] initWithFrame:self.frame];
[self.view addSubview:dimView];
[dimView setBackgroundColor:[UIColor clearColor]];
[dimView setAllowsTransparency:YES];

我知道我做错了什么我只是不知道它是什么。任何人都可以找出我的错误吗?

更新

我也试过这个,它也不起作用,也是黑屏:

CGRect screenRect = [[UIScreen mainScreen] bounds];
//create a new view with the same size
UIView* coverView = [[UIView alloc] initWithFrame:screenRect];
// change the background color to black and the opacity to 0.6
coverView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.6];
// add this new view to your main view
[self.view addSubview:coverView];

更新2:

我编辑了第一个代码集,试图用另一个skview覆盖skview,其透明度设置为true,颜色设置为clear color。这样我只得到一个灰色的屏幕。我已经在这一段时间了,似乎无法弄清楚为什么这不起作用。任何帮助将不胜感激。

更新3:

所以我认为用另一个视图覆盖视图的正确实现是这样的,但即便如此,它仍然显示一个完全黑屏:

    CGRect screenFrame = [UIScreen mainScreen].bounds;
    SKView *dimView = [[SKView alloc] initWithFrame:screenFrame];
    SKScene *currentScene = [[SKScene alloc]initWithSize:dimView.bounds.size];
    [self.view addSubview:dimView];
    [currentScene setBackgroundColor:[[UIColor clearColor] colorWithAlphaComponent:0.5f]];
    [dimView setAllowsTransparency:YES];
    [dimView presentScene:currentScene];

2 个答案:

答案 0 :(得分:0)

根据SKScene Class Reference

的概述部分
  

SKScene对象表示Sprite Kit中的内容场景。一个场景   是Sprite Kit节点(SKNode)树中的根节点。这些节点   提供场景动画和渲染显示的内容。至   显示一个场景,您可以从SKView对象中显示它。

你没有嵌套SKScene。您不能同时运行两个场景(仅在它们之间转换)。

如果你想“覆盖”两个场景,你总是要从转换中切换。

替代方案可以是GitHub项目,使用名为SpriteKitShaderTransitionExample的着色器自定义过渡场景

从下面的来源可以看出,它扩展了SKScene以集成着色器。

<强>来源:

//private let totalAnimationDuration = 1.0
private let kNodeNameTransitionShaderNode = "kNodeNameTransitionShaderNode"
private let kNodeNameFadeColourOverlay = "kNodeNameFadeColourOverlay"
private var presentationStartTime: CFTimeInterval = -1
private var shaderChoice = -1

extension SKScene {
    private var transitionShader: SKShader? {
        get {
            if let shaderContainerNode = self.childNodeWithName(kNodeNameTransitionShaderNode) as? SKSpriteNode {
                return shaderContainerNode.shader
            }
            return nil
        }
    }
    private func createShader(shaderName: String, transitionDuration: NSTimeInterval) -> SKShader {
        var shader = SKShader(fileNamed:shaderName)
        var u_size = SKUniform(name: "u_size", floatVector3: GLKVector3Make(Float(UIScreen.mainScreen().scale * size.width), Float(UIScreen.mainScreen().scale * size.height), Float(0)))
        var u_fill_colour = SKUniform(name: "u_fill_colour", floatVector4: GLKVector4Make(131.0 / 255.0, 149.0 / 255.0, 255.0 / 255.0, 1.0))
        var u_border_colour = SKUniform(name: "u_border_colour", floatVector4: GLKVector4Make(104.0 / 255.0, 119.0 / 255.0, 204.0 / 255.0, 1.0))
        var u_total_animation_duration = SKUniform(name: "u_total_animation_duration", float: Float(transitionDuration))
        var u_elapsed_time = SKUniform(name: "u_elapsed_time", float: Float(0))
        shader.uniforms = [u_size, u_fill_colour, u_border_colour, u_total_animation_duration, u_elapsed_time]
        return shader
    }
    func presentScene(scene: SKScene?, shaderName: String, transitionDuration: NSTimeInterval) {
        // Create shader and add it to the scene
        var shaderContainer = SKSpriteNode(imageNamed: "dummy")
        shaderContainer.name = kNodeNameTransitionShaderNode
        shaderContainer.zPosition = 9999 // something arbitrarily large to ensure it's in the foreground
        shaderContainer.position = CGPointMake(size.width / 2, size.height / 2)
        shaderContainer.size = CGSizeMake(size.width, size.height)
        shaderContainer.shader = createShader(shaderName, transitionDuration:transitionDuration)
        self.addChild(shaderContainer)
        // remove the shader from the scene after its animation has completed.
        let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(transitionDuration * Double(NSEC_PER_SEC)))
        dispatch_after(delayTime, dispatch_get_main_queue(), { () -> Void in
            var fadeOverlay = SKShapeNode(rect: CGRectMake(0, 0, self.size.width, self.size.height))
            fadeOverlay.name = kNodeNameFadeColourOverlay
            fadeOverlay.fillColor = SKColor(red: 131.0 / 255.0, green: 149.0 / 255.0, blue: 255.0 / 255.0, alpha: 1.0)
            fadeOverlay.zPosition = shaderContainer.zPosition
            scene!.addChild(fadeOverlay)
            self.view!.presentScene(scene)
        })
        // Reset the time presentScene was called so that the elapsed time from now can
        // be calculated in updateShaderTransitions(currentTime:)
        presentationStartTime = -1
    }
    func updateShaderTransition(currentTime: CFTimeInterval) {
        if let shader = self.transitionShader {
            let elapsedTime = shader.uniformNamed("u_elapsed_time")!
            if (presentationStartTime < 0) {
                presentationStartTime = currentTime
            }
            elapsedTime.floatValue = Float(currentTime - presentationStartTime)
        }
    }
    // this function is called by the scene being transitioned to when it's ready to have the view faded in to the scene i.e. loading is complete, etc.
    func completeShaderTransition() {
        if let fadeOverlay = self.childNodeWithName(kNodeNameFadeColourOverlay) {
            fadeOverlay.runAction(SKAction.sequence([SKAction.fadeAlphaTo(0, duration: 0.3), SKAction.removeFromParent()]))
        }
    }  
}

答案 1 :(得分:0)

我终于完成了它!我的问题是我在更新方法中有我的代码,并没有检查它是否已经添加。我在更新循环的每次迭代中都添加了多个视图,并且不透明度为.5,这使得它看起来像黑色。