Controller sind mit zusätzlichen Funktionen ausgestattet, die die Interaktion und das Eintauchen in das Spiel 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 des Spielers auf einzigartige Weise und fördert so sinnvollere und intuitivere Interaktionen im Spiel.
Wenn du deklarieren möchtest, dass deine App Controller unterstützt, füge das Feature android.hardware.gamepad dem App-Manifest hinzu:
<manifest ...>
...
<uses-feature android:name="android.hardware.gamepad" android:required="false"/>
...
</manifest>
Haptik
Die Haptikfunktion in Android-Controllern ist eine entscheidende Technologie, die während des Spiels ein realistisches haptisches Feedback bietet.
Die Haptiktechnologie vermittelt dem Nutzer durch Vibrationen oder Bewegungen physische Empfindungen. Wenn beispielsweise im Spiel eine Explosion auftritt, vibriert der Controller, sodass der Spieler die Auswirkungen realistisch spüren kann. Darüber hinaus können subtile Vibrationen mit dem Geräusch eines Charakters synchronisiert werden, der geht oder rennt, um ein lebensechteres Erlebnis zu bieten. Durch diese Art von haptischem Feedback können Spieler verschiedene Ereignisse im Spiel physisch spüren.
Diese Technologie maximiert das Eintauchen in das Spiel, verstärkt emotionale Reaktionen und bereichert die Dynamik des Spiels. Die Haptikeinstellungen 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));
}
}
}
Wenn du die Vibrationsfunktion verwenden möchtest, musst du ein Feature und eine Berechtigung festlegen.
<manifest ...>
...
<uses-permission android:name="android.permission.VIBRATE"/>
...
</manifest>
Weitere Informationen zu
VibratorManager und
zum App-Manifest.
Bewegungssensoren
Eine der innovativsten Technologien zur Verbesserung des Spielerlebnisses ist der mit Bewegungssensoren ausgestattete Android-Controller. Diese Technologie erkennt die physischen Bewegungen der Nutzer genau und übersetzt diese Daten in Aktionen im Spiel, wodurch ein intuitiveres und immersiveres Spielerlebnis entsteht. In dieser Einführung erfährst du, wie die Bewegungssensorfunktionen in Android-Controllern funktionieren.
Bewegungssensoren enthalten in der Regel Gyroskope und Beschleunigungsmesser, um die Bewegungen und Ausrichtungen der Nutzer zu erkennen.
Es müssen Klassen für Beschleunigungs- und Gyroskopsensoren implementiert und diese Sensoren 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-Controllern verleihen dem Gameplay durch visuelle Elemente eine neue Dimension.
Die Funktion für die Lichtfarbe nutzt die integrierten LED-Leuchten im Controller, um verschiedene Farben anzuzeigen, die dynamisch auf unterschiedliche Spielszenarien reagieren. Die Lichter blinken beispielsweise rot, wenn die Gesundheit des Spielers kritisch ist, oder leuchten grün, wenn eine bestimmte Mission abgeschlossen ist. So wird visuelles Feedback basierend auf In-Game-Ereignissen gegeben. Diese Einstellungen für die Lichtfarbe vertiefen das Nutzer-Engagement, erhöhen die Spannung und den Spaß am Spiel und helfen Spielern, noch tiefer in die Spielwelt einzutauchen.
Die Funktion für die Lichtfarbe in Android-Controllern dient nicht nur als Dekoration, sondern spielt 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-Lichter verwenden möchtest, deklariere das Gamepad-Feature und die Berechtigung LIGHTS im Manifest:
<manifest ...>
...
<uses-permission android:name="android.permission.LIGHTS" />
...
</manifest>
Weitere Informationen zu
LightsManager und
zum App-Manifest.
Touchpad des Controllers
Einige Controller enthalten ein Touchpad, das für eine Vielzahl von In-Game-Aktionen verwendet werden kann, z. B. zum Navigieren in Menüs oder zum Steuern von Spielcharakteren auf intuitivere Weise.
Controller mit integrierten Touchpads ermöglichen die direkte Gerätesteuerung auf Android-Geräten. Wenn du das Touchpad berührst, wird ein Mauszeiger auf dem Bildschirm angezeigt, der eine intuitive mausähnliche Navigation ermöglicht.