แม้ว่าเกมส่วนใหญ่ออกแบบมาเพื่อรองรับผู้ใช้ 1 คนต่ออุปกรณ์ Android 1 เครื่อง คุณยังสามารถรองรับผู้ใช้หลายคนด้วยตัวควบคุมเกมที่ ที่เชื่อมต่อพร้อมกันได้ในอุปกรณ์ Android เครื่องเดียวกัน
บทเรียนนี้ครอบคลุมเทคนิคพื้นฐานบางประการสำหรับการจัดการการป้อนข้อมูลในซิงเกิลของคุณ เกมที่มีอุปกรณ์แบบผู้เล่นหลายคนจากตัวควบคุมหลายรายการที่เชื่อมต่ออยู่ ซึ่งรวมถึง การดูแลรักษาการแมประหว่างรูปโปรไฟล์ผู้เล่นและอุปกรณ์ควบคุมแต่ละเครื่อง และ ประมวลผลเหตุการณ์อินพุตตัวควบคุมอย่างเหมาะสม
แมปผู้เล่นกับรหัสอุปกรณ์ตัวควบคุม
เมื่อเกมคอนโทรลเลอร์เชื่อมต่อกับอุปกรณ์ Android ระบบจะ
กำหนดรหัสอุปกรณ์เป็นจำนวนเต็ม คุณสามารถรับรหัสอุปกรณ์สำหรับการเชื่อมต่อ
ตัวควบคุมเกมโดยโทรหา InputDevice.getDeviceIds()
ดังที่แสดงในยืนยันว่าตัวควบคุมเกมเชื่อมต่อแล้ว จากนั้น คุณสามารถเชื่อมโยง
รหัสอุปกรณ์ที่มีผู้เล่นอยู่ในเกม และประมวลผลการดำเนินการในเกมสำหรับผู้เล่นแต่ละคนแยกกัน
หมายเหตุ: ในอุปกรณ์ที่ใช้ Android 4.1 (API
ระดับ 16) ขึ้นไป คุณสามารถดูตัวบอกลักษณะของอุปกรณ์อินพุตได้โดยใช้
getDescriptor()
ซึ่งแสดงผลค่าที่ไม่ซ้ำกัน
ค่าสตริงถาวรสำหรับอุปกรณ์อินพุต ตัวบ่งชี้ต่างจากรหัสอุปกรณ์
จะไม่เปลี่ยนแปลงแม้ว่าอุปกรณ์อินพุตจะไม่ได้เชื่อมต่อ เชื่อมต่อใหม่ หรือ
กำหนดค่าใหม่หรือไม่
ข้อมูลโค้ดด้านล่างแสดงวิธีใช้ SparseArray
เพื่อเชื่อมโยงอวาตาร์ของผู้เล่นกับตัวควบคุมที่เจาะจง ในตัวอย่างนี้
ตัวแปร mShips
จัดเก็บคอลเล็กชันของออบเจ็กต์ Ship
รายการ ใหม่
ระบบจะสร้างรูปโปรไฟล์ของผู้เล่นในเกมเมื่อผู้ใช้แนบตัวควบคุมใหม่
และนำออกเมื่อมีการนำตัวควบคุมที่เกี่ยวข้องออก
การติดต่อกลับของ onInputDeviceAdded()
และ onInputDeviceRemoved()
เป็นส่วนหนึ่งของชั้นแอบสแตรกต์ที่แนะนำใน
การรองรับตัวควบคุมใน Android เวอร์ชันต่างๆ โดยการใช้สิ่งเหล่านี้
Listener Callback เกมของคุณสามารถระบุรหัสอุปกรณ์ของตัวควบคุมเกมเมื่อ
มีการเพิ่มหรือนำตัวควบคุมออก การตรวจหานี้เข้ากันได้กับ Android 2.3
(API ระดับ 9) ขึ้นไป
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); }
ประมวลผลอินพุตตัวควบคุมหลายรายการ
เกมของคุณควรเรียกใช้ลูปต่อไปนี้เพื่อประมวลผล อินพุตจากตัวควบคุมหลายตัว:
- ตรวจจับว่าเกิดเหตุการณ์อินพุตหรือไม่
- ระบุแหล่งที่มาของอินพุตและรหัสอุปกรณ์
- อิงตามการทำงานที่ระบุโดยรหัสคีย์ของเหตุการณ์ที่ป้อนหรือค่าแกน อัปเดตรูปโปรไฟล์ของผู้เล่นที่เชื่อมโยงกับรหัสอุปกรณ์นั้น
- แสดงผลและอัปเดตอินเทอร์เฟซผู้ใช้
อินพุต KeyEvent
และ MotionEvent
เหตุการณ์จะมีรหัสอุปกรณ์ที่เชื่อมโยงอยู่ เกมของคุณสามารถใช้ประโยชน์จาก
เพื่อระบุว่าเหตุการณ์อินพุตมาจากตัวควบคุมใด แล้วอัปเดตคอมโพเนนต์
อวาตาร์ของผู้เล่นที่เชื่อมโยงกับตัวควบคุมนั้น
ข้อมูลโค้ดต่อไปนี้แสดงวิธีที่คุณอาจได้รับการอ้างอิงรูปโปรไฟล์ของผู้เล่น สอดคล้องกับรหัสอุปกรณ์ตัวควบคุมเกม และอัปเดตเกมตามรหัสอุปกรณ์ ผู้ใช้กดปุ่มบนตัวควบคุมนั้น
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); }
หมายเหตุ: ตามแนวทางปฏิบัติที่ดีที่สุด เมื่อผู้ใช้ เกมคอนโทรลเลอร์ยกเลิกการเชื่อมต่อ คุณควรหยุดเกมชั่วคราวแล้วถามผู้ใช้ ต้องการเชื่อมต่อใหม่