Tay điều khiển trò chơi được trang bị các tính năng bổ sung giúp cải thiện đáng kể khả năng tương tác và mức độ nhập vai của người chơi. Các chức năng xúc giác, cảm biến chuyển động và ánh sáng của tay điều khiển trò chơi trên Android đặc biệt hữu ích trong việc làm sâu sắc và phong phú thêm trải nghiệm chơi trò chơi. Mỗi tính năng đều kích thích các giác quan của người chơi theo cách riêng, thúc đẩy các hoạt động tương tác trực quan và có ý nghĩa hơn trong trò chơi.
Để khai báo rằng ứng dụng của bạn hỗ trợ tay điều khiển trò chơi, hãy thêm tính năng android.hardware.gamepad vào tệp kê khai ứng dụng:
<manifest ...>
...
<uses-feature android:name="android.hardware.gamepad" android:required="false"/>
...
</manifest>
Xúc giác
Tính năng phản hồi xúc giác trong tay điều khiển trò chơi Android là một công nghệ quan trọng, mang lại phản hồi xúc giác chân thực trong quá trình chơi.
Công nghệ xúc giác mang lại cảm giác vật lý cho người dùng thông qua các rung động hoặc chuyển động. Ví dụ: khi xảy ra vụ nổ trong trò chơi, tay điều khiển sẽ rung, giúp người chơi cảm nhận được tác động một cách chân thực. Ngoài ra, các rung động tinh tế có thể được đồng bộ hoá với âm thanh của một nhân vật đang đi bộ hoặc chạy, mang đến trải nghiệm chân thực hơn. Loại phản hồi xúc giác này cho phép người chơi cảm nhận được các sự kiện diễn ra trong trò chơi.
Công nghệ này giúp người chơi đắm chìm tối đa, tăng cường phản ứng cảm xúc và làm phong phú thêm tính linh động của trò chơi. Chế độ cài đặt phản hồi xúc giác trong tay điều khiển trò chơi Android không chỉ mở rộng khả năng sáng tạo cho nhà phát triển trò chơi mà còn mang đến cho người chơi trải nghiệm chơi game chân thực hơn bao giờ hết.
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));
}
}
}
Để sử dụng chế độ rung, bạn cần thiết lập một tính năng và quyền.
<manifest ...>
...
<uses-permission android:name="android.permission.VIBRATE"/>
...
</manifest>
Để biết thêm thông tin, hãy xem
VibratorManager và
Tệp kê khai ứng dụng.
Cảm biến chuyển động
Một trong những công nghệ tiên tiến nhất giúp nâng cao trải nghiệm chơi trò chơi là tay điều khiển trò chơi Android được trang bị cảm biến chuyển động. Công nghệ này phát hiện chính xác các chuyển động vật lý của người dùng và chuyển dữ liệu đó thành các hành động trong trò chơi, mang đến trải nghiệm chơi trò chơi trực quan và sống động hơn. Trong phần giới thiệu này, chúng ta sẽ khám phá cách hoạt động của các tính năng cảm biến chuyển động trong tay điều khiển trò chơi Android.
Cảm biến chuyển động thường kết hợp con quay hồi chuyển và gia tốc kế để phát hiện chuyển động và hướng của người dùng.
Nó cần triển khai các lớp trình nghe gia tốc và con quay hồi chuyển, đồng thời đăng ký các trình nghe này với trình quản lý cảm biến của bộ điều khiển.
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) {
}
}
Để biết thêm thông tin về Cảm biến chuyển động và SensorEventListener.
Đèn
Chế độ cài đặt màu đèn trên tay điều khiển trò chơi Android giúp tăng thêm trải nghiệm đắm chìm vào trò chơi thông qua các yếu tố hình ảnh.
Tính năng màu đèn sử dụng đèn LED tích hợp trong tay điều khiển để hiển thị nhiều màu sắc, phản hồi linh hoạt theo các tình huống chơi trò chơi khác nhau. Ví dụ: đèn có thể nhấp nháy màu đỏ khi sức khoẻ của người chơi ở mức nguy kịch hoặc phát sáng màu xanh lục khi hoàn thành một nhiệm vụ cụ thể, cung cấp thông tin phản hồi trực quan dựa trên các sự kiện trong trò chơi. Những chế độ cài đặt màu sáng này giúp tăng mức độ tương tác của người dùng, tăng thêm sự hồi hộp và niềm vui khi chơi trò chơi, đồng thời giúp người chơi đắm chìm hoàn toàn vào thế giới trò chơi.
Các tính năng màu sáng trong tay điều khiển trò chơi Android không chỉ đơn thuần là để trang trí mà còn đóng vai trò quan trọng trong việc thiết lập tâm trạng của trò chơi và cải thiện trải nghiệm người dùng.
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());
}
}
}
}
}
Để sử dụng đèn của tay điều khiển, hãy khai báo tính năng tay điều khiển trò chơi và quyền LIGHTS trong tệp kê khai:
<manifest ...>
...
<uses-permission android:name="android.permission.LIGHTS" />
...
</manifest>
Để biết thêm thông tin về LightsManager và Tệp kê khai ứng dụng.
Bàn di chuột của bộ điều khiển
Một số tay điều khiển trò chơi có bàn di chuột có thể dùng cho nhiều hành động trong trò chơi, chẳng hạn như di chuyển trong trình đơn hoặc điều khiển nhân vật trong trò chơi theo cách trực quan hơn.
Tay điều khiển trò chơi có bàn di chuột tích hợp giúp bạn điều khiển thiết bị trực tiếp trên Android. Khi chạm vào bàn di chuột, con trỏ chuột sẽ xuất hiện trên màn hình, cho phép bạn điều hướng một cách trực quan như khi dùng chuột.