컨트롤러 작업 처리

시스템 수준에서 Android는 게임 컨트롤러의 입력 이벤트 코드를 보고합니다. Android 키 코드 및 축 값으로 사용합니다. 게임에서 다음 코드를 받을 수 있습니다. 특정 게임 내 활동으로 전환할 수 있습니다.

플레이어가 게임 컨트롤러를 물리적으로 연결하거나 무선으로 페어링할 때 Android 구동 장치를 사용하면 시스템이 자동으로 입력 장치로 사용하고 입력 이벤트를 보고하기 시작합니다. 게임에서 활성 액티비티에 다음 콜백 메서드를 구현하여 이러한 입력 이벤트를 Activity 또는 포커스가 맞춰진 View( Activity 또는 View 중 한 가지만).

가장 좋은 방법은 사용자가 상호작용하는 특정 View 객체입니다. 콜백에서 제공한 다음 객체를 검사하여 정보 가져오기 수신된 입력 이벤트 유형:

KeyEvent
방향을 설명하는 객체 패드 (D패드) 및 게임패드 버튼 이벤트입니다. 주요 이벤트에는 트리거된 특정 버튼을 나타내는 키 코드(예: <ph type="x-smartling-placeholder">DPAD_DOWN</ph> 또는 BUTTON_A. 여기에서 getKeyCode() 호출 또는 키에서 이벤트 콜백(예: onKeyDown()입니다.
MotionEvent
조이스틱 및 숄더 트리거의 입력을 나타내는 객체입니다. 움직입니다. 모션 이벤트에는 작업 코드와 축 값. 작업 코드는 조이스틱을 움직이는 것과 같이요. 축 값은 특정 물리적 제어를 위한 움직임 속성(예: AXIS_X 또는 AXIS_RTRIGGER입니다. 작업 코드를 가져올 수 있습니다. getAction()를 호출하고 축 값을 getAxisValue() 호출

이 강의에서는 가장 일반적인 유형의 API로부터 입력을 처리하는 방법을 물리적 컨트롤 (게임패드 버튼, 방향 패드 및 조이스틱을 게임 화면에 표시할 수 있습니다. View 콜백 메서드 및 처리 KeyEventMotionEvent 객체

게임 컨트롤러가 연결되어 있는지 확인

입력 이벤트를 보고할 때 Android는 발생한 이벤트와 비게임 컨트롤러 기기에서 발생한 이벤트 간의 차이 생성할 수 있습니다. 예를 들어 터치 스크린 작업은 X를 나타내는 AXIS_X 이벤트 좌표를 자동으로 생성할 수 있지만 조이스틱은 조이스틱의 X 위치를 나타내는 AXIS_X 이벤트입니다. 만약 게임 컨트롤러 입력 처리를 중요하게 생각한다면 먼저 입력 이벤트가 관련 소스 유형에서 비롯된다는 것을 의미합니다.

연결된 입력 장치가 게임 컨트롤러인지 확인하려면 getSources()는 다음과 같은 결합된 비트 필드를 얻습니다. 입력 소스 유형을 선택합니다. 그런 다음 테스트를 통해 다음 필드가 설정됩니다.

  • SOURCE_GAMEPAD의 소스 유형은 다음을 나타냅니다. 입력 장치에 게임패드 버튼 (예: BUTTON_A). 이 소스는 게임 컨트롤러에 D패드 버튼이 있는지 엄격하게 나타내지 않습니다. 그러나 대부분의 게임패드에는 일반적으로 방향 컨트롤이 있습니다.
  • SOURCE_DPAD의 소스 유형은 다음을 나타냅니다. 입력 장치에 D패드 버튼이 있는 경우 (예: DPAD_UP).
  • SOURCE_JOYSTICK의 소스 유형 는 입력 장치에 아날로그 컨트롤 스틱 (예: AXIS_X을 따라 움직임을 기록하는 조이스틱 및 AXIS_Y)

다음 코드 스니펫은 연결된 입력 장치는 게임 컨트롤러입니다. 설정된 경우 메서드는 게임 컨트롤러의 기기 ID입니다. 그런 다음 각 기기를 게임 플레이어와 ID를 지정하고 연결된 각 플레이어에 대해 게임 작업을 처리합니다. 개별적으로 재생할 수 있습니다. 여러 게임 컨트롤러 지원에 관해 자세히 알아보기 동일한 Android 기기에 동시에 연결되어 있는 경우 여러 게임 컨트롤러를 지원합니다.

Kotlin

fun getGameControllerIds(): List<Int> {
    val gameControllerDeviceIds = mutableListOf<Int>()
    val deviceIds = InputDevice.getDeviceIds()
    deviceIds.forEach { deviceId ->
        InputDevice.getDevice(deviceId).apply {

            // Verify that the device has gamepad buttons, control sticks, or both.
            if (sources and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD
                    || sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK) {
                // This device is a game controller. Store its device ID.
                gameControllerDeviceIds
                        .takeIf { !it.contains(deviceId) }
                        ?.add(deviceId)
            }
        }
    }
    return gameControllerDeviceIds
}

자바

public ArrayList<Integer> getGameControllerIds() {
    ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>();
    int[] deviceIds = InputDevice.getDeviceIds();
    for (int deviceId : deviceIds) {
        InputDevice dev = InputDevice.getDevice(deviceId);
        int sources = dev.getSources();

        // Verify that the device has gamepad buttons, control sticks, or both.
        if (((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
                || ((sources & InputDevice.SOURCE_JOYSTICK)
                == InputDevice.SOURCE_JOYSTICK)) {
            // This device is a game controller. Store its device ID.
            if (!gameControllerDeviceIds.contains(deviceId)) {
                gameControllerDeviceIds.add(deviceId);
            }
        }
    }
    return gameControllerDeviceIds;
}

또한 개별 입력 기능을 확인하는 것이 좋습니다. 게임 컨트롤러입니다. 예를 들어, 게임에서 물리적 컨트롤 세트의 입력만 사용하도록 하려는 경우 이해할 수 있습니다

특정 키 코드 또는 축 코드가 연결된 다음 기법을 사용하세요.

  • Android 4.4 (API 수준 19) 이상에서는 키 코드가 연결된 게임 컨트롤러에서 지원되는 hasKeys(int...)
  • Android 3.1 (API 수준 12) 이상에서는 사용 가능한 모든 축을 찾을 수 있습니다. 연결된 게임 컨트롤러에서 지원되는 getMotionRanges() 그런 다음 InputDevice.MotionRange 객체 반환됨, 호출 getAxis(): 축 ID를 가져옵니다.

게임패드 버튼 누름 처리

그림 1은 Android가 키 코드와 축 값을 실제 컨트롤을 사용하는 것입니다.

그림 1. 일반 게임 컨트롤러용 프로필

그림에서 번호는 다음을 가리킵니다.

게임패드 버튼을 누를 때 생성되는 일반적인 키 코드는 다음과 같습니다. BUTTON_A, BUTTON_B, BUTTON_SELECT, 및 BUTTON_START. 일부 게임 또한 컨트롤러는 D패드 크로스바의 중앙을 누르면 DPAD_CENTER 키 코드를 트리거합니다. 내 게임에서 getKeyCode()를 호출하여 키 코드를 검사할 수 있습니다. 키 이벤트 콜백(예: onKeyDown(), 그리고 게임과 관련된 이벤트를 나타내는 경우에는 게임 액션입니다. 표 1에는 가장 일반적인 경우의 권장 게임 작업이 나열되어 있습니다. 게임패드 버튼

표 1. 게임패드용 권장 게임 작업 버튼을 클릭합니다.

게임 작업 버튼 키 코드
메인 메뉴에서 게임을 시작하거나 게임 중 일시중지 또는 일시중지 해제 BUTTON_START*
메뉴 표시 BUTTON_SELECT*KEYCODE_MENU*
아래 참조에 설명된 Android 뒤로 탐색 동작과 동일합니다. 탐색 디자인 참조하세요. KEYCODE_BACK
메뉴에서 이전 항목으로 돌아가기 BUTTON_B
선택을 확인하거나 기본 게임 작업 실행 BUTTON_ADPAD_CENTER

* 게임에서 시작, 선택 또는 메뉴가 있어서는 안 됩니다. 있습니다

도움말: 구성 화면을 제공하는 것이 좋습니다. 사용자가 게임 컨트롤러 매핑을 맞춤설정하도록 허용 게임 액션도 있습니다.

다음 스니펫은 onKeyDown()부터 BUTTON_A와 버튼 누름 DPAD_CENTER회 게임 액션이 있습니다.

Kotlin

class GameView(...) : View(...) {
    ...

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        var handled = false
        if (event.source and InputDevice.SOURCE_GAMEPAD == InputDevice.SOURCE_GAMEPAD) {
            if (event.repeatCount == 0) {
                when (keyCode) {
                    // Handle gamepad and D-pad button presses to navigate the ship
                    ...

                    else -> {
                        keyCode.takeIf { isFireKey(it) }?.run {
                            // Update the ship object to fire lasers
                            ...
                            handled = true
                        }
                    }
                }
            }
            if (handled) {
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    // Here we treat Button_A and DPAD_CENTER as the primary action
    // keys for the game.
    private fun isFireKey(keyCode: Int): Boolean =
            keyCode == KeyEvent.KEYCODE_DPAD_CENTER || keyCode == KeyEvent.KEYCODE_BUTTON_A
}

자바

public class GameView extends View {
    ...

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        boolean handled = false;
        if ((event.getSource() & InputDevice.SOURCE_GAMEPAD)
                == InputDevice.SOURCE_GAMEPAD) {
            if (event.getRepeatCount() == 0) {
                switch (keyCode) {
                    // Handle gamepad and D-pad button presses to
                    // navigate the ship
                    ...

                    default:
                         if (isFireKey(keyCode)) {
                             // Update the ship object to fire lasers
                             ...
                             handled = true;
                         }
                     break;
                }
            }
            if (handled) {
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }

    private static boolean isFireKey(int keyCode) {
        // Here we treat Button_A and DPAD_CENTER as the primary action
        // keys for the game.
        return keyCode == KeyEvent.KEYCODE_DPAD_CENTER
                || keyCode == KeyEvent.KEYCODE_BUTTON_A;
    }
}

참고: Android 4.2 (API) 17) 이하에서는 BUTTON_A: Android 기본적으로 뒤로 키. 앱에서 다음 Android를 지원하는 경우 한 개 이상의 기본 게임: BUTTON_A 있습니다. 현재 Android SDK 확인 자세히 알아보려면 Build.VERSION.SDK_INT 값입니다.

방향 패드 입력 처리

4방향 패드 (D패드)는 많은 게임에서 일반적인 물리적 컨트롤입니다. 컨트롤러입니다 Android는 D패드의 위/아래를 누를 때를 다음과 같이 보고합니다. 범위가 있는 이벤트 AXIS_HAT_Y개 -1.0 (위)에서 1.0 (아래)까지, D패드 왼쪽 또는 오른쪽 누름 범위가 -1.0인 AXIS_HAT_X 이벤트 (왼쪽)에서 1.0 (오른쪽)까지.

일부 컨트롤러는 D패드가 눌렸을 때 이벤트 대신 키 코드로 보고합니다. 게임 D패드 누르기에 관심이 있는 경우 해트축 이벤트와 D패드를 키 코드를 동일한 입력 이벤트로 설정해야 합니다.

표 2. D패드 키에 권장되는 기본 게임 작업 코드 및 해트 축 값입니다.

게임 작업 D패드 키 코드 해트 축 코드
위로 이동 KEYCODE_DPAD_UP AXIS_HAT_Y(0 ~ -1.0의 값을 가짐)
아래로 이동 KEYCODE_DPAD_DOWN AXIS_HAT_Y(0 ~ 1.0의 값을 가짐)
왼쪽으로 이동 KEYCODE_DPAD_LEFT AXIS_HAT_X(0 ~ -1.0의 값을 가짐)
오른쪽으로 이동 KEYCODE_DPAD_RIGHT AXIS_HAT_X(0 ~ 1.0의 값을 가짐)

다음 코드 스니펫은 모자를 확인할 수 있는 도우미 클래스를 보여줍니다. 축 및 키 코드 값을 사용하여 D패드 방향을 결정합니다.

Kotlin

class Dpad {

    private var directionPressed = -1 // initialized to -1

    fun getDirectionPressed(event: InputEvent): Int {
        if (!isDpadDevice(event)) {
            return -1
        }

        // If the input event is a MotionEvent, check its hat axis values.
        (event as? MotionEvent)?.apply {

            // Use the hat axis value to find the D-pad direction
            val xaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_X)
            val yaxis: Float = event.getAxisValue(MotionEvent.AXIS_HAT_Y)

            directionPressed = when {
                // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
                // LEFT and RIGHT direction accordingly.
                xaxis.compareTo(-1.0f) == 0 -> Dpad.LEFT
                xaxis.compareTo(1.0f) == 0 -> Dpad.RIGHT
                // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
                // UP and DOWN direction accordingly.
                yaxis.compareTo(-1.0f) == 0 -> Dpad.UP
                yaxis.compareTo(1.0f) == 0 -> Dpad.DOWN
                else -> directionPressed
            }
        }
        // If the input event is a KeyEvent, check its key code.
        (event as? KeyEvent)?.apply {

            // Use the key code to find the D-pad direction.
            directionPressed = when(event.keyCode) {
                KeyEvent.KEYCODE_DPAD_LEFT -> Dpad.LEFT
                KeyEvent.KEYCODE_DPAD_RIGHT -> Dpad.RIGHT
                KeyEvent.KEYCODE_DPAD_UP -> Dpad.UP
                KeyEvent.KEYCODE_DPAD_DOWN -> Dpad.DOWN
                KeyEvent.KEYCODE_DPAD_CENTER ->  Dpad.CENTER
                else -> directionPressed
            }
        }
        return directionPressed
    }

    companion object {
        internal const val UP = 0
        internal const val LEFT = 1
        internal const val RIGHT = 2
        internal const val DOWN = 3
        internal const val CENTER = 4

        fun isDpadDevice(event: InputEvent): Boolean =
            // Check that input comes from a device with directional pads.
            event.source and InputDevice.SOURCE_DPAD != InputDevice.SOURCE_DPAD
    }
}

자바

public class Dpad {
    final static int UP       = 0;
    final static int LEFT     = 1;
    final static int RIGHT    = 2;
    final static int DOWN     = 3;
    final static int CENTER   = 4;

    int directionPressed = -1; // initialized to -1

    public int getDirectionPressed(InputEvent event) {
        if (!isDpadDevice(event)) {
           return -1;
        }

        // If the input event is a MotionEvent, check its hat axis values.
        if (event instanceof MotionEvent) {

            // Use the hat axis value to find the D-pad direction
            MotionEvent motionEvent = (MotionEvent) event;
            float xaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X);
            float yaxis = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y);

            // Check if the AXIS_HAT_X value is -1 or 1, and set the D-pad
            // LEFT and RIGHT direction accordingly.
            if (Float.compare(xaxis, -1.0f) == 0) {
                directionPressed =  Dpad.LEFT;
            } else if (Float.compare(xaxis, 1.0f) == 0) {
                directionPressed =  Dpad.RIGHT;
            }
            // Check if the AXIS_HAT_Y value is -1 or 1, and set the D-pad
            // UP and DOWN direction accordingly.
            else if (Float.compare(yaxis, -1.0f) == 0) {
                directionPressed =  Dpad.UP;
            } else if (Float.compare(yaxis, 1.0f) == 0) {
                directionPressed =  Dpad.DOWN;
            }
        }

        // If the input event is a KeyEvent, check its key code.
        else if (event instanceof KeyEvent) {

           // Use the key code to find the D-pad direction.
            KeyEvent keyEvent = (KeyEvent) event;
            if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
                directionPressed = Dpad.LEFT;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
                directionPressed = Dpad.RIGHT;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {
                directionPressed = Dpad.UP;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
                directionPressed = Dpad.DOWN;
            } else if (keyEvent.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) {
                directionPressed = Dpad.CENTER;
            }
        }
        return directionPressed;
    }

    public static boolean isDpadDevice(InputEvent event) {
        // Check that input comes from a device with directional pads.
        if ((event.getSource() & InputDevice.SOURCE_DPAD)
             != InputDevice.SOURCE_DPAD) {
             return true;
         } else {
             return false;
         }
     }
}

처리하려는 모든 곳에서 게임에서 이 도우미 클래스를 사용할 수 있습니다. D패드 입력 (예: onGenericMotionEvent() 또는 onKeyDown() 합니다.

예를 들면 다음과 같습니다.

Kotlin

private val dpad = Dpad()
...
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
    if (Dpad.isDpadDevice(event)) {
        when (dpad.getDirectionPressed(event)) {
            Dpad.LEFT -> {
                // Do something for LEFT direction press
                ...
                return true
            }
            Dpad.RIGHT -> {
                // Do something for RIGHT direction press
                ...
                return true
            }
            Dpad.UP -> {
                // Do something for UP direction press
                ...
                return true
            }
            ...
        }
    }

    // Check if this event is from a joystick movement and process accordingly.
    ...
}

자바

Dpad dpad = new Dpad();
...
@Override
public boolean onGenericMotionEvent(MotionEvent event) {

    // Check if this event if from a D-pad and process accordingly.
    if (Dpad.isDpadDevice(event)) {

       int press = dpad.getDirectionPressed(event);
       switch (press) {
            case LEFT:
                // Do something for LEFT direction press
                ...
                return true;
            case RIGHT:
                // Do something for RIGHT direction press
                ...
                return true;
            case UP:
                // Do something for UP direction press
                ...
                return true;
            ...
        }
    }

    // Check if this event is from a joystick movement and process accordingly.
    ...
}

조이스틱 이동 처리

플레이어가 게임 컨트롤러에서 조이스틱을 움직이면 Android에서 MotionEvent: ACTION_MOVE 작업 코드 및 업데이트된 조이스틱 축의 위치를 조정합니다. 게임에서 Google Play 게임즈에서 제공하는 MotionEvent: 조이스틱이 움직이는지 확인합니다. 파악할 수 있습니다.

조이스틱 모션 이벤트는 여러 이동 샘플을 함께 일괄 처리할 수 있음 단일 객체 내에서 실행할 수 있습니다 MotionEvent 객체에는 각 조이스틱 축의 현재 위치와 여러 과거 위치를 지정할 수 있습니다. 작업 코드가 ACTION_MOVE인 모션 이벤트 (예: 조이스틱 움직임)를 보고할 때 Android는 축 값을 자동으로 조정합니다. 축의 과거 값은 현재 축 값보다 이전되고 다음보다 최근인 고유 값 집합 이전 모션 이벤트에서 보고된 값입니다. 자세한 내용은 자세한 내용은 MotionEvent를 참조하세요.

이전 정보를 사용하여 게임을 더 정확하게 렌더링할 수 있습니다. 물체의 움직임을 인식합니다. 받는사람 현재 값과 과거 값을 검색하고, getAxisValue() 또는 getHistoricalAxisValue() 또한 지난 30일간의 조이스틱 이벤트에 대한 포인트를 getHistorySize()

다음 스니펫은 조이스틱 입력을 처리하는 onGenericMotionEvent() 콜백 먼저 축의 과거 값을 처리한 다음 현재 위치를 처리합니다.

Kotlin

class GameView(...) : View(...) {

    override fun onGenericMotionEvent(event: MotionEvent): Boolean {

        // Check that the event came from a game controller
        return if (event.source and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK
                && event.action == MotionEvent.ACTION_MOVE) {

            // Process the movements starting from the
            // earliest historical position in the batch
            (0 until event.historySize).forEach { i ->
                // Process the event at historical position i
                processJoystickInput(event, i)
            }

            // Process the current movement sample in the batch (position -1)
            processJoystickInput(event, -1)
            true
        } else {
            super.onGenericMotionEvent(event)
        }
    }
}

자바

public class GameView extends View {

    @Override
    public boolean onGenericMotionEvent(MotionEvent event) {

        // Check that the event came from a game controller
        if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) ==
                InputDevice.SOURCE_JOYSTICK &&
                event.getAction() == MotionEvent.ACTION_MOVE) {

            // Process all historical movement samples in the batch
            final int historySize = event.getHistorySize();

            // Process the movements starting from the
            // earliest historical position in the batch
            for (int i = 0; i < historySize; i++) {
                // Process the event at historical position i
                processJoystickInput(event, i);
            }

            // Process the current movement sample in the batch (position -1)
            processJoystickInput(event, -1);
            return true;
        }
        return super.onGenericMotionEvent(event);
    }
}

조이스틱 입력을 사용하기 전에 조이스틱이 그에 따라 축 이동을 계산합니다. 일반적으로 조이스틱 평면 영역, 즉 (0,0) 좌표 근처의 값 범위 여기에서 축이 중심에 있는 것으로 간주됩니다. 축 값이 Android가 평평한 영역 내에 있으므로 컨트롤러를 다음과 같이 처리해야 합니다. 두 축을 따라 움직이지 않습니다.

아래 스니펫은 이동을 계산하는 도우미 메서드를 보여줍니다. 표시됩니다. processJoystickInput() 메서드에서 이 도우미를 호출합니다. 아래에 자세히 설명되어 있습니다.

Kotlin

private fun getCenteredAxis(
        event: MotionEvent,
        device: InputDevice,
        axis: Int,
        historyPos: Int
): Float {
    val range: InputDevice.MotionRange? = device.getMotionRange(axis, event.source)

    // A joystick at rest does not always report an absolute position of
    // (0,0). Use the getFlat() method to determine the range of values
    // bounding the joystick axis center.
    range?.apply {
        val value: Float = if (historyPos < 0) {
            event.getAxisValue(axis)
        } else {
            event.getHistoricalAxisValue(axis, historyPos)
        }

        // Ignore axis values that are within the 'flat' region of the
        // joystick axis center.
        if (Math.abs(value) > flat) {
            return value
        }
    }
    return 0f
}

자바

private static float getCenteredAxis(MotionEvent event,
        InputDevice device, int axis, int historyPos) {
    final InputDevice.MotionRange range =
            device.getMotionRange(axis, event.getSource());

    // A joystick at rest does not always report an absolute position of
    // (0,0). Use the getFlat() method to determine the range of values
    // bounding the joystick axis center.
    if (range != null) {
        final float flat = range.getFlat();
        final float value =
                historyPos < 0 ? event.getAxisValue(axis):
                event.getHistoricalAxisValue(axis, historyPos);

        // Ignore axis values that are within the 'flat' region of the
        // joystick axis center.
        if (Math.abs(value) > flat) {
            return value;
        }
    }
    return 0;
}

다음은 조이스틱 이동을 처리하는 방법에 대한 모든 것을 모아 놓은 것입니다. 있습니다.

Kotlin

private fun processJoystickInput(event: MotionEvent, historyPos: Int) {

    val inputDevice = event.device

    // Calculate the horizontal distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat axis, or the right control stick.
    var x: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_X, historyPos)
    if (x == 0f) {
        x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_X, historyPos)
    }
    if (x == 0f) {
        x = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Z, historyPos)
    }

    // Calculate the vertical distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat switch, or the right control stick.
    var y: Float = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_Y, historyPos)
    if (y == 0f) {
        y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_HAT_Y, historyPos)
    }
    if (y == 0f) {
        y = getCenteredAxis(event, inputDevice, MotionEvent.AXIS_RZ, historyPos)
    }

    // Update the ship object based on the new x and y values
}

자바

private void processJoystickInput(MotionEvent event,
        int historyPos) {

    InputDevice inputDevice = event.getDevice();

    // Calculate the horizontal distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat axis, or the right control stick.
    float x = getCenteredAxis(event, inputDevice,
            MotionEvent.AXIS_X, historyPos);
    if (x == 0) {
        x = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_HAT_X, historyPos);
    }
    if (x == 0) {
        x = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_Z, historyPos);
    }

    // Calculate the vertical distance to move by
    // using the input value from one of these physical controls:
    // the left control stick, hat switch, or the right control stick.
    float y = getCenteredAxis(event, inputDevice,
            MotionEvent.AXIS_Y, historyPos);
    if (y == 0) {
        y = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_HAT_Y, historyPos);
    }
    if (y == 0) {
        y = getCenteredAxis(event, inputDevice,
                MotionEvent.AXIS_RZ, historyPos);
    }

    // Update the ship object based on the new x and y values
}

좀 더 정교한 게임 컨트롤러를 지원하는 데 기능을 사용하는 경우 다음 모범 사례를 따르세요.

  • 듀얼 컨트롤러 스틱의 처리. 많은 게임 컨트롤러에는 조이스틱을 좌우로 조작해야 합니다. 왼쪽 스틱의 경우 Android 수평 이동을 AXIS_X 이벤트로 보고 및 수직 이동을 AXIS_Y 이벤트로 간주할 수 있습니다. 오른쪽 스틱의 경우 Android는 수평 이동을 다음과 같이 보고합니다. 이벤트 AXIS_Z회 및 수직 이동 이벤트 AXIS_RZ개 처리 속도 향상 두 컨트롤러가 모두 코드에 꽂혀 있습니다.
  • 숄더 트리거 누름 처리 (대체 입력 제공) 메서드). 일부 컨트롤러에는 왼쪽 및 오른쪽 어깨가 있습니다. 지정할 수도 있습니다 이러한 트리거가 있는 경우 Android는 왼쪽 트리거 누르기를 보고합니다. AXIS_LTRIGGER 이벤트로 오른쪽 트리거 누르기 AXIS_RTRIGGER 이벤트. Android의 경우 4.3(API 레벨 18) 4.3(API 레벨 18)의 AXIS_LTRIGGER에서는 다음 항목도 보고합니다. AXIS_BRAKE 축의 동일한 값입니다. 이 AXIS_RTRIGGERAXIS_GAS입니다. Android에서 모든 아날로그 트리거를 보고함 0.0 (해제됨)에서 1.0 (완전히 눌림) 사이의 정규화된 값으로 누르기 비 모든 컨트롤러에는 트리거가 있으므로 플레이어가 사용할 수 있습니다.