swift – 在特定场景中构建SpriteKit / GameKit排行榜

前端之家收集整理的这篇文章主要介绍了swift – 在特定场景中构建SpriteKit / GameKit排行榜前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我对 Swift很陌生,而且我在游戏中实现排行榜时遇到了一些麻烦.我刚看了一个教程:’游戏中心排行榜! (Xcode中的Swift 2)’其中GameCenter信息都通过应用程序的一个视图.在我的游戏中,我希望用户能够玩游戏,然后只有当他们使用特定的SKScene时,他们才能访问GameCenter.

因此,例如,在GameOverScene上,他们将进行用户身份验证,并且还可以上传他们的高分.我想我也错过了GameViewController(所有教程逻辑所在的位置)和我制作的众多场景之间的一些差异.

这是我的代码,我尝试在GameOverScene上使用GKGameCenterControllerDelegate并创建各种功能以到达GameCenter.当用户在视图中点击某个标签时进行调用:(这显然不起作用,因为我正在尝试访问这样的行上的场景:self.presentViewController(view!,animated:true,completion:nil)

class GameOverScene: SKScene,GKGameCenterControllerDelegate  {

    init(size: CGSize,the@R_301_182@:Int) {
        @R_301_182@ = the@R_301_182@
        super.init(size: size)
    }
    ...

    override func didMoveToView(view: SKView) {

        authPlayer()

        leaderboardLabel.text = "Tap for Leaderboard"
        leaderboardLabel.fontSize = 12
        leaderboardLabel.fontColor = SKColor.redColor()
        leaderboardLabel.position = CGPoint(x: size.width*0.85,y: size.height*0.1)
        addChild(leaderboardLabel)

        ...

    override func touchesBegan(touches: Set<UITouch>,withEvent event: UIEvent?) {

        for touch : AnyObject in touches {
            let location = touch.locationInNode(self)

            if(CGRectContainsPoint(leaderBoardLabel.frame,location)){
                saveHigh@R_301_182@(@R_301_182@)
                showLeaderBoard()
            }
        }
    }


    func authPlayer(){

        //Create a play
        let localPlayer = GKLocalPlayer.localPlayer()

        //See if signed in or not
        localPlayer.authenticateHandler = {
            //A view controller and an error handler
            (view,error) in

            //If there is a view to work with
            if view != nil {
                self.presentViewController(view!,animated:true,completion: nil) //we dont want a completion handler
            }

            else{
                print(GKLocalPlayer.localPlayer().authenticated)
            }
        }
    }


    //Call this when ur high@R_301_182@ should be saved
    func saveHigh@R_301_182@(number:Int){

        if(GKLocalPlayer.localPlayer().authenticated){

            let @R_301_182@Reporter = GK@R_301_182@(leaderboardIdentifier: "@R_301_182@Board")
            @R_301_182@Reporter.value = Int64(number)

            let @R_301_182@Array: [GK@R_301_182@] = [@R_301_182@Reporter]

            GK@R_301_182@.report@R_301_182@s(@R_301_182@Array,withCompletionHandler: nil)

        }

    }


    func showLeaderBoard(){

        let viewController = self.view.window?.rootViewController
        let gcvc = GKGameCenterViewController()

        gcvc.gameCenterDelegate = self

        viewController?.presentViewController(gcvc,animated: true,completion: nil)


    }


    func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController) {
        gameCenterViewController.dismissViewControllerAnimated(true,completion: nil)
    }

关于如何进行此操作的任何建议都会很棒,我认为我可能会让整个场景/视图控制器混乱并导致问题.谢谢!

这个答案部分地延续了我们在评论中所停留的位置,因为你没有发布你的整个代码,我无法确切地知道你的挂断在哪里,但这是我和一个单独的指南放在一起的(这是一个稍微的您发布的不同版本的代码):

大部分代码的作者:

https://www.reddit.com/r/swift/comments/3q5owv/how_to_add_a_leaderboard_in_spritekit_and_swift_20/

GameViewController.swift:

import UIKit
import SpriteKit
import GameKit

class GameViewController: UIViewController {

    func authenticateLocalPlayer() {
        let localPlayer = GKLocalPlayer.localPlayer()
        localPlayer.authenticateHandler = {(viewController,error) -> Void in

            if (viewController != nil) {
                self.presentViewController(viewController!,completion: nil)
            }
            else {
                print((GKLocalPlayer.localPlayer().authenticated))
            }
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        /////authentication//////
        authenticateLocalPlayer()

        //... The rest of the default code
    }

    //... The rest of the default code
}

GameScene.swift(或任何你想使用GC的场景):

import SpriteKit
import GameKit
import UIKit

// Global scope (I generally put these in a new file called Global.swift)
var @R_301_182@ = 0


//sends the highest @R_301_182@ to leaderboard
func saveHigh@R_301_182@(game@R_301_182@: Int) {
    print ("You have a high @R_301_182@!")
    print("\n Attempting to authenticating with GC...")

    if GKLocalPlayer.localPlayer().authenticated {
        print("\n Success! Sending high@R_301_182@ of \(@R_301_182@) to leaderboard")

        //---------PUT YOUR ID HERE:
        //                          |
        //                          |
        //                          V
        let my_leaderboard_id = "YOUR_LEADERBOARD_ID"
        let @R_301_182@Reporter = GK@R_301_182@(leaderboardIdentifier: my_leaderboard_id)

        @R_301_182@Reporter.value = Int64(game@R_301_182@)
        let @R_301_182@Array: [GK@R_301_182@] = [@R_301_182@Reporter]

        GK@R_301_182@.report@R_301_182@s(@R_301_182@Array,withCompletionHandler: {error -> Void in
            if error != nil {
                print("An error has occured:")
                print("\n \(error) \n")
            }
        })
    }
}

// Your scene:
class GameScene: SKScene,GKGameCenterControllerDelegate {

    // Local scope variables (for this scene):

    // Declare a new node,then initialize it
    let call_gc_node   = SKLabelNode(fontNamed:"Chalkduster")
    let add_@R_301_182@_node = SKLabelNode(fontNamed: "Helvetica")


    override func didMoveToView(view: SKView) {

        // Give our GameCenter node some stuff
        initGCNode: do {

            // Set the name of the node (we will reference this later)
            call_gc_node.name = "callGC"

            // Default inits
            call_gc_node.text = "Send your High@R_301_182@ of \(@R_301_182@) into Game Center"
            call_gc_node.fontSize = 25
            call_gc_node.position = CGPoint(
                x:CGRectGetMidX(self.frame),y:CGRectGetMidY(self.frame))

            // Self here is the instance (object) of our class,GameScene
            // This adds it to our view
            self.addChild(call_gc_node)
        }

        // Give our Add label some stuff
        initADDLabel: do {

            // Set the name of the node (we will reference this later)
            add_@R_301_182@_node.name = "addGC"

            // Basic inits
            add_@R_301_182@_node.text = "ADD TO @R_301_182@!"
            add_@R_301_182@_node.fontSize = 25
            add_@R_301_182@_node.position = call_gc_node.position

            // Align our label some
            add_@R_301_182@_node.runAction(SKAction.moveByX(0,y: 50,duration: 0.01))

            // Add it to the view
            self.addChild(add_@R_301_182@_node)
        }

    }


    override func touchesBegan(touches: Set<UITouch>,withEvent event: UIEvent?) {
        for touch in touches {

            // Get the position of our click
            let TPOINT = touch.locationInNode(self)

            // Get the name (string) of the node that was touched
            let
                node_that_was_touched: String?
                                                = nodeAtPoint(TPOINT).name


            // Prepare for switch statement,when we unwrap the optional,we don't want nil
            guard (node_that_was_touched != nil)
                else { print("-> before switch: found nil--not entering Switch");
                    return
            }


            // Find out which node we clicked based on node.name?,then do stuff:
            switch node_that_was_touched! {

                case "callGC":
                    // We clicked the GC label:

                    GameOver: do {

                        print("GAME OVER!")

                        // If we have a high-@R_301_182@,send it to leaderboard:
                        overrideHighest@R_301_182@(@R_301_182@)

                        // Reset our @R_301_182@ (for the next playthrough)
                        @R_301_182@ = 0

                        // Show us our stuff!
                        showLeader()
                    }

                case "addGC":
                    // we clicked the Add label:

                    // Update our *current @R_301_182@*
                    @R_301_182@ += 1


                default: print("no matches found")
            }

        }

    }


    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
        call_gc_node.text = "Send your High@R_301_182@ of \(@R_301_182@) into Game Center"

    }


    // Gamecenter
    func gameCenterViewControllerDidFinish(gameCenterViewController: GKGameCenterViewController) {
        gameCenterViewController.dismissViewControllerAnimated(true,completion: nil)
    }

    //shows leaderboard screen
    func showLeader() {
        let viewControllerVar = self.view?.window?.rootViewController
        let gKGCViewController = GKGameCenterViewController()
        gKGCViewController.gameCenterDelegate = self
        viewControllerVar?.presentViewController(gKGCViewController,completion: nil)
    }

    // Your "game over" function call
    func overrideHighest@R_301_182@(game@R_301_182@: Int) {
        NSUserDefaults.standardUserDefaults().integerForKey("high@R_301_182@")
        if game@R_301_182@ > NSUserDefaults.standardUserDefaults().integerForKey("high@R_301_182@")
        {
            NSUserDefaults.standardUserDefaults().setInteger(game@R_301_182@,forKey: "high@R_301_182@")
            NSUserDefaults.standardUserDefaults().synchronize()

            saveHigh@R_301_182@(game@R_301_182@)
        }
    }
}

要特别注意

29: let my_leaderboard_id = "YOUR_LEADERBOARD_ID"

我在那里放了一些愚蠢的ASCII艺术,以确保你不会错过它.您必须从GameCenter设置中输入您的实际排行榜ID.

您还必须添加GameCenter库,然后执行iTunes连接以在弹出窗口中实际查看您的高分.

我认为你最初的问题是没有理解SpriteKit甚至iOS视图如何工作的后端(这完全没问题,因为Apple让人很容易进入并且很容易).但是,如您所见,遵循指南/教程可能很困难,因为您的实施会有所不同.

以下是一些很好的信息:

SK中每个帧发生的情况图:

所以你看,SKScene是一个包含节点和动作等所有有趣内容的类,并且是一切(对你很重要)发生的地方.您可以通过编辑器生成这些场景,但是您可能需要创建一个新的.swift文件(因为每个场景都有自己的逻辑).

编辑器只是初始化一堆东西的“捷径”,老实说,你可以用很少的代码制作完整的游戏(但你很快发现你想要更多)

所以在这段代码中,你声明了GameScene或PauseScreen(它们基本上只是类声明,继承自SKScene),你很快就会发现这一行谈论ISNT场景:

override func didMoveToView(view: SKView)
.. it’s calling a SKView… what is that,and where did it come from?

(Read about SKView here,and look at its inheritance):

07002

我们在GameViewController文件中找到这个SKView声明(这只是一个类),注意它与普通的iOS应用程序大致相同,因为它继承了UIViewController:

override func viewDidLoad() {
    super.viewDidLoad()
    if let scene = GameScene(fileNamed:"GameScene") {
        // Configure the view.
        let skView = self.view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true

        /* Sprite Kit applies additional optimizations to improve               rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .AspectFill

        skView.presentScene(scene)
    }

同样,该方法在GameViewController.swift中声明,基本上就是这样:
class GameViewController:UIViewController

那么所有这些与iOS应用和SpriteKit有什么关系呢?好吧,他们都被捣碎在彼此之上:

IOS app解剖:

基本上,从右到左,你有一个Window,它是(如果错误的话,我是错误的)AppDelegate,然后是ViewController,然后是你的View,里面有所有很酷的东西(Storyboards就在View里面,就像SKScenes位于View ….标签,节点或按钮内,都位于各自的类中((视图)))

这都是继承的三明治.

查看Apple网站了解更多信息.

https://developer.apple.com/library/safari/documentation/UserExperience/Conceptual/MobileHIG/ContentViews.html#//apple_ref/doc/uid/TP40006556-CH13-SW1

https://developer.apple.com/spritekit/

https://developer.apple.com/library/ios/documentation/SpriteKit/Reference/SpriteKitFramework_Ref/

https://developer.apple.com/library/safari/documentation/UserExperience/Conceptual/MobileHIG/Anatomy.html

基本上,一切都是继承自类继承的类的类,依此类推……它可能会变得混乱.你也可以通过CMD点击它们在Xcode中看到这些遗产,这会将你跳转到源文件.

Goodluck与你在SpriteKit的学习和冒险:)

猜你在找的Swift相关文章