Hỗ trợ nhiều tay điều khiển trò chơi

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()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:

  1. Phát hiện xem sự kiện đầu vào có xảy ra hay không.
  2. Xác định nguồn đầu vào và mã thiết bị của nguồn đó.
  3. 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ị đó.
  4. Kết xuất và cập nhật giao diện người dùng.

Phương thức nhập KeyEventMotionEvent 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.