Fitur pengontrol tambahan

Controller game dilengkapi dengan fitur tambahan yang meningkatkan interaksi dan imersi pemain secara signifikan. Fungsi haptik, sensor gerak, dan cahaya pengontrol game Android sangat berperan dalam memperdalam dan memperkaya pengalaman bermain game. Setiap fitur secara unik merangsang indra pemain, sehingga mendorong interaksi yang lebih bermakna dan intuitif dalam game.

Untuk menyatakan bahwa aplikasi Anda mendukung pengontrol game, tambahkan fitur android.hardware.gamepad ke manifes aplikasi Anda:

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

Sentuhan

Fitur haptik di pengontrol game Android adalah teknologi penting yang memberikan respons sentuh yang realistis selama gameplay.

Teknologi haptik memberikan sensasi fisik kepada pengguna melalui getaran atau gerakan. Misalnya, saat terjadi ledakan dalam game, pengontrol akan bergetar, sehingga pemain dapat merasakan dampaknya secara realistis. Selain itu, getaran halus dapat disinkronkan dengan suara karakter yang sedang berjalan atau berlari, sehingga menawarkan pengalaman yang lebih nyata. Jenis respons haptik ini memungkinkan pemain merasakan secara fisik berbagai peristiwa yang terjadi dalam game.

Teknologi ini memaksimalkan imersi pemain, memperkuat respons emosional, dan memperkaya dinamika game. Setelan haptik di pengontrol game Android tidak hanya memperluas kemungkinan kreatif bagi developer game, tetapi juga memberikan pengalaman bermain game yang lebih realistis kepada pemain.

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

Untuk menggunakan getaran, aplikasi menetapkan fitur dan izin.

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

Untuk mengetahui informasi selengkapnya tentang VibratorManager dan Manifes aplikasi.

Sensor gerakan

Salah satu teknologi paling inovatif yang meningkatkan pengalaman gameplay adalah pengontrol game Android yang dilengkapi sensor gerak. Teknologi ini mendeteksi secara akurat gerakan fisik pengguna dan menerjemahkan data tersebut menjadi tindakan dalam game, sehingga memberikan pengalaman bermain game yang lebih intuitif dan imersif. Dalam pengantar ini, kita akan mempelajari cara kerja fitur sensor gerak di pengontrol game Android.

Sensor gerak biasanya menggabungkan giroskop dan akselerometer untuk mendeteksi gerakan dan orientasi pengguna.

Aplikasi ini perlu menerapkan class pemroses akselerasi dan giroskop serta mendaftarkan pemroses ini dengan pengelola sensor pengontrol.

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

Untuk mengetahui informasi selengkapnya tentang Sensor gerakan dan SensorEventListener.

Lampu

Setelan warna lampu pada controller game Android menambahkan dimensi baru yang imersif ke gameplay melalui elemen visual.

Fitur warna cahaya memanfaatkan lampu LED bawaan di pengontrol untuk menampilkan berbagai warna, yang merespons secara dinamis berbagai skenario game. Misalnya, lampu dapat berkedip merah saat kesehatan pemain kritis atau bercahaya hijau setelah menyelesaikan misi tertentu, memberikan masukan visual berdasarkan peristiwa dalam game. Setelan warna terang ini memperdalam engagement pengguna, meningkatkan ketegangan dan keseruan game, serta membantu pemain lebih tenggelam dalam dunia game.

Fitur warna lampu di controller game Android memiliki fungsi lebih dari sekadar tujuan dekoratif—fitur ini berperan penting dalam mengatur suasana game dan meningkatkan pengalaman pengguna.

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

Untuk menggunakan lampu pengontrol, deklarasikan fitur gamepad dan izin LIGHTS dalam manifes Anda:

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

Untuk mengetahui informasi selengkapnya tentang LightsManager dan Manifes aplikasi.

Touchpad pengontrol

Beberapa pengontrol game menyertakan touchpad yang dapat digunakan untuk berbagai tindakan dalam game, seperti menavigasi menu atau mengontrol karakter game dengan cara yang lebih intuitif.

Touchpad pada pengontrol game
Gambar 1. Touchpad di pengontrol game.

Controller game dengan touchpad terintegrasi menawarkan kontrol perangkat langsung di Android. Menyentuh touchpad akan menghasilkan kursor mouse di layar, sehingga memungkinkan navigasi intuitif seperti mouse.