xcode 将变量从UIViewController传递到SK场景

x6yk4ghg  于 2023-01-10  发布在  其他
关注(0)|答案(3)|浏览(153)

我正在XCode 7中使用Swift 2制作一个a游戏。我有一个变量,希望从开始屏幕传递(它是一个UIViewController)添加到游戏场景(这是一个SKScene)。我想让玩家在一个UIView中选择一个角色,然后在SKScene中玩它。我还想让SKScene中的分数显示在游戏结束屏幕上,这是一个UIView。我'我看过在两个UIViewController之间和两个SKScene之间传递数据的教程,但是没有一个适合这种情况。
如何将变量从UIViewController传递到SKScene(反之亦然)?

0dxa2lsx

0dxa2lsx1#

昨天我又碰到了同样的问题。
Swift 5.2,xcode 12,目标iOS 14。上下搜索。最终找到了SKScene的userData属性。
注:该应用程序基于SwiftUI,SKScene位于UIViewRepresentable内:

struct SpriteKitContainer: UIViewRepresentable {
    typealias UIViewType = SKView
    
    var skScene: SKScene!
    @Binding var timerData :  ModelProgressTimer

我并不是要将绑定传递到视图中--这包含了许多我希望场景可以使用的数据项。
我在两个地方放置了代码来填充skScene.userData:

func makeUIView(context: Context) -> SKView {
    self.skScene.scaleMode = .resizeFill
    self.skScene.backgroundColor = .green
    debugPrint("setting user data")

    self.skScene.userData = [:]
    self.skScene.userData!["color"] = UIColor(timerData.flatColorTwo!)
    self.skScene.userData!["running"] = timerData.isRunning
    self.skScene.userData!["percent"] = timerData.percentComplete

    let view = SKView(frame: .zero)
    view.preferredFramesPerSecond = 60
   // view.showsFPS = true
   // view.showsNodeCount = true
    view.backgroundColor = .clear
    view.allowsTransparency = true
    
    return view
}

func updateUIView(_ view: SKView, context: Context) {
    self.skScene.userData = [:]
    
    self.skScene.userData!["running"] = timerData.isRunning
    self.skScene.userData!["color"] = UIColor(timerData.flatColorTwo!)
    self.skScene.userData!["percent"] = timerData.percentComplete
    view.presentScene(context.coordinator.scene)
}

然后,在skScene对象中,我能够检索userData值:

var item: SKShapeNode! = nil

   override func sceneDidLoad() {
       let scaleUp = SKAction.scale(by: 2.0, duration: 1.0)
       let scaleDown = SKAction.scale(by: 0.5, duration: 1.0)
        
       scaleUp.timingMode = .easeInEaseOut
       scaleDown.timingMode = .easeInEaseOut
       let sequence = SKAction.sequence([scaleUp,scaleDown])

       actionRepeat = SKAction.repeatForever(sequence)

       item = SKShapeNode(circleOfRadius: radius)
       addChild(item)
    }

override func didChangeSize(_ oldSize: CGSize) {

   item.fillColor = self.userData!["color"] as! UIColor
   item.strokeColor = .clear
                
   let meRunning = self.userData!["running"] as! Bool
                
   if meRunning {
         item.run(actionRepeat)        
   } else {
        item.removeAllActions()  
   }
}

如果在userdata中设置了“running”布尔值(Bool值),则会绘制一个“脉动”的圆。

kyks70gy

kyks70gy2#

如果你还没有找到答案,我确实找到了一种方法,我正在做一些非常相似的事情。
在我的例子中,我有一个UIView,它作为一个暂停菜单从我的场景中调用。我使类和变量名更加模糊,以便它们也能应用于您的情况。

class MyView: UIView {
    var scene: MyScene!
    var button: UIButton!
    init(frame: CGRect, scene: MyScene){
        super.init(frame: frame)
        self.scene = scene
        //initialize the button
        button.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "buttonTapped"))
    }

    func buttonTapped(){
        self.removeFromSuperview() // this removes my menu from the scene
        scene.doTheThing() // this calls the method on my scene
}

下面是我的场景的相关部分。

class MyScene: SKScene {

    func doTheThing(){
         //this is a function on the scene. You can pass any variable you want through the function. 
    }
}

在您的情况下,听起来第一个屏幕是UIView,第二个屏幕是SKScene。
你可以先制作SKScene,暂停它,然后在场景前面添加UIView。一旦角色被选中,你就可以删除UIView并将角色添加到场景中。
我希望这能回答你的问题。如果它没让我知道。

dgenwo3n

dgenwo3n3#

从关卡选择场景:

let scene = GameScene(fileNamed:"GameScene")
scene?.userData = [:]
scene?.userData!["level"] = 21
self.view?.presentScene(scene!)

在游戏场景中:

let level = self.userData!["level"] as! Int

相关问题