【问题标题】:Dimming SKScene by adding SKScene/SKView or UIView on top not working通过在顶部添加 SKScene/SKView 或 UIView 使 SKScene 变暗不起作用
【发布时间】:2016-07-26 23:58:49
【问题描述】:

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

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

我有一个扩展 SKScene 的游戏场景,我在其中将所有 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,该 skview 的透明度设置为 true,颜色设置为清除颜色。这样我只会得到一个灰屏。我已经有一段时间了,似乎真的无法弄清楚为什么这不起作用。任何帮助将不胜感激。

更新 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];

【问题讨论】:

    标签: ios objective-c sprite-kit uikit


    【解决方案1】:

    根据SKScene Class Reference的概述部分:

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

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

    如果你想“重叠”两个场景,你总是必须从使用过渡切换。

    另一种方法是使用名为 SpriteKitShaderTransitionExample 的着色器自定义过渡场景的 GitHub 项目

    从下面的来源可以看出,它扩展了 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()]))
            }
        }  
    }
    

    【讨论】:

    • 我不一定要覆盖两个场景,我真正想要的是用另一个视图覆盖一个视图,其中顶部的视图是黑色,不透明度为 0.5-.6。这是为了在用户输掉游戏时使背景变暗。使用上面的代码我无法实现这一点,因为覆盖的场景总是不透明的。
    • 我不明白你的意思,你是什么意思?你必须区分 UIKit 和 Sprite-kit,那么你到底得到了什么?
    • 对不起,我试图用不同的 SKView 覆盖我的 SKScene,但这似乎不起作用,它不透明。我也尝试用 UIView 覆盖我的 SKScene ,但这也不透明。我想要的是让我的 SKScene 节点通过另一个视图或场景可见,我真的不在乎哪个。我正在寻找的效果是原始场景的暗淡效果。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2014-09-09
      • 1970-01-01
      • 2014-08-21
      • 2015-04-05
      • 1970-01-01
      • 2016-09-10
      • 2014-10-25
      • 1970-01-01
      • 2021-01-04
      相关资源
      最近更新 更多