Gamecontroller sind mit zusätzlichen Funktionen ausgestattet, die die Interaktion und Immersion der Spieler erheblich verbessern. Die Haptik, die Bewegungssensoren und die Lichtfunktionen von Android-Controllern tragen besonders dazu bei, das Spielerlebnis zu vertiefen und zu bereichern. Jede Funktion stimuliert die Sinne der Spieler auf einzigartige Weise und ermöglicht so sinnvollere und intuitivere Interaktionen im Spiel.
Wenn du angeben möchtest, dass deine App Controller unterstützt, füge deinem App-Manifest die Funktion android.hardware.gamepad hinzu:
<manifest ...>
...
<uses-feature android:name="android.hardware.gamepad" android:required="false"/>
...
</manifest>
Haptik
Die Haptikfunktion in Android-Controllern ist eine wichtige Technologie, die während des Gameplays realistisches haptisches Feedback liefert.
Haptische Technologie vermittelt dem Nutzer durch Vibrationen oder Bewegungen physische Empfindungen. Wenn im Spiel beispielsweise eine Explosion stattfindet, vibriert der Controller, sodass der Spieler den Aufprall realistisch spüren kann. Außerdem können subtile Vibrationen mit dem Geräusch einer gehenden oder laufenden Figur synchronisiert werden, um ein lebensechteres Erlebnis zu bieten. Diese Art von haptischem Feedback ermöglicht es Spielern, verschiedene Ereignisse im Spiel physisch zu spüren.
Diese Technologie maximiert die Immersion der Spieler, verstärkt emotionale Reaktionen und bereichert die Dynamik des Spiels. Die Einstellungen für haptisches Feedback in Android-Controllern erweitern nicht nur die kreativen Möglichkeiten für Spieleentwickler, sondern bieten Spielern auch ein realistischeres Spielerlebnis als je zuvor.
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));
}
}
}
Damit die Vibration verwendet werden kann, werden eine Funktion und eine Berechtigung festgelegt.
<manifest ...>
...
<uses-permission android:name="android.permission.VIBRATE"/>
...
</manifest>
Weitere Informationen zu
VibratorManager und
App-Manifest.
Bewegungssensoren
Eine der innovativsten Technologien zur Verbesserung des Gameplays sind Android-Gamecontroller mit Bewegungssensoren. Diese Technologie erkennt die physischen Bewegungen der Nutzer genau und setzt diese Daten in Aktionen im Spiel um. Das sorgt für ein intuitiveres und immersiveres Spielerlebnis. In dieser Einführung erfahren Sie, wie die Bewegungssensorfunktionen in Android-Controllern funktionieren.
Bewegungssensoren enthalten in der Regel Gyroskope und Beschleunigungsmesser, um die Bewegungen und Ausrichtungen von Nutzern zu erkennen.
Sie muss Listener-Klassen für Beschleunigung und Gyroskop implementieren und diese Listener beim Sensor-Manager des Controllers registrieren.
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) {
}
}
Weitere Informationen zu Bewegungssensoren und SensorEventListener.
Lichter
Die Einstellungen für die Lichtfarbe auf Android-Controllern verleihen dem Gameplay durch visuelle Elemente eine neue Dimension der Immersion.
Die Funktion für die Lichtfarbe nutzt integrierte LED-Leuchten im Controller, um verschiedene Farben anzuzeigen, die dynamisch auf unterschiedliche Spielszenarien reagieren. Beispielsweise können die Lichter rot blinken, wenn die Gesundheit des Spielers kritisch ist, oder grün leuchten, wenn eine bestimmte Mission abgeschlossen wurde. So erhalten Spieler visuelles Feedback basierend auf Ereignissen im Spiel. Diese Einstellungen für die Lichtfarbe vertiefen das Nutzer-Engagement, erhöhen die Spannung und den Spielspaß und helfen den Spielern, noch besser in die Spielwelt einzutauchen.
Die Lichtfarbenfunktionen von Android-Controllern dienen nicht nur der Dekoration, sondern spielen auch eine wichtige Rolle bei der Stimmung des Spiels und der Verbesserung der Nutzerfreundlichkeit.
Kotlin
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());
}
}
}
}
}
Wenn du die Controller-Leuchten verwenden möchtest, deklariere die Gamepad-Funktion und die Berechtigung LIGHTS in deinem Manifest:
<manifest ...>
...
<uses-permission android:name="android.permission.LIGHTS" />
...
</manifest>
Weitere Informationen zu
LightsManager und
App-Manifest.
Touchpad des Controllers
Einige Gamecontroller haben ein Touchpad, das für verschiedene Aktionen im Spiel verwendet werden kann, z. B. zum Navigieren in Menüs oder zum intuitiveren Steuern von Spielfiguren.
Gamecontroller mit integrierten Touchpads bieten eine direkte Gerätesteuerung unter Android. Wenn du das Touchpad berührst, wird ein Mauszeiger auf dem Bildschirm angezeigt, mit dem du intuitiv wie mit einer Maus navigieren kannst.