【问题标题】:Swift/SpriteKit: Attempting to reach a function/method in a class from another class not workingSwift/SpriteKit:试图从另一个类不工作的类中访问一个函数/方法
【发布时间】:2018-02-16 12:26:44
【问题描述】:

我的 ScoreSystem 类中有一个名为 addScore 的函数。该函数为游戏增加 1 分,将 SKLabelNode 更新为当前分数,然后每 25 分调用函数 startNewLevel。

func addScore(scene: SKScene) {
    gameScore += 1
    scoreLabel.text = "\(gameScore)"

    if CGFloat(gameScore).truncatingRemainder(dividingBy: 25) == 0 {
        NotificationCenter.default.post(name: Notification.Name.init("start_new_level"), object: nil)
        GameScreen().displayLevel(scene: scene)
    }
}

每次发射的鱼雷击中敌人时都会调用该函数。我现在想添加一个必须避免流星(SKSpriteNode)的新关卡。我按顺序有几个 SKAction 来完成此操作。本质上,SKSpriteNode 从屏幕顶部移动,到达屏幕下方并被删除。如果流星到达屏幕底部意味着它已被玩家避开。

我正在尝试调用函数 addScore 但它没有更新。

函数如下:

let scoreSystem = ScoreSystem()

func spawnMeteor() {

    let randomXStart = CGFloat.random(min: gameArea.minX, max: gameArea.maxX)

    let startPoint = CGPoint(x: randomXStart, y: scene.size.height * 1.2)
    let endPoint = CGPoint(x: randomXStart, y: -scene.size.height * 0.2)


    let meteor = SKSpriteNode(imageNamed: "meteor")
    meteor.name = "Meteor"
    meteor.zPosition = 2
    meteor.position = startPoint

    let moveMeteor = SKAction.move(to: endPoint, duration: 3)
    let deleteEnemy = SKAction.removeFromParent()

    let score = SKAction.run(addToScore)

    let meteorSequence = SKAction.sequence([
        moveMeteor,
        score,
        deleteEnemy])

    scene.addChild(meteor)
    meteor.run(meteorSequence)

}

我试过这样的函数 addToScore:

func addToScore() {
    scoreSystem.addScore(scene: scene!)
}

也试过了

func addToScore() {
    NotificationCenter.default.post(name: Notification.Name.init("add_to_score"), object: nil)
}

在尝试第二种选择时,我将以下内容添加到 GameScene

override func sceneDidLoad() {
    super.sceneDidLoad()
    NotificationCenter.default.addObserver(forName: Notification.Name.init("add_to_score"), object: nil, queue: OperationQueue.main) { [weak self] (notification) in
        self?.scoreSystem.addScore(scene: self!)
    }

}

我从 spawnMeteor() 函数中删除了几行代码,以免不必要的代码行阻塞空间。我还没有弄清楚如何使用 SKAction.run() 调用该函数。有人能指出我正确的方向吗?

【问题讨论】:

  • addToScore中下断点,是否调用?
  • 好电话。不,不是。为什么?
  • 我没有调用中间函数来到达 addScore(),而是从 SKAction.run() 调用函数,如下所示: let score = SKAction.run(scoreSystem.addScore) 但我得到以下错误:无法将类型“(SKScene)->()”的值转换为预期的参数类型“()-> Void”。我已经搜索了如何解决这个问题的答案,但不太明白开始的含义。

标签: swift sprite-kit skaction


【解决方案1】:

您正在向您的函数传递大量信息,可能太多了。

我建议您实施协议或通知来处理您的信息,我个人更喜欢协议,因此我的示例将是协议。

我正在对您的代码做出一些假设,因为并非所有代码都在您的问题中呈现...

protocol ScoreSystemDelegate: class {
    func displayLevel()
}

class ScoreSystem: SKNode {

    weak var scoreSystemDelegate: ScoreSystemDelegate! 

    //your init func and any other funcs in this class (unknown)

    func addScore(scene: SKScene) {
        gameScore += 1
        scoreLabel.text = "\(gameScore)"

        if CGFloat(gameScore).truncatingRemainder(dividingBy: 25) == 0 {
            NotificationCenter.default.post(name: Notification.Name.init("start_new_level"), object: nil)
            //GameScreen().displayLevel(scene: scene)
            self.scoreSystemDelegate.displayLevel()
        }
   }
}

在创建 scoreSystem 的类中(假设为 GameScene)...

class GameScene: SKScene, ScoreSystemDelegate {

    let scoreSystem = ScoreSystem()
    //assign GameScene as the delegate of ScoreSystem that way the 2 can communicate
    scoreSystem.scoreSystemDelegate = self

    func displayLevel() {
        //do whatever you do when you display the level
    }
}

现在你的 spawn meteor 函数应该像你编码的那样工作,因为 addScore 不再需要一个场景属性,这个方法的好处是你可以让任何对象成为 ScoreSystem 的委托,它不必是一个场景。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 2017-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多