Lập trình trò xếp hình đối kháng online(Tetris Online) sử dụng Firebase (Phần 1)

Vì có nhiều bài viết về firebase rồi nên mình sẽ không đi sâu vào khái niệm nữa, các bạn có thể tìm với từ khoá “firebase” trên ngay trang này để đọc thêm.

Ở bài này mình sẽ hướng dẫn từng bước để có thể xây dựng được game xếp hình đối kháng chơi online ở mức đơn giản dùng firebase để lưu trữ dữ liệu của ván chơi, về cách làm game tetris mình cũng không đề cập nữa mà sẽ làm tiếp trên 1 opensource tetris khác các bạn có thể clone ở link này: https://github.com/Bloc/swiftris

Yêu cầu ban đầu:

  1. Máy tính cần cài cocoapod, các bạn có thể xem ở đây https://cocoapods.org
  2. Đăng ký tài khoản firebase, và có thể xem tài liệu của google, cùng sample code trước: https://firebase.google.com
  3. Có thể tìm hiểu trước về scenceKit (game sử dụng sceneKit)
  4. Ngôn ngữ sử dụng: Swift 3.0

Bước 1: vào trang firebase console https://console.firebase.google.com tạo 1 project của riêng bạn.

1.png

Bước 2: Click vào project vừa tạo, rồi tap vào mục Authentication, chọn tab SIGN-IN METHOD chọn enable email/password

2.png

**Bước 3: **tiếp tục chọn mục Database rồi chuyển qua tab RULES add rule cho data của game tetris online, ở đây mình sử dụng 2 keys, users (lưu thông tin user) và stages (lưu thông tin ván chơi), copy and patse thông tin bên dưới vào:

Code

- {
  "rules": {
        "users": {
            ".read": "auth != null",
            ".write": "auth != null"
        },
          "stages": {
            ".read": "auth != null",
            ".write": "auth != null"
        }
  }
}

3.png

Bước 4: Clone hoặc download project swiftris mình đã cung cấp link ở bên trên, mở terminal trỏ đến đường dẫn project vừa tải về, thiết lập cocoapod cho nó qua lệnh:

pod init

Mở file pod nhập các pod sau:

pod 'Firebase/Storage'
pod 'Firebase/AdMob'
pod 'Firebase/Auth'
pod 'Firebase/Crash'
pod 'Firebase/Database'
pod 'Firebase/RemoteConfig'

rồi gõ lệnh “pod install”, mở project workspace

Để ý file “Main.storyboard”, hiện tại nó chỉ có GameViewController, chúng ta cần bố trí lại bố cục của các controller bằng cách thêm 1 navigation controller, HomeViewController, LoginViewController

**Bước 5: ** Kéo Navigation controller, và HomeViewController vào storyboard đồng thời tạo các class tương ứng, HomeViewController là RootViewController của Navigation controller, kéo thêm 2 button Play và Login vào HomeView Controller

4.png

Tạo action tương ứng cho nút Play và Login

@IBAction func play(_ sender: UIButton) {
}

@IBAction func login(_ sender: UIButton) {
}

**Bước 6: **Kéo thêm LoginViewController vào storyboard tạo class tương ứng, các bạn có thể tạo form login giống như hình

5.png

Bước 7: Tạo SegueIdentifier tương ứng như hình bên dưới:

6.png

Ok đến bước này thì đã xong phần giao diện

Bước 8: Test thử game, ở màn hình home thêm sự kiện cho nút play:

   self.performSegue(withIdentifier:GamePlayIdentifier, sender: nil)

Run app nhấn play, lúc này game đã hoạt động, OK tiếp theo sẽ là xử lý login, register

**Bước 9: ** vào AppDelegate.swift trong phương thức didFinishLaunchingWithOption chèn thêm dòng lệnh này: FIRApp.configure() Dòng này có tác dụng khởi tạo config 1 số tham số ban đầu của fire base, nó là thread safe

**Bước 10: ** Khai báo các biến trong HomeViewController:

   var ref: FIRDatabaseReference! //Database reference
    fileprivate var _refHandle: FIRDatabaseHandle! // handle

bổ sung phương thức configureDatabase()

func configureDatabase() {
        ref = FIRDatabase.database().reference()
        // Listen for new stage in the Firebase database
        _refHandle = self.ref.child("users").observe(.childAdded, with: { [weak self] (snapshot) -> Void in
            //add stage table here
            guard let strongSelf = self else { return }

        })
    }

nhớ gọi nó ở viewDidLoad nhé:

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        configureDatabase()

    }

**Bước 11: **LoginViewController kéo outlet cho 2 textfield:

    @IBOutlet weak var tfEmail: UITextField!
    @IBOutlet weak var tfPassword: UITextField!

Kéo action cho nút login và nút register, gõ lệnh tương ứng

@IBAction func signUp(_ sender: Any) {

        guard let email = tfEmail.text, let password = tfPassword.text else {
            return
        }
        FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
            if let error = error {
                print(error.localizedDescription)
                return
            }

            self.signedIn(nil)
        })

    }

    @IBAction func login(_ sender: UIButton) {

        guard let email = tfEmail.text, let password = tfPassword.text else {
            return
        }
        FIRAuth.auth()?.signIn(withEmail: email, password: password, completion: { (user, error) in
            if let error = error {
                print(error.localizedDescription)
                return
            }

            self.signedIn(nil)
        })

    }

  func signedIn(_ user: FIRUser?) {
        self.dismiss(animated: true, completion: nil)
    }

Bước 12: Khi login thành công chúng ta sẽ ẩn form login đi và bổ sung code trong hàm viewDidAppear của HomeViewController:

override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if let user = FIRAuth.auth()?.currentUser {
            guard let name = us?.email else {
            return
        	}
			lbWelcome.text = "Welcome " + name
       	 btnLogin.setTitle("Logout", for: .normal)
        }else {
            btnLogin.setTitle("Login", for: .normal)
        }

    }

OK Run app và chạy thử, Xem thành quả sau khi login:

7.png

Lưu ý:

Để login và register được các bạn cần phải enable 1 phương thức authentication, mình đã hướng dẫn enable ở bước 2, trường hợp này mình sử dụng email và password để đăng nhập

**Bước 13: ** Ở bước này chúng ta sẽ xây dựng cấu trúc dữ liệu, ở đây mình sử dụng 2 objects User để lưu dữ liệu người dùng, và Stages để lưu dữ liệu ván chơi, dưới đây là game case:

8.png

Với Users chúng ta chỉ cần khai báo 1 số field nhất định đủ dùng, các bạn có thể khai báo thêm nếu thấy cần thiết:

 struct UserFields {
        static let email = "email"
        static let uID  = "uID"
        static let status = "status"
    }

Tiếp theo là Stages

struct StageFields {
        static let userID1 = "userId1"
        static let userID2 = "userId2"
        static let status = "status"
		   static let stageId = “stageID”
		   static let moves = “moves”

    }

trong đó moves là giá trị dùng để lưu thông tin di chuyển của các khối block, thao tác play1 đến với play2 và ngược lại Viết đến đây có vẻ hơi dài rồi mình sẽ cập nhật tiếp ở phần 2, ở phần sau mình sẽ tiếp tục hướng dẫn xử lý user, lấy danh sách user online và random 1 người để invite vào cuộc chơi, đồng thời xử lý đồng bộ move các khối shape.

like và scribble để cập nhật thông tin mới nhất các bạn nhé. Có bất kỳ vấn đề gì về bài viết các bạn có thể comment bên dưới, mình theo dõi thường xuyên và sẽ trả lời sớm nhất.


All Rights Reserved