שלטי משחק מצוידים בתכונות נוספות שמשפרות באופן משמעותי את האינטראקציה של השחקנים ואת חוויית המשחק. הפונקציות של בקרים למשחקי Android, כמו משוב הפטי, חיישני התנועה והתאורה, עוזרות להעמיק את חוויית המשחק ולשפר אותה. כל תכונה מעוררת את החושים של השחקן בצורה ייחודית, ומעודדת אינטראקציות משמעותיות ואינטואיטיביות יותר במשחק.
מגע
תכונת המשוב ההפטי בשלטים למשחקי Android היא טכנולוגיה חשובה שמספקת משוב מישוש מציאותי במהלך המשחק.
טכנולוגיית משוב מישוש מספקת למשתמש תחושות פיזיות באמצעות רעידות או תנועות. לדוגמה, כשמתרחש פיצוץ במשחק, הבקר רוטט ומאפשר לשחקן להרגיש את ההשפעה בצורה מציאותית. בנוסף, אפשר לסנכרן רטט עדין עם הצליל של דמות שהולכת או רצה, וכך ליהנות מחוויה מציאותית יותר. סוג המשוב הזה מאפשר לשחקנים להרגיש פיזית אירועים שונים שמתרחשים במשחק.
הטכנולוגיה הזו ממקסמת את חוויית המשחק של השחקנים, מגבירה את התגובות הרגשיות ומעשירה את הדינמיקה של המשחק. הגדרות המשוב המישוש בבקרי משחקים ל-Android לא רק מרחיבות את האפשרויות היצירתיות למפתחי משחקים, אלא גם מספקות לשחקנים חוויית משחק מציאותית יותר מאי פעם.
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));
}
}
}
כדי להשתמש ברטט, צריך להגדיר תכונה והרשאה.
<application ...>
...
<uses-feature android:name="android.hardware.gamepad" android:required="true"/>
<uses-permission android:name="android.permission.VIBRATE"/>
...
</application>
מידע נוסף על
VibratorManager ועל
מניפסט האפליקציה
חיישני תנועה
אחת מהטכנולוגיות החדשניות ביותר שמשפרות את חוויית הגיימינג היא שלט Android למשחקים שמצויד בחיישן תנועה. הטכנולוגיה הזו מזהה במדויק את התנועות הפיזיות של המשתמשים ומתרגמת את הנתונים האלה לפעולות במשחק, וכך מספקת חוויית גיימינג אינטואיטיבית וסוחפת יותר. במאמר הזה נסביר איך פועלות התכונות של חיישן התנועה בבקרי משחקים של Android.
חיישני תנועה בדרך כלל כוללים ג'ירוסקופים ומדי תאוצה כדי לזהות את התנועות והכיוונים של המשתמשים.
צריך להטמיע מחלקות של האזנה למד תאוצה ולג'ירוסקופ, ולרשום את האזנות האלה במנהל החיישנים של הבקר.
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) {
}
}
מידע נוסף על חיישני תנועה ועל SensorEventListener
אורות
ההגדרות של צבע האור בבקרים למשחקי Android מוסיפות מימד חדש של חוויית משחק סוחפת באמצעות רכיבים חזותיים.
התכונה 'צבע התאורה' משתמשת בנורות LED מובנות בבקר כדי להציג צבעים שונים, שמשתנים באופן דינמי בהתאם לתרחישי משחק שונים. לדוגמה, האורות יכולים להבהב באדום כשמצב הבריאות של השחקן קריטי, או לזהור בירוק בסיום משימה ספציפית, וכך לספק משוב חזותי על סמך אירועים במשחק. הגדרות הצבע הבהיר האלה מעודדות את המשתמשים להמשיך לשחק, מגבירות את המתח וההנאה מהמשחק ועוזרות לשחקנים לחוות את עולם המשחק בצורה מלאה יותר.
התכונות של הצבעים הבהירים בבקרי משחקים ל-Android לא משמשות רק כקישוט, אלא ממלאות תפקיד חשוב ביצירת האווירה במשחק ובשיפור חוויית המשתמש.
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());
}
}
}
}
}
כדי להשתמש ברטט, צריך להגדיר תכונה והרשאה.
<application ...>
...
<uses-feature android:name="android.hardware.gamepad" android:required="true"/>
<uses-permission android:name="android.permission.LIGHTS" />
...
</application>
מידע נוסף על
LightsManager ועל
מניפסט האפליקציה
לוח מגע של בקר
חלק מבקרי המשחקים כוללים משטח מגע שאפשר להשתמש בו למגוון פעולות במשחק, כמו ניווט בתפריטים או שליטה בדמויות במשחק בצורה אינטואיטיבית יותר.
בקרי משחקים עם משטחי מגע משולבים מאפשרים שליטה ישירה במכשיר ב-Android. כשנוגעים בלוח המגע, מופיע סמן עכבר במסך, וכך אפשר לנווט בצורה אינטואיטיבית כמו עם עכבר.