여러 게임 컨트롤러 지원

대부분의 게임은 Android 기기당 단일 사용자를 지원하도록 설계되었지만 인코더-디코더 아키텍처를 기반으로 하는 게임 컨트롤러로 동일한 Android 기기에 동시에 연결되어 있어야 합니다.

이 강의에서는 단일 프로젝트에서 입력을 처리하는 몇 가지 기본 기술을 다룹니다. 여러 개의 연결된 컨트롤러에서 기기 멀티플레이어 게임을 할 수 있습니다. 여기에는 플레이어 아바타와 각 컨트롤러 기기 간의 매핑을 유지하고 컨트롤러 입력 이벤트를 적절히 처리합니다.

플레이어를 컨트롤러 기기 ID에 매핑

게임 컨트롤러가 Android 기기에 연결되면 시스템은 정수 기기 ID를 할당합니다. 연결된 기기의 기기 ID를 가져올 수 있으며 게임 컨트롤러를 사용하여 새 게임 컨트롤러를 만들 수 있습니다(게임 컨트롤러가 연결되었는지 확인 참고).InputDevice.getDeviceIds() 그런 다음 각 광고 단위를 기기 ID를 배치하고 플레이어마다 게임 작업을 개별적으로 처리합니다.

참고: Android 4.1 (API)을 실행하는 기기 레벨 16) 이상이 있는 경우, getDescriptor(): 고유한 영구 문자열 값입니다. 기기 ID와 달리 설명어는 입력 장치가 연결 해제되거나 다시 연결되거나 재구성됩니다

아래의 코드 스니펫은 SparseArray를 사용하는 방법을 보여줍니다. 플레이어의 아바타를 특정 컨트롤러와 연결하는 것입니다. 이 예에서 mShips 변수는 Ship 객체 컬렉션을 저장합니다. 새로운 플레이어 아바타는 사용자가 새 컨트롤러를 연결하면 게임 내에서 생성됩니다. 연결된 컨트롤러가 삭제되면 삭제됩니다.

onInputDeviceAdded()onInputDeviceRemoved() 콜백 메서드는 <ph type="x-smartling-placeholder"></ph> 다양한 Android 버전에서 컨트롤러 지원을 참조하세요. 이를 구현함으로써 리스너 콜백을 사용하면 리스너가 연결되었을 때 게임에서 게임 컨트롤러의 기기 ID를 컨트롤러가 추가되거나 삭제될 수 있습니다 이 감지 기능은 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)
}

자바

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);
}

여러 컨트롤러 입력 처리

게임에서 다음 루프를 실행하여 여러 컨트롤러의 입력:

  1. 입력 이벤트가 발생했는지 감지합니다.
  2. 입력 소스와 기기 ID를 확인합니다.
  3. 입력 이벤트 키 코드 또는 축 값에 의해 표시되는 액션에 따라, 해당 기기 ID와 연결된 플레이어 아바타를 업데이트합니다.
  4. 사용자 인터페이스를 렌더링하고 업데이트합니다.

KeyEventMotionEvent 입력 이벤트에는 연결된 기기 ID가 있습니다. 게임에서 이를 통해 입력 이벤트가 발생한 컨트롤러를 판단한 다음 해당 컨트롤러와 연결된 플레이어 아바타입니다.

다음 코드 스니펫은 플레이어 아바타 참조를 가져오는 방법을 보여줍니다. 게임 컨트롤러 기기 ID에 해당하는 기기 ID를 찾고, 이에 따라 게임을 사용자가 버튼을 눌러야 합니다.

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)
}

자바

@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);
}

참고: 일반적으로 사용자가 게임 컨트롤러의 연결이 끊어지면 게임을 일시중지하고 다시 연결하려고 합니다.