Gamecontroller sind mit zusätzlichen Funktionen ausgestattet, die die Interaktion und das Eintauchen in die Spielwelt deutlich verbessern. Die Haptik, Bewegungssensoren und Lichtfunktionen von Android-Gamecontrollern tragen besonders dazu bei, das Spielerlebnis zu intensivieren und zu bereichern. Jede Funktion stimuliert die Sinne des Spielers auf einzigartige Weise und ermöglicht so sinnvollere und intuitivere Interaktionen im Spiel.
Haptik
Die Haptikfunktion in Android-Controllern ist eine wichtige Technologie, die während des Spiels für realistisches taktiles Feedback sorgt.
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 eines Charakters synchronisiert werden, der geht oder rennt, um ein noch realistischeres Erlebnis zu bieten. Durch diese Art von haptischem Feedback können Spieler verschiedene Ereignisse im Spiel physisch spüren.
Diese Technologie maximiert das Eintauchen der Spieler in die Spielwelt, verstärkt emotionale Reaktionen und bereichert die Dynamik des Spiels. Die Haptik-Einstellungen in Android-Gamecontrollern 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));
}
}
}
Für die Vibrationsfunktion werden ein Feature und eine Berechtigung festgelegt.
<application ...>
...
<uses-feature android:name="android.hardware.gamepad" android:required="true"/>
<uses-permission android:name="android.permission.VIBRATE"/>
...
</application>
Weitere Informationen zu VibratorManager
Bewegungssensoren
Eine der innovativsten Technologien, die das Spielerlebnis verbessern, ist der Android-Controller mit Bewegungssensor. Diese Technologie erkennt die physischen Bewegungen von Nutzern präzise und setzt diese Daten in Aktionen im Spiel um. So wird ein intuitiveres und intensiveres Spielerlebnis ermöglicht. In dieser Einführung erfahren Sie, wie die Bewegungssensorfunktionen in Android-Gamecontrollern funktionieren.
Bewegungssensoren enthalten in der Regel Gyroskope und Beschleunigungsmesser, um die Bewegungen und Ausrichtungen von Nutzern zu erkennen.
Dazu müssen Beschleunigungs- und Gyroskop-Listener-Klassen implementiert und diese Listener beim Sensormanager des Controllers registriert werden.
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-Gamecontrollern sorgen durch visuelle Elemente für eine neue Dimension des Eintauchens in das Gameplay.
Bei der Funktion „Lichtfarbe“ werden die im Controller integrierten LEDs verwendet, um verschiedene Farben anzuzeigen, die dynamisch auf unterschiedliche Spielszenarien reagieren. Die Beleuchtung kann beispielsweise rot blinken, wenn die Gesundheit des Spielers kritisch ist, oder grün leuchten, wenn eine bestimmte Mission abgeschlossen wurde. So wird visuelles Feedback basierend auf In-Game-Ereignissen gegeben. Diese Einstellungen für die Lichtfarbe steigern das Nutzer-Engagement, erhöhen die Spannung und den Spaß am Spiel und helfen den Spielern, tiefer in die Spielwelt einzutauchen.
Die Lichtfarbenfunktionen in Android-Gamecontrollern dienen nicht nur dekorativen Zwecken, sondern spielen eine wichtige Rolle bei der Stimmung des Spiels und der Verbesserung der Nutzerfreundlichkeit.
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());
}
}
}
}
}
Für die Vibrationsfunktion werden ein Feature und eine Berechtigung festgelegt.
<application ...>
...
<uses-feature android:name="android.hardware.gamepad" android:required="true"/>
<uses-permission android:name="android.permission.LIGHTS" />
...
</application>
Weitere Informationen zu LightsManager
Touchpad des Controllers
Einige Gamecontroller haben ein Touchpad, das für verschiedene In-Game-Aktionen verwendet werden kann, z. B. zum Navigieren in Menüs oder zum intuitiveren Steuern von Spielfiguren.
Gamecontroller mit integrierten Touchpads ermöglichen die direkte Gerätesteuerung auf Android-Geräten. Durch Berühren des Touchpads wird ein Mauszeiger auf dem Bildschirm angezeigt, der eine intuitive mausähnliche Navigation ermöglicht.