Kontrol cihazlarında iki tür işlem vardır:
KeyEvent"Açık" ve "kapalı" ikili durumuna sahip tüm düğmeler için kullanılır.MotionEventBir değer aralığı döndüren tüm eksenler için kullanılır. Örneğin, analog çubuklar için -1 ile 1 arasında veya analog tetikler için 0 ile 1 arasında.
Bu girişleri View bölümünden okuyabilirsiniz. focus.
onGenericMotionEvent, herhangi birMotionEventiçin artırılır.Düğmelere basılıp bırakıldığında
onKeyDownveonKeyUp,KeyEventiçin yükseltilir.
Kotlin
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (event.isFromSource(SOURCE_GAMEPAD)
&& event.repeatCount == 0
) {
Log.d("GameView", "Gamepad key pressed: $keyCode")
return true
}
return super.onKeyDown(keyCode, event)
}
override fun onGenericMotionEvent(event: MotionEvent): Boolean {
if (event.isFromSource(SOURCE_JOYSTICK)) {
Log.d("GameView", "Gamepad event: $event")
return true
}
return super.onGenericMotionEvent(event)
}
Java
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (event.isFromSource(SOURCE_GAMEPAD)
&& event.getRepeatCount() == 0
) {
Log.d("GameView", "Gamepad key pressed: " + keyCode);
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onGenericMotionEvent(MotionEvent event) {
if (event.isFromSource(SOURCE_JOYSTICK)) {
Log.d("GameView", "Gamepad event: " + event);
return true;
}
return super.onGenericMotionEvent(event);
}
Gerekirse etkinlikleri doğrudan Activity kaynağından okuyabilirsiniz.
dispatchGenericMotionEventherhangi birMotionEventiçin yükseltilir.dispatchKeyEvent. Herhangi birKeyEventiçin artırılır.
Oyun kumandasının bağlı olduğunu doğrulayın.
Android, giriş etkinliklerini bildirirken farklı giriş cihazı türleri için aynı tuş veya eksen kimliklerini yeniden kullanır. Örneğin, dokunmatik ekran işlemi, dokunma yüzeyinin X koordinatını temsil eden bir AXIS_X etkinliği oluşturur ancak gamepad, sol çubuğun X konumunu temsil eden bir AXIS_X etkinliği oluşturur. Bu nedenle, giriş etkinliklerini doğru şekilde yorumlamak için kaynak türünü kontrol etmeniz gerekir.
Bağlı bir InputDevice cihazın oyun kumandası olduğunu doğrulamak için supportsSource(int) işlevini kullanın:
SOURCE_GAMEPADkaynak türü, giriş cihazında kontrol düğmeleri (örneğin,KEYCODE_BUTTON_A) olduğunu gösterir. Bu kaynak türünün, oyun kumandasında yön tuşları olup olmadığını kesin olarak belirtmediğini unutmayın. Bununla birlikte, çoğu kumandada genellikle yön kontrolleri bulunur.SOURCE_DPADkaynak türü, giriş cihazında D-pad düğmeleri (ör.DPAD_UP) olduğunu gösterir.SOURCE_JOYSTICKkaynak türü, giriş cihazının analog kontrol çubuklarına (örneğin,AXIS_XveAXIS_Yboyunca hareketleri kaydeden bir joystick) sahip olduğunu gösterir.
Aşağıdaki kod snippet'inde, bağlı giriş cihazlarının oyun kumandası olup olmadığını kontrol etmenizi sağlayan bir yardımcı yöntem gösterilmektedir. Bu durumda yöntem, oyun kumandalarının cihaz kimliklerini alır. Ardından her cihaz kimliğini oyununuzdaki bir oyuncuyla ilişkilendirebilir ve bağlı her oyuncu için oyun işlemlerini ayrı ayrı işleyebilirsiniz. Aynı Android destekli cihaza aynı anda bağlanan birden fazla oyun denetleyicisini destekleme hakkında daha fazla bilgi edinmek için Birden fazla oyun denetleyicisini destekleme başlıklı makaleyi inceleyin.
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 (supportsSource(SOURCE_GAMEPAD)
|| supportsSource(SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
gameControllerDeviceIds
.takeIf { !it.contains(deviceId) }
?.add(deviceId)
}
}
}
return gameControllerDeviceIds
}
Java
public ArrayList<Integer> getGameControllerIds() {
ArrayList<Integer> gameControllerDeviceIds = new ArrayList<Integer>();
int[] deviceIds = InputDevice.getDeviceIds();
for (int deviceId : deviceIds) {
InputDevice dev = InputDevice.getDevice(deviceId);
if (dev == null) {
continue;
}
// Verify that the device has gamepad buttons, control sticks, or both.
if (dev.supportsSource(SOURCE_GAMEPAD) || dev.supportsSource(SOURCE_JOYSTICK)) {
// This device is a game controller. Store its device ID.
if (!gameControllerDeviceIds.contains(deviceId)) {
gameControllerDeviceIds.add(deviceId);
}
}
}
return gameControllerDeviceIds;
}
İşlem denetleyici girişleri
Bu bölümde, Android'de desteklenen oyun kumandası türleri açıklanmaktadır.
C++ geliştiricileri Game Controller Library'yi kullanmalıdır. Tüm denetleyicileri en yaygın özelliklerin alt kümesinde birleştirir ve düğme düzenini algılama özelliği de dahil olmak üzere aralarında tutarlı bir arayüz sağlar.
Bu şekil, Android oyun geliştiricilerin Android'de yaygın bir kontrol cihazının nasıl görünmesini bekleyebileceğini gösterir.
Tabloda, oyun kumandaları için standart etkinlik adları ve türleri listelenmektedir. Etkinliklerin tam listesi için Sık kullanılan varyantlar başlıklı makaleyi inceleyin. Sistem, MotionEvent etkinliklerini onGenericMotionEvent ve KeyEvent etkinliklerini onKeyDown ve onKeyUp üzerinden gönderir.
| Kumanda Girişi | KeyEvent | MotionEvent |
|---|---|---|
| 1. D-Pad |
AXIS_HAT_X(yatay giriş) AXIS_HAT_Y(dikey giriş) |
|
| 2. Sol Analog Çubuk |
KEYCODE_BUTTON_THUMBL(içe bastırıldığında) |
AXIS_X(yatay hareket) AXIS_Y(dikey hareket) |
| 3. Sağ Analog Çubuk |
KEYCODE_BUTTON_THUMBR(içe bastırıldığında) |
AXIS_Z(yatay hareket) AXIS_RZ(dikey hareket) |
| 4. X Düğmesi | KEYCODE_BUTTON_X |
|
| 5. A düğmesi | KEYCODE_BUTTON_A |
|
| 6. Y Düğmesi | KEYCODE_BUTTON_Y |
|
| 7. B Düğmesi | KEYCODE_BUTTON_B |
|
| 8. Sağ Bumper |
KEYCODE_BUTTON_R1 |
|
| 9. Sağ tetikleyici |
AXIS_RTRIGGER |
|
| 10. Sol tetikleyici | AXIS_LTRIGGER |
|
| 11. Sol Bumper | KEYCODE_BUTTON_L1 |
|
| 12. Başlat | KEYCODE_BUTTON_START |
|
| 13. Seç | KEYCODE_BUTTON_SELECT |
Düğmeye basma işlemlerini işleme
Android, kumanda düğmesine basma işlemlerini klavye düğmesine basma işlemleriyle aynı şekilde bildirdiğinden:
- Etkinliğin bir
SOURCE_GAMEPADtarafından gönderildiğini doğrulayın. KeyEvent.getRepeatCount()ile düğmeyi yalnızca bir kez aldığınızdan emin olun. Android, klavye tuşunu basılı tuttuğunuzda olduğu gibi tekrarlanan tuş etkinlikleri gönderir.- Bir etkinliğin işlendiğini belirtmek için
truedeğerini döndürün. Android'in çeşitli uyumluluk katmanlarının düzgün çalıştığını doğrulamak için işlenmemiş etkinlikleri
super'ye iletin.Kotlin
class GameView : View { // ... override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { event.apply { var handled = false // make sure we're handling gamepad events if (isFromSource(SOURCE_GAMEPAD)) { // avoid processing the keycode repeatedly if (repeatCount == 0) { when (keyCode) { // handle the "A" button KEYCODE_BUTTON_A -> { handled = true } } // ... } } if (handled) { return true } } return super.onKeyDown(keyCode, event) } }Java
public class GameView extends View { // ... @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean handled = false; // make sure we're handling gamepad events if (event.isFromSource(SOURCE_GAMEPAD)) { // avoid processing the keycode repeatedly if (event.getRepeatCount() == 0) { switch (keyCode) { case KEYCODE_BUTTON_A: // handle the "A" button handled = true; break; // ... } } // mark this event as handled if (handled) { return true; } } // Always do this instead of "return false" // it allows Android's input compatibility layers to work return super.onKeyDown(keyCode, event); } }
Yön tuşu girişini işleme
4 yönlü yön tuşu veya D-pad, birçok oyun kumandasında yaygın olarak kullanılan fiziksel bir kontrol mekanizmasıdır. Android, D-pad'in YUKARI ve AŞAĞI tuşlarına basma işlemlerini AXIS_HAT_Y etkinlikleri olarak bildirir. -1,0 yukarı, 1,0 ise aşağı yönü gösterir. D-pad'in SOL veya SAĞ tuşuna basma işlemlerini AXIS_HAT_X etkinlikleri olarak bildirir. -1,0 değeri sol, 1,0 değeri ise sağ tuşa basıldığını gösterir.
Bazı kontrol cihazları ise D-pad tuşlarına basıldığında tuş koduyla bildirir. Oyununuzda yön tuşuna basma işlemleri önemliyse 2. tabloda önerildiği gibi şapka ekseni etkinliklerini ve yön tuşu kodlarını aynı giriş etkinlikleri olarak değerlendirmeniz gerekir.
Tablo 2. D-pad tuş kodları ve şapka ekseni değerleri için önerilen varsayılan oyun işlemleri.
| Oyun İşlemi | D-pad Tuş Kodu | Hat Axis Code |
|---|---|---|
| Yukarı Taşı | KEYCODE_DPAD_UP |
AXIS_HAT_Y (0 ile -1,0 arasındaki değerler için) |
| Aşağı Taşı | KEYCODE_DPAD_DOWN |
AXIS_HAT_Y (0 ile 1,0 arasındaki değerler için) |
| Sola Taşı | KEYCODE_DPAD_LEFT |
AXIS_HAT_X (0 ile -1,0 arasındaki değerler için) |
| Sağa Taşı | KEYCODE_DPAD_RIGHT |
AXIS_HAT_X (0 ile 1,0 arasındaki değerler için) |
Aşağıdaki kod snippet'inde, D-pad yönünü belirlemek için giriş etkinliğindeki şapka ekseni ve tuş kodu değerlerini kontrol etmenize olanak tanıyan bir yardımcı sınıf gösterilmektedir.
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.
return event.isFromSource(InputDevice.SOURCE_DPAD)
}
}
Java
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.
return event.isFromSource(InputDevice.SOURCE_DPAD);
}
}
Bu yardımcı sınıfı, D-pad girişini işlemek istediğiniz her yerde (ör. onGenericMotionEvent() veya onKeyDown() geri çağırmalarında) oyununuzda kullanabilirsiniz.
Örneğin:
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.
...
}
Java
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.
...
}
Joystick hareketlerini işleme
Oyuncular oyun kumandalarındaki bir kontrol çubuğunu hareket ettirdiğinde Android, MotionEvent içeren bir ACTION_MOVE işlemi bildirir. Bu işlem, kontrol çubuğunun eksenlerinin güncellenmiş konumlarını içerir. Oyununuz, MotionEvent tarafından sağlanan verileri kullanarak ilgilendiği bir joystick hareketinin gerçekleşip gerçekleşmediğini belirleyebilir.
Joystick hareket etkinliklerinin, tek bir nesne içinde birden fazla hareket örneğini birlikte gruplandırabileceğini unutmayın. MotionEvent nesnesi, her bir kontrol çubuğu ekseninin mevcut konumunun yanı sıra her eksenin birden fazla geçmiş konumunu içerir. Hareket etkinlikleri, ACTION_MOVE işlem koduyla (ör. joystick hareketleri) raporlandığında Android, verimlilik için eksen değerlerini toplu olarak işler. Bir eksenin geçmiş değerleri, geçerli eksen değerinden eski ve önceki hareket etkinliklerinde bildirilen değerlerden daha yeni olan farklı değerler kümesinden oluşur. Ayrıntılar için MotionEvent referansına bakın.
Bir oyun nesnesinin hareketini, kontrol çubuğu girişine göre doğru şekilde oluşturmak için MotionEvent nesneleri tarafından sağlanan geçmiş bilgilerini kullanabilirsiniz.
Aşağıdaki yöntemleri kullanarak mevcut ve geçmiş değerleri alabilirsiniz:
getAxisValue()getHistoricalAxisValue()getHistorySize()(joystick etkinliğindeki geçmiş nokta sayısını bulmak için)
Aşağıdaki snippet'te, onGenericMotionEvent() geri çağırma işlevini geçersiz kılarak joystick girişini nasıl işleyebileceğiniz gösterilmektedir. Öncelikle bir eksenin geçmiş değerlerini, ardından mevcut konumunu işlemelisiniz.
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)
}
}
}
Java
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);
}
}
Çubuk girişini kullanmadan önce çubuğun ortalanıp ortalanmadığını belirlemeniz ve ardından eksen hareketlerini buna göre hesaplamanız gerekir. Joystick'lerde genellikle düz bir alan bulunur. Bu alan, eksenin ortalanmış olarak kabul edildiği (0,0) koordinatına yakın bir değer aralığıdır. Android tarafından bildirilen eksen değeri düz alanın içindeyse kontrol cihazını dinlenme modunda (yani her iki eksen boyunca hareketsiz) kabul etmeniz gerekir.
Snippet'te, her eksen boyunca hareketi hesaplayan bir yardımcı yöntem gösterilmektedir. Bu yardımcıyı, aşağıdaki örnekte daha ayrıntılı olarak açıklanan processJoystickInput() yönteminde çağırırsınız:
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
}
Java
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;
}
Tüm bunları bir araya getirdiğimizde, oyununuzda joystick hareketlerini şu şekilde işleyebilirsiniz:
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
}
Java
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
}
Tek bir kontrol çubuğunun ötesinde daha gelişmiş özelliklere sahip oyun kumandalarını desteklemek için aşağıdaki en iyi uygulamaları izleyin:
- Çift kontrol çubuğunu kullanma Birçok oyun kumandasında hem sol hem de sağ analog çubuk bulunur. Android, sol çubuk için yatay hareketleri
AXIS_Xetkinlikleri, dikey hareketleri iseAXIS_Yetkinlikleri olarak bildirir. Android, sağ çubuk için yatay hareketleriAXIS_Zetkinlikleri, dikey hareketleri iseAXIS_RZetkinlikleri olarak bildirir. Kodunuzda her iki kontrol çubuğunu da kullandığınızdan emin olun. - Omuz tetikleyicisine basma işlemlerini yönetin (ve oyununuzun
AXIS_veKEYCODE_BUTTON_etkinlikleriyle çalıştığından emin olun). Bazı kumandalarda sol ve sağ omuz tetikleri bulunur. Bu tetikleyiciler mevcut olduğundaAXIS_*TRIGGERveyaKEYCODE_BUTTON_*2etkinliği ya da her ikisi de yayınlanır. Sol tetik için bu,AXIS_LTRIGGERveKEYCODE_BUTTON_L2olur. Doğru tetikleyici için bu değerlerAXIS_RTRIGGERveKEYCODE_BUTTON_R2olacaktır. Eksen etkinlikleri yalnızca tetikleyici 0 ile 1 arasında bir değer aralığı yayarsa gerçekleşir. Analog çıkışlı bazı kontrol cihazları, eksen etkinliklerine ek olarak düğme etkinlikleri de yayar. Oyunların, tüm yaygın oyun kumandalarıyla uyumlu kalması için hemAXIS_hem deKEYCODE_BUTTON_etkinliklerini desteklemesi gerekir. Ancak bir kumanda her ikisini de bildiriyorsa oyun tarzınız için en mantıklı olan etkinliği tercih edin. Android 4.3 (API düzeyi 18) ve sonraki sürümlerde,AXIS_LTRIGGERüreten bir kontrol cihazı,AXIS_BRAKEekseni için de aynı değeri bildirir. Aynı durumAXIS_RTRIGGERveAXIS_GASiçin de geçerlidir. Android, tüm analog tetikleyici basmalarını 0,0 (serbest bırakılmış) ile 1,0 (tamamen basılmış) arasında normalleştirilmiş bir değerle bildirir. - Belirli davranışlar ve destek, emüle edilmiş ortamlarda farklılık gösterebilir.
Google Play Games gibi emüle edilmiş platformların davranışları, ana makine işletim sisteminin özelliklerine bağlı olarak biraz farklılık gösterebilir. Örneğin, hem
AXIS_hem deKEYCODE_BUTTON_etkinlikleri yayan bazı kontrol cihazları yalnızcaAXIS_etkinlikleri yayar ve bazı kontrol cihazları için destek tamamen eksik olabilir.
Sık kullanılan varyantlar
Android'in oyun kumandaları için sunduğu geniş destek yelpazesi nedeniyle, oyununuzun oyuncu tabanınız arasında hatasız çalıştığını doğrulamak için nasıl geliştirme ve test yapacağınız net olmayabilir. Bu çeşitliliğe rağmen, dünya genelindeki denetleyici üreticilerinin genellikle üç farklı denetleyici tarzına bağlı kaldığını görüyoruz. Bazıları, bu özelliklerden ikisi veya daha fazlası arasında donanım geçişleri sağlar.
Bu sayede, geliştirme ekibinizdeki üç kontrol cihazıyla test yapabilir ve izin verilenler/reddedilenler listelerine başvurmadan oyununuzun oynanabilir olduğundan emin olabilirsiniz.
Sık Kullanılan Kumanda Türleri
En yaygın kumanda stili, popüler oyun konsollarının düzenlerini taklit etme eğilimindedir. Bu, hem düğme etiketleri ve düzen açısından estetik hem de hangi etkinliklerin tetiklendiği açısından işlevseldir. Farklı konsol türleri arasında donanım geçişleri olan kontrol cihazları, gönderdikleri etkinlikleri ve genellikle mantıksal düğme düzenlerini bile değiştirir.
Test sırasında, oyununuzun her kategorideki bir kumandayla çalıştığını doğrulamanızı öneririz. Birinci taraf kontrol cihazlarıyla veya popüler üçüncü taraf üreticilerle test etmeyi seçebilirsiniz. Genellikle en popüler kontrol cihazlarını yukarıdaki tanıma en iyi şekilde eşleriz.
| Kumanda Türü | Davranışsal Farklılıklar | Etiketleme Varyasyonları |
|---|---|---|
| Xbox tarzı kumandalar
Bunlar genellikle Microsoft Xbox ve Windows* platformu için üretilen denetleyicilerdir. |
Bu kontrol cihazları, İşlem kontrol cihazı girişleri bölümünde belirtilen özellik kümesiyle eşleşir. | Bu kumandalardaki L2/R2 düğmeleri LT/RT olarak etiketlenir. |
| Switch Style Controllers
Bu kumandalar genellikle Nintendo Switch* konsol ailesi için tasarlanır. |
Bu denetleyiciler KeyEvent
KEYCODE_BUTTON_R2
KEYCODE_BUTTON_L2
MotionEvent gönderir. |
Bu kumandalardaki L2/R2 düğmeleri ZL/ZR olarak etiketlenir.
Bu kumandalarda A ve B düğmeleri ile X ve Y düğmeleri de yer değiştirir. Bu nedenle |
| PlayStation Stili Kumandalar
Bu denetleyiciler genellikle Sony PlayStation* konsol ailesi için tasarlanır. |
Bu denetleyiciler, Xbox tarzı denetleyiciler gibi MotionEventlar gönderir ancak tamamen basıldığında Switch tarzı denetleyiciler gibi KeyEventlar da gönderir. |
Bu kumandalar, aksiyon düğmeleri için farklı glifler kullanır. |
* Microsoft, Xbox ve Windows, Microsoft'un tescilli ticari markalarıdır; Nintendo Switch, Nintendo of America Inc. şirketinin tescilli ticari markasıdır; PlayStation, Sony Interactive Entertainment Inc. şirketinin tescilli ticari markasıdır.
Açıklığa kavuşturma tetikleme düğmeleri
Bazı kontrol cihazları AXIS_LTRIGGER ve AXIS_RTRIGGER, bazıları KEYCODE_BUTTON_L2 ve KEYCODE_BUTTON_R2, bazıları ise donanım özelliklerine bağlı olarak bu etkinliklerin tümünü gönderir. Bu etkinliklerin tümünü destekleyerek uyumluluğu en üst düzeye çıkarın.
AXIS_LTRIGGER gönderen tüm denetleyiciler AXIS_BRAKE de gönderir. Benzer şekilde, yarış direksiyonları ile normal oyun denetleyicileri arasındaki uyumluluğu en üst düzeye çıkarmak için AXIS_RTRIGGER ve AXIS_GAS de gönderilir. Bu durum genellikle sorunlara neden olmaz ancak tuş yeniden eşleme ekranları gibi özelliklere dikkat edin.
| Tetikleyici | MotionEvent |
KeyEvent |
|---|---|---|
| Sol tetikleyici | AXIS_LTRIGGERAXIS_BRAKE
|
KEYCODE_BUTTON_L2
|
| Sağ Tetikleyici | AXIS_RTRIGGERAXIS_GAS
|
KEYCODE_BUTTON_R2
|
Oyununuzun mümkün olduğunca çok sayıda kumandayla uyumluluğunu korumak için hem KeyEvent hem de MotionEvent işleyebildiğini ve etkinliklerin yinelenmediğini doğrulamanız gerekir.
Desteklenen kumandalar
Test sırasında, oyununuzun her kategorideki bir kumandayla çalıştığını doğrulamanızı öneririz.
- Xbox Tarzı
- Nintendo Switch Stili
- PlayStation Stili
Birinci taraf kontrol cihazlarıyla veya popüler üçüncü taraf üreticilerle test yapabilirsiniz. Genellikle en popüler kontrol cihazlarını tanıma olabildiğince yakın bir şekilde eşleriz.