Ek kumanda özellikleri

Oyun kumandaları, oyuncu etkileşimini ve oyun deneyimini önemli ölçüde iyileştiren ek özelliklerle donatılmıştır. Android oyun kumandalarının dokunma, hareket sensörleri ve ışık işlevleri, oyun deneyimini derinleştirip zenginleştirmede özellikle etkilidir. Her özellik, oyuncunun duyularını benzersiz bir şekilde uyararak oyun içinde daha anlamlı ve sezgisel etkileşimler sağlar.

Uygulamanızın oyun kumandalarını desteklediğini beyan etmek için uygulama manifestinize android.hardware.gamepad özelliğini ekleyin:

<manifest ...>
  ...
  <uses-feature android:name="android.hardware.gamepad" android:required="false"/>
  ...
</manifest>

Dokunma teknolojisi

Android oyun kumandalarındaki dokunsal geri bildirim özelliği, oyun sırasında gerçekçi dokunsal geri bildirim sağlayan önemli bir teknolojidir.

Dokunma teknolojisi, titreşimler veya hareketler aracılığıyla kullanıcıya fiziksel hisler verir. Örneğin, oyunda bir patlama olduğunda kumanda titrer ve oyuncunun etkiyi gerçekçi bir şekilde hissetmesini sağlar. Ayrıca, karakterin yürüme veya koşma sesleriyle senkronize edilen hafif titreşimler daha gerçekçi bir deneyim sunar. Bu tür dokunsal geribildirim, oyuncuların oyunda gerçekleşen çeşitli olayları fiziksel olarak hissetmelerini sağlar.

Bu teknoloji, oyuncuların oyuna kendilerini kaptırmasını en üst düzeye çıkarır, duygusal tepkileri güçlendirir ve oyunun dinamiklerini zenginleştirir. Android oyun kumandalarındaki dokunma ayarları, oyun geliştiricilerin yaratıcılıklarını daha fazla kullanmalarına olanak tanımakla kalmaz, aynı zamanda oyunculara her zamankinden daha gerçekçi bir oyun deneyimi sunar.

Kotlin

fun triggerVibrationMultiChannel(
  deviceId: Int, leftIntensity: Int, leftDuration: Int,
  rightIntensity: Int, rightDuration: Int) {
  val inputDevice = InputDevice.getDevice(deviceId)
  val vibratorManager = inputDevice!!.vibratorManager
  if (vibratorManager != null) {
    val vibratorIds = vibratorManager.vibratorIds
    val vibratorCount = vibratorIds.size
    if (vibratorCount > 0) {
      // We have an assumption that game controllers have two vibrators
      // corresponding to a left motor and a right motor, and the left
      // motor will be first.
      updateVibrator(vibratorManager.getVibrator(vibratorIds  [0]), leftIntensity, leftDuration)
      if (vibratorCount > 1) {
        updateVibrator(vibratorManager.getVibrator(vibratorIds[1]), rightIntensity, rightDuration)
      }
    }
  }
}

fun updateVibrator(vibrator: Vibrator?, intensity: Int, duration: Int) {
  if (vibrator != null) {
    if (intensity == 0) {
      vibrator.cancel()
    } else if (duration > 0) {
      vibrator.vibrate(VibrationEffect.createOneShot(duration.toLong(), intensity))
    }
  }
}

Java

public void triggerVibrationMultiChannel(
    int deviceId, int leftIntensity, int leftDuration,
    int rightIntensity, int rightDuration) {

    InputDevice inputDevice = InputDevice.getDevice(deviceId);

    // Check if device exists to avoid NullPointerException
    if (inputDevice == null) {
      return;
    }

    VibratorManager vibratorManager = inputDevice.getVibratorManager();
    if (vibratorManager != null) {
        int[] vibratorIds = vibratorManager.getVibratorIds();
        int vibratorCount = vibratorIds.length;

        if (vibratorCount > 0) {
            // We have an assumption that game controllers have two vibrators
            // corresponding to a left motor and a right motor, and the left
            // motor will be first.
            updateVibrator(vibratorManager.getVibrator(vibratorIds[0]), leftIntensity, leftDuration);

            if (vibratorCount > 1) {
                updateVibrator(vibratorManager.getVibrator(vibratorIds[1]), rightIntensity, rightDuration);
            }
        }
    }
}

public void updateVibrator(Vibrator vibrator, int intensity, int duration) {
    if (vibrator != null) {
        if (intensity == 0) {
            vibrator.cancel();
        } else if (duration > 0) {
            vibrator.vibrate(VibrationEffect.createOneShot. ((long) duration, intensity));
        }
    }
}

Titreşimi kullanmak için bir özellik ve izin ayarlanır.

<manifest ...>
  ...
  <uses-permission android:name="android.permission.VIBRATE"/>
  ...
</manifest>

VibratorManager ve Uygulama manifesti hakkında daha fazla bilgi edinin.

Hareket sensörü

Oyun deneyimlerini geliştiren en yenilikçi teknolojilerden biri, hareket sensörüyle donatılmış Android oyun kumandasıdır. Bu teknoloji, kullanıcıların fiziksel hareketlerini hassas bir şekilde algılayıp bu verileri oyun içindeki eylemlere dönüştürerek daha sezgisel ve sürükleyici bir oyun deneyimi sunar. Bu giriş bölümünde, Android oyun kumandalarındaki hareket sensörü özelliklerinin nasıl çalıştığını inceleyeceğiz.

Hareket sensörleri genellikle kullanıcıların hareketlerini ve yönlerini algılamak için jiroskop ve ivme ölçerlerden yararlanır.

İvme ve jiroskop dinleyici sınıflarını uygulaması ve bu dinleyicileri kumandanın sensör yöneticisine kaydetmesi gerekir.

Kotlin

fun setIntegratedAccelerometerActive(deviceId: Int) {
  val device = InputDevice.getDevice(deviceId)
  val sensorManager = device?.sensorManager
  val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
  if (accelerometer != null) {
    val accelerometerListener =
      GameControllerAccelerometerListener(accelerometer)
    sensorManager.registerListener(
      accelerometerListener, accelerometer,
      SensorManager.SENSOR_DELAY_GAME
    )
  }
}

fun setIntegratedGyroscopeActive(deviceId: Int) {
  val device = InputDevice.getDevice(deviceId)
  val sensorManager = device?.sensorManager
  val gyroscope = sensorManager?.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
  if (gyroscope != null) {
    val gyroscopeListener = GameControllerGyroscopeListener(gyroscope)
    sensorManager.registerListener(
      gyroscopeListener, gyroscope,
      SensorManager.SENSOR_DELAY_GAME
    )
  }
}

class GameControllerAccelerometerListener(private val listenerAccelerometer: Sensor?) :
  SensorEventListener {
  override fun onSensorChanged(event: SensorEvent) {
    if (listenerAccelerometer != null) {
      synchronized(listenerAccelerometer) {
        if (event.sensor == listenerAccelerometer) {
          Log.d("Accelerometer",
            "onSensorChanged " + event.values[0] + ", "
            + event.values[1] + ", " + event.values[2])
        }
      }
    }
  }

  override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
  }
}

class GameControllerGyroscopeListener(private val listenerGyroscope: Sensor?) :
  SensorEventListener {
  override fun onSensorChanged(event: SensorEvent) {
    if (listenerGyroscope != null) {
      synchronized(listenerGyroscope) {
        if (event.sensor == listenerGyroscope) {
          Log.d("Gyroscope",
            "onSensorChanged " + event.values[0] + ", " +
            event.values[1] + ", " + event.values[2])
        }
      }
    }
 }

  override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
  }
}

Java


public void setIntegratedAccelerometerActive(int deviceId) {
    InputDevice device = InputDevice.getDevice(deviceId);
    // Safe handling for null device or sensor manager
    if (device == null) {
      return;
    }
    SensorManager sensorManager = device.getSensorManager();
    if (sensorManager == null) {
      return;
    }

    Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
    if (accelerometer != null) {
      GameControllerAccelerometerListener   accelerometerListener =
          new GameControllerAccelerometerListener(accelerometer);
        sensorManager.registerListener(
          accelerometerListener, accelerometer,
          SensorManager.SENSOR_DELAY_GAME
        );
    }
}

public void setIntegratedGyroscopeActive(int deviceId) {
    InputDevice device = InputDevice.getDevice(deviceId);
    if (device == null) {
        return;
    }
    SensorManager sensorManager = device.getSensorManager();
    if (sensorManager == null) {
        return;
    }
    Sensor gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
    if (gyroscope != null) {
        GameControllerGyroscopeListener gyroscopeListener =
          new GameControllerGyroscopeListener(gyroscope);
        sensorManager.registerListener(
          gyroscopeListener, gyroscope,
          SensorManager.SENSOR_DELAY_GAME
        );
    }
}

public static class GameControllerAccelerometerListener implements SensorEventListener {
    private final Sensor listenerAccelerometer;
    public GameControllerAccelerometerListener(Sensor   listenerAccelerometer) {
        this.listenerAccelerometer = listenerAccelerometer;
    }
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (listenerAccelerometer != null) {
            synchronized (listenerAccelerometer) {
                if (event.sensor == listenerAccelerometer) {
                    Log.d("Accelerometer",
                      "onSensorChanged " + event.values[0] + ", "
                      + event.values[1] + ", " + event.values[2]);
                }
            }
        }
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}

public static class GameControllerGyroscopeListener implements SensorEventListener {
    private final Sensor listenerGyroscope;

    public GameControllerGyroscopeListener(Sensor listenerGyroscope) {
        this.listenerGyroscope = listenerGyroscope;
    }
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (listenerGyroscope != null) {
            synchronized (listenerGyroscope) {
                if (event.sensor == listenerGyroscope) {
                    Log.d("Gyroscope",
                      "onSensorChanged " + event.values[0] +  ", " +
                        event.values[1] + ", " + event.values  [2]);
                }
            }
        }
    }
    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }
}

Hareket sensörleri ve SensorEventListener hakkında daha fazla bilgi

Işıklar

Android oyun kumandalarındaki ışık rengi ayarları, görsel öğeler aracılığıyla oyun deneyimine yeni bir boyut kazandırır.

Işık rengi özelliği, çeşitli renkleri göstermek için kontrol cihazındaki yerleşik LED ışıkları kullanır. Bu renkler, farklı oyun senaryolarına dinamik olarak yanıt verir. Örneğin, oyuncunun canı kritik seviyeye düştüğünde ışıklar kırmızı renkte yanıp sönebilir veya belirli bir görev tamamlandığında yeşil renkte yanarak oyun içi etkinliklere göre görsel geri bildirim sağlayabilir. Bu ışık rengi ayarları, kullanıcı etkileşimini derinleştirir, oyunun heyecanını ve keyfini artırır ve oyuncuların oyun dünyasına daha fazla dalmasına yardımcı olur.

Android oyun kumandalarındaki ışık rengi özellikleri yalnızca dekoratif amaçlı değildir. Oyunun atmosferini belirlemede ve kullanıcı deneyimini iyileştirmede önemli bir rol oynar.

Kotin

fun changeControllerLightColor(deviceId: Int, color: Int) {
  val device = InputDevice.getDevice(deviceId)
  device?.let {
    if (it.sources and InputDevice.SOURCE_JOYSTICK == InputDevice.SOURCE_JOYSTICK) {
      val lightsManager = device.lightsManager
      lightsManager?.let { manager ->
        manager.lights.forEach { light ->
          val stateBuilder = LightState.Builder()
          stateBuilder.setColor(color)
          val requestBuilder = LightsRequest.Builder()
          requestBuilder.addLight(light, stateBuilder.build())
          val lightsSession = lightsManager.openSession()
          lightsSession.requestLights(requestBuilder.build())
        }
      }
    }
  }
}

Java

public void changeControllerLightColor(int deviceId, int  color) {
    InputDevice device = InputDevice.getDevice(deviceId);

    if (device != null) {
      // Check if the device is a joystick.
      // Note: Parentheses are required around the bitwise AND operation in Java
      // because == has higher precedence than &.
        if ((device.getSources() & InputDevice.  SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK) {
            LightsManager lightsManager = device.getLightsManager();

            if (lightsManager != null) {
                for (Light light : lightsManager.getLights()) {
                    LightState.Builder stateBuilder = new   LightState.Builder();
                    stateBuilder.setColor(color);

                    LightsRequest.Builder requestBuilder = new LightsRequest.Builder();
                    requestBuilder.addLight(light, stateBuilder.build());

                    LightsManager.Session lightsSession =   lightsManager.openSession();
                    lightsSession.requestLights(requestBuilder.build());
                }
            }
        }
    }
}

Kumanda ışıklarını kullanmak için manifest dosyanızda oyun kumandası özelliğini ve LIGHTS iznini tanımlayın:

<manifest ...>
  ...
  <uses-permission android:name="android.permission.LIGHTS" />
  ...
</manifest>

LightsManager ve Uygulama manifesti hakkında daha fazla bilgi edinin.

Kumanda dokunmatik alanı

Bazı oyun kumandalarında, menülerde gezinme veya oyun karakterlerini daha sezgisel bir şekilde kontrol etme gibi çeşitli oyun içi işlemler için kullanılabilecek bir dokunmatik alan bulunur.

Oyun kumandasındaki dokunmatik alan
Şekil 1. Oyun kumandasındaki dokunmatik yüzey.

Entegre dokunmatik yüzeylere sahip oyun kumandaları, Android'de doğrudan cihaz kontrolü sağlar. Dokunmatik alana dokunulduğunda ekranda bir fare işaretçisi oluşturulur. Bu sayede fare benzeri sezgisel bir gezinme deneyimi sağlanır.