如何使 SKScene 的背景透明以便我可以在 ZStack 中分层?
How can I make background of an SKScene transparent so I can layer in a 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 的背景透明?
有关实际解决方案,请参阅我在此线程上的最终答案。一旦我想出自定义 SpriteViews,我决定删除我最初包含的解决方法。
终于用自定义SpriteView解决了。下面的代码使 spritekit 视图实际上具有透明背景。问题似乎是 swiftUI 的声明性意味着您总是在使用他们的 SpriteView(具有黑色背景)。 SKScene 确实是唯一传递给 SwiftUI 的东西。
我认为这可以解释为什么视图设置不像 UIKit 那样有效。
解决方案是在 body 结构之外创建一个新的 SpriteView,然后在 body 结构中使用它来代替标准 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 修改。
我正在尝试使用 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 的背景透明?
有关实际解决方案,请参阅我在此线程上的最终答案。一旦我想出自定义 SpriteViews,我决定删除我最初包含的解决方法。
终于用自定义SpriteView解决了。下面的代码使 spritekit 视图实际上具有透明背景。问题似乎是 swiftUI 的声明性意味着您总是在使用他们的 SpriteView(具有黑色背景)。 SKScene 确实是唯一传递给 SwiftUI 的东西。
我认为这可以解释为什么视图设置不像 UIKit 那样有效。
解决方案是在 body 结构之外创建一个新的 SpriteView,然后在 body 结构中使用它来代替标准 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 修改。