Mặc dù hầu hết các trò chơi đều được thiết kế để hỗ trợ một người dùng duy nhất trên mỗi thiết bị Android, bạn cũng có thể hỗ trợ nhiều người dùng bằng tay điều khiển trò chơi được kết nối đồng thời trên cùng một thiết bị Android.
Bài học này đề cập đến một số kỹ thuật cơ bản để xử lý thông tin đầu vào trong trò chơi nhiều người chơi trên nhiều thiết bị từ nhiều tay điều khiển được kết nối. bao gồm duy trì mối liên kết giữa hình đại diện của người chơi và từng thiết bị tay điều khiển, xử lý sự kiện nhập của bộ điều khiển một cách thích hợp.
Liên kết người chơi với mã thiết bị của tay điều khiển
Khi tay điều khiển trò chơi kết nối với thiết bị Android, hệ thống
gán cho nó một mã thiết bị số nguyên. Bạn có thể lấy ID thiết bị cho các kết nối
tay điều khiển trò chơi bằng cách gọi InputDevice.getDeviceIds()
, như minh hoạ trong phần Xác minh tay điều khiển trò chơi đã kết nối. Sau đó, bạn có thể liên kết mỗi
mã thiết bị với người chơi trong trò chơi của bạn và xử lý hành động trong trò chơi cho từng người chơi riêng biệt.
Lưu ý: Trên các thiết bị chạy Android 4.1 (API
cấp 16) trở lên, bạn có thể lấy mã mô tả của thiết bị đầu vào bằng cách sử dụng
getDescriptor()
sẽ trả về một giá trị duy nhất
giá trị chuỗi cố định cho thiết bị đầu vào. Không giống như mã thiết bị, phần mô tả
giá trị sẽ không thay đổi ngay cả khi thiết bị đầu vào bị ngắt kết nối, đã kết nối lại, hoặc
đã định cấu hình lại.
Đoạn mã dưới đây cho biết cách sử dụng SparseArray
để liên kết hình đại diện của người chơi với một tay điều khiển cụ thể. Trong ví dụ này, phương thức
Biến mShips
lưu trữ một tập hợp các đối tượng Ship
. Một mô hình
hình đại diện của người chơi được tạo trong trò chơi khi người dùng gắn tay điều khiển mới vào,
và bị loại bỏ khi bộ điều khiển liên kết bị loại bỏ.
Lệnh gọi lại onInputDeviceAdded()
và onInputDeviceRemoved()
là một phần của tầng trừu tượng được đưa vào trong
Hỗ trợ tay điều khiển trên các phiên bản Android. Bằng cách triển khai
lệnh gọi lại trình nghe, trò chơi của bạn có thể xác định mã thiết bị của tay điều khiển trò chơi khi
thêm hoặc loại bỏ bộ điều khiển. Tính năng phát hiện này tương thích với Android 2.3
(API cấp 9) trở lên.
Kotlin
private val ships = SparseArray<Ship>() override fun onInputDeviceAdded(deviceId: Int) { getShipForID(deviceId) } override fun onInputDeviceRemoved(deviceId: Int) { removeShipForID(deviceId) } private fun getShipForID(shipID: Int): Ship { return ships.get(shipID) ?: Ship().also { ships.append(shipID, it) } } private fun removeShipForID(shipID: Int) { ships.remove(shipID) }
Java
private final SparseArray<Ship> ships = new SparseArray<Ship>(); @Override public void onInputDeviceAdded(int deviceId) { getShipForID(deviceId); } @Override public void onInputDeviceRemoved(int deviceId) { removeShipForID(deviceId); } private Ship getShipForID(int shipID) { Ship currentShip = ships.get(shipID); if ( null == currentShip ) { currentShip = new Ship(); ships.append(shipID, currentShip); } return currentShip; } private void removeShipForID(int shipID) { ships.remove(shipID); }
Xử lý hoạt động đầu vào của nhiều tay điều khiển
Trò chơi của bạn nên thực thi vòng lặp sau để xử lý dữ liệu đầu vào từ nhiều bộ điều khiển:
- Phát hiện xem sự kiện đầu vào có xảy ra hay không.
- Xác định nguồn đầu vào và mã thiết bị của nguồn đó.
- Dựa trên hành động chỉ định bằng mã khoá hoặc giá trị trục của sự kiện đầu vào, cập nhật hình đại diện của người chơi được liên kết với mã thiết bị đó.
- Kết xuất và cập nhật giao diện người dùng.
Phương thức nhập KeyEvent
và MotionEvent
có mã thiết bị liên kết với các sự kiện đó. Trò chơi của bạn có thể tận dụng
thao tác này để xác định sự kiện đầu vào xuất phát từ bộ điều khiển nào và cập nhật
hình đại diện của người chơi được liên kết với tay điều khiển đó.
Đoạn mã sau đây hướng dẫn cách để bạn có thể tham chiếu đến hình đại diện của người chơi tương ứng với mã thiết bị của tay điều khiển trò chơi và cập nhật trò chơi dựa trên thao tác nhấn nút của người dùng trên bộ điều khiển đó.
Kotlin
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) { event.deviceId.takeIf { it != -1 }?.also { deviceId -> val currentShip: Ship = getShipForID(deviceId) // Based on which key was pressed, update the player avatar // (e.g. set the ship headings or fire lasers) return true } } return super.onKeyDown(keyCode, event) }
Java
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { if ((event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { int deviceId = event.getDeviceId(); if (deviceId != -1) { Ship currentShip = getShipForId(deviceId); // Based on which key was pressed, update the player avatar // (e.g. set the ship headings or fire lasers) ... return true; } } return super.onKeyDown(keyCode, event); }
Lưu ý: Tốt nhất là khi người dùng tay điều khiển trò chơi ngắt kết nối, bạn nên tạm dừng trò chơi và hỏi xem người dùng muốn kết nối lại.