微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使SKScene的背景透明,以便可以在ZStack中分层?

如何解决如何使SKScene的背景透明,以便可以在ZStack中分层?

我正在尝试使用SwiftUI和SpriteKit制作游戏。而且,我希望能够在ZStack中布局游戏,并使游戏分层于背景图像之上。为此,我需要使SKScene的背景透明。但是当我这样做时,添加到SKScene的节点将不再显示

这是我正在使用的编码:

import SwiftUI
import SpriteKit
import GameplayKit

class GameScene: SKScene {
  
  override func didMove(to view: SKView) {
    
    view.allowsTransparency = true
    self.backgroundColor = .clear
    view.alpha = 0.0
    view.isOpaque = true
    view.backgroundColor = SKColor.clear.withAlphaComponent(0.0)

    
    if let particles = SKEmitterNode(fileNamed: "Mud") {
      particles.position.x = 512
      addChild(particles)
    }
    
  }
  
}


struct ContentView: View {
  
  var scene: SKScene {
    
    let scene = GameScene()
    scene.size = CGSize(width: 300,height: 400)
    scene.scaleMode = .fill
    
    return scene
  }
  
  var body: some View {
    ZStack {
      Image("road")
        .resizable()
        .aspectRatio(contentMode: /*@START_MENU_TOKEN@*/.fill/*@END_MENU_TOKEN@*/)
        .ignoresSafeArea()
      SpriteView(scene: scene)
        .ignoresSafeArea()
        .frame(minWidth: 0,maxWidth: .infinity,minHeight: 0,maxHeight: .infinity)
    }
  }
}

SKScene的背景是透明的,我可以在ZStack中看到其下方分层的图像。但是,场景中的其他所有内容也是透明的,因此我根本看不到发射器效果

如何仅使SKScene的背景透明?

解决方法

最后使用自定义SpriteView解决了。下面的代码使spritekit视图实际上具有透明的背景。问题似乎是swiftUI的声明性,意味着您始终使用其SpriteView(背景为黑色)。实际上,SKScene是唯一传递到SwiftUI的东西。

我认为这可以解释为什么视图设置不像UIKit那样起作用。

解决方案是在主体结构外部创建一个新的SpriteView,然后在主体结构中使用它代替标准SpriteView(scene:scene)。这允许将init()中的SpriteView.Options设置为最终在所呈现的SwiftUI的某些视图中设置.allowsTransparency。

请参见下面的代码:

//  Created by Larry Mcdowell on 9/25/20.
//

import SwiftUI
import SpriteKit
import GameplayKit

class GameScene: SKScene {
    

   override func didMove(to view: SKView) {
     
    
        // 1
        self.backgroundColor = .clear
        
        //2
        view.allowsTransparency = true
        
        
        if let particles = SKEmitterNode(fileNamed: "Mud"){
            particles.position.x = 140
            particles.position.y = 200
       
            addChild(particles)
        }
    }
    

}



struct ContentView: View {
    
    var mySpriteView:SpriteView
  
    init(){
        
        mySpriteView = SpriteView(scene: scene,transition: nil,isPaused: false,preferredFramesPerSecond: 60,options: [.allowsTransparency],shouldRender: {_ in return true})
        
    }
    let scene:GameScene = {
        let scene = GameScene()
        scene.size = CGSize(width: 300,height: 400)
        scene.scaleMode = .fill
        
        return scene
    }()
    

    var body: some View {
        
        ZStack {
            
              Image("road")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .ignoresSafeArea()
   
            mySpriteView
              .ignoresSafeArea()
                .frame(minWidth: 0,maxWidth: .infinity,minHeight: 0,maxHeight: .infinity)
         
        }
    }
    
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

这是一个下雨天的有趣项目!

,

您需要做的就是将场景背景设置为.clear,并将选项作为参数传递给SpriteView以提高透明度。所以对于您的情况,应该是

SpriteView(scene: scene,options: [.allowsTransparency])

所有的SKView修改都可以删除。

,

删除view.alpha = 0.0。它使整个GameScene,视图和所有内容透明化。

根据documentation,您所需要做的就是:

view.backgroundColor = .clear
view.allowsTransparency = true
backgroundColor = .clear
,

有关实际解决方案,请参见我在此线程上的最终答案。一旦确定了自定义SpriteViews,我决定删除最初包含的解决方法。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。