如何在 Swift 中使用 Firestore 为 2 人多人游戏构建数据?

Posted

技术标签:

【中文标题】如何在 Swift 中使用 Firestore 为 2 人多人游戏构建数据?【英文标题】:How to structure the data for a 2 person muliplayer game using Firestore and Swift? 【发布时间】:2018-03-22 13:55:00 【问题描述】:

首先,我对 Firestore 及其功能非常陌生,所以如果其中一些可能对其他人来说很明显,我深表歉意。这些事情还没有在我的脑海中登记。

我正在尝试使用 Swift 语言和 Firestore 作为后端创建一个 2 人多人游戏。但是,我不确定如何创建在给定时间仅允许两个玩家进入单个游戏的功能。我将如何限制每场比赛只允许两名球员参加一场比赛?这是我需要在 Firestore 的安全和规则部分中设置的吗?或者我是否需要在我的数据建模方式中创建此功能?

我目前对数据建模的设置包括创建一个“游戏”集合,其中每个“游戏”都有两个文档分别用于“player1”和“player2”。然后,在每个播放器/文档中,我存储每个播放器功能的值。但是通过这种方法,我仍然没有解决在一个“游戏”/集合中只允许两个玩家的问题。如何防止第三名玩家进入游戏?或者当多人同时进入游戏时我将如何处理这种情况?

感谢您的任何建议。

【问题讨论】:

【参考方案1】:

您可以使用 Cloud Functions 将玩家分配给游戏,管理游戏何时满员,然后开始游戏。看看这篇关于 Medium 的文章,Building a multi-player board game with Firebase Firestore & Functions

【讨论】:

非常感谢,这正是我所需要的。这些云函数和触发器解决了我的所有问题,本文为我提供了一种在 Firestore 中构建数据的更合乎逻辑的方法。 不客气。您在问题中表示您是新手并寻求帮助,但人们对您的问题投了反对票。我真的不明白为什么。这应该是一个开发者互相帮助的社区【参考方案2】:

这是我最终在 Swift 中使用 Firestore 创建的用于创建 2 人多人游戏的代码。

import UIKit
import Firebase

class WaitForOpponentViewController: UIViewController

    @IBOutlet weak var activityIndicator: UIActivityIndicatorView!

    var battleRoomDocumentReference : DocumentReference!
    var battleRoomListenerRegistration : ListenerRegistration!

    override func viewDidLoad()
        super.viewDidLoad()

         activityIndicator.hidesWhenStopped = true
         activityIndicator.startAnimating()

        Firestore.firestore().collection(BATTLEROOMS_Collection)
            .whereField(BATTLEROOMFULL_FIELD, isEqualTo: false)
            .whereField(NUMOFPLAYERS_FIELD, isLessThan: 2)
            .limit(to: 1)
            .getDocuments  (snapShot, error) in

            if let error = error
            
                print("There was a error while fetching the documents: \(error)")
            
            else
            
                guard let snap = snapShot else return
                if(snap.documents.count > 0)
                
                    //Update the current battle room
                    for document in snap.documents
                    
                        Firestore.firestore().collection(BATTLEROOMS_Collection)
                            .document(document.documentID)
                            .setData(
                                [
                                    BATTLEROOMFULL_FIELD : true,
                                    NUMOFPLAYERS_FIELD : 2, //Note: Player1Id is not changed because there is already a player1Id when this document is updated
                                    PLAYER2ID_FIELD : Auth.auth().currentUser?.uid ?? "AnonymousNum2"
                                ], options: SetOptions.merge(), completion:  (error) in

                                    if let error = error
                                    
                                        print("There was an error while adding the second player to the battle room document : \(error)")
                                    

                                    self.addBattleRoomListener(battleRoomDocumentId: document.documentID)
                          )
                       
                   
                   else
                   
                      //Create a new battle room
                      self.battleRoomDocumentReference =  Firestore.firestore().collection(BATTLEROOMS_Collection)
                           .addDocument(data:
                            [
                                BATTLEROOMFULL_FIELD: false,
                                NUMOFPLAYERS_FIELD : 1,
                                PLAYER1ID_FIELD : Auth.auth().currentUser?.uid ?? "AnonymousNum1",
                                PLAYER2ID_FIELD : ""
                            ], completion:  (error) in

                                if let error = error
                                
                                    print("Error while adding a new battle room/player 1 to the battle room document : \(error)")
                                
                    )
                    self.addBattleRoomListener(battleRoomDocumentId: self.battleRoomDocumentReference.documentID)
                
            
        
     

    override func viewWillDisappear(_ animated: Bool) 

        //Remove Battle Room Listener
        battleRoomListenerRegistration.remove()

        activityIndicator.stopAnimating()
    

    func addBattleRoomListener(battleRoomDocumentId : String)
    
        battleRoomListenerRegistration = Firestore.firestore().collection(BATTLEROOMS_Collection)
            .document(battleRoomDocumentId)
            .addSnapshotListener  (documentSnapshot, error) in

                guard let snapshot = documentSnapshot else  return 
                guard let documentData = snapshot.data() else  return 
                let battleRoomFullData = documentData[BATTLEROOMFULL_FIELD] as? Bool ?? false
                let numOfPlayerData = documentData[NUMOFPLAYERS_FIELD] as? Int ?? 0

                if(battleRoomFullData == true && numOfPlayerData == 2)
                
                    print("Two Players in the Game, HURRAY. Segue to GAME VIEW CONTROLLER")
                
                else
                
                    return
                
        
    

    @IBAction func cancelBattle(_ sender: UIButton) 

        //NOTE: Canceling is only allowed for the first user thats creates the Battle Room, once the Second Person enters the Battle Room the system will automatically segue to the Game View Controller sending both players into the game VC

        Firestore.firestore().collection(BATTLEROOMS_Collection)
            .document(battleRoomDocumentReference.documentID)
            .delete  (error) in
                if let error = error
                
                    print("There was an error while trying to delete a document: \(error)")
                
        

        activityIndicator.stopAnimating()

        self.dismiss(animated: true, completion: nil)
    

【讨论】:

以上是关于如何在 Swift 中使用 Firestore 为 2 人多人游戏构建数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用swift在firestore文档中的字段中生成空值?

如何使用Firestore Geopoint为社交媒体应用程序(swift Xcode)获取基于位置的帖子

如何在 Swift 中重构重复的 Firestore 文档 ID?

如何在 Swift 的 Firebase Firestore 中获取当前文档 ID?

如何读取 Firestore (Swift) 中字段的值

如何从存储在 Firestore (Swift) 中的文档中返回对象