- Mastering Android Game Development
- Raul Portales
- 750字
- 2021-07-16 13:59:10
Sensors and InputControllers
Sensors are a common way to control games on smartphones. They work fine when the only controls in the game are left and right (like a car racing game). If you plan to also move up and down, you need to ask the player to do a calibration at the beginning of the game to make it usable. Note that, when you are using only one axis, such calibration is not necessary.
In addition to this, the up and down movement tends to interfere with the sensorLandscape
orientation. So, the use of sensors is not a very good idea for YASS.
Note
Sensors are good controls only in certain cases.
You also have to consider that, while sensors are a replacement for directions, you still need to place the action buttons on the screen—in our case, the fire button.
We are not going to use sensors for YASS but, if you want to make a game that uses them, we will cover the basics.
You need to register a listener for the accelerometer and another one for the magnetic field. You should only listen to the sensors while the game is running, so we will override the life cycle methods to register and unregister sensors accordingly:
private void registerListeners() { SensorManager sm = (SensorManager) mActivity.getSystemService(Activity.SENSOR_SERVICE); sm.registerListener(mAccelerometerChangesListener, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_FASTEST); sm.registerListener(mMagneticChangesListener, sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_FASTEST); } private void unregisterListeners() { SensorManager sm = (SensorManager) mActivity.getSystemService(Activity.SENSOR_SERVICE); sm.unregisterListener(mAccelerometerChangesListener); sm.unregisterListener(mMagneticChangesListener); } @Override public void onStart() { registerListeners(); } @Override public void onStop() { unregisterListeners(); } @Override public void onResume() { registerListeners(); } @Override public void onPause() { unregisterListeners(); }
Note that we are using SensorManager.SENSOR_DELAY_FASTEST
, which means that the sensors will give feedback as fast and as often as they can. This is very important for real-time games.
We are setting objects as listeners. Each listener will just copy the values of the sensor into a local array that we will process later on. For example, in the case of an accelerometer, we will do:
@Override public void onSensorChanged(SensorEvent event) { System.arraycopy(event.values, 0, mLastAccels, 0, 3); }
To obtain the final value, we have to do some calculations. So, we will add a onPreUpdate
method that will be called by the GameEngine
just before calling onUpdate
.
It is important to note that there are some special cases. They are as follows:
- There are devices that lack a magnetic field sensor. In such cases, we can use a simplified version using the value of the accelerometer. Nvidia Shield and specific versions of Nook are some of these devices.
- In all cases, the sensors are related to the default orientation of the device, which can be either landscape or portrait. We have to take this into consideration while processing the values.
All in all, the conversion for the horizontal axis can be done like this:
private double getHorizontalAxis() { if (SensorManager.getRotationMatrix(mRotationMatrix, null, mLastAccels, mLastMagFields)) { if (mRotation == Surface.ROTATION_0) { SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_Y, SensorManager.AXIS_MINUS_X, mRotationMatrix); SensorManager.getOrientation(mRotationMatrix, mOrientation); return mOrientation[1] * DEGREES_PER_RADIAN; } else { SensorManager.getOrientation(mRotationMatrix, mOrientation); return -mOrientation[1] * DEGREES_PER_RADIAN; } } else { // Case for devices which do NOT have magnetic sensors if (mRotation == Surface.ROTATION_0) { return -mLastAccels[0]* 5; } else { return -mLastAccels[1] * -5; } } }
The getHorizontalAxis
code does the following steps:
- Calculates the rotation matrix using the last data from the accelerometer and the magnetic sensor.
- If it returns true, all goes well. Based on the rotation of the device, we decide whether we need to remap the coordinate system or not and then return the orientation that is converted into degrees.
- If it could not be calculated (lack of a magnetic field sensor), the method returns false. We have to rely on an approximation using the accelerometer values. Based on the rotation of the device, we should use one or another axis.
The rotation of the device can be read in the constructor of the InputController
with a single line of code.
mRotation = yassActivity.getWindowManager().getDefaultDisplay().getRotation();
Finally, the onPreUpdate
method:
@Override public void onPreUpdate() { mHorizontalFactor = getHorizontalAxis()/ MAX_ANGLE; if (mHorizontalFactor > 1) { mHorizontalFactor = 1; } else if (mHorizontalFactor < -1) { mHorizontalFactor = -1; } mVerticalFactor = 0; }
The is method just converts the reading (in degrees) into values in the range [-1,1] by using the maximum angle at which we consider it to be fully tilted. I recommend you to play with this constant and start with 30 degrees.
For more information on handling sensors, you can check the official documentation http://developer.android.com/guide/topics/sensors/sensors_overview.html.
- 新編Visual Basic程序設(shè)計(jì)上機(jī)實(shí)驗(yàn)教程
- AngularJS入門(mén)與進(jìn)階
- FuelPHP Application Development Blueprints
- Maven Build Customization
- PHP程序設(shè)計(jì)(慕課版)
- C#完全自學(xué)教程
- Mastering Kotlin
- C語(yǔ)言程序設(shè)計(jì)
- Learn WebAssembly
- 深度強(qiáng)化學(xué)習(xí)算法與實(shí)踐:基于PyTorch的實(shí)現(xiàn)
- FFmpeg入門(mén)詳解:音視頻原理及應(yīng)用
- C程序設(shè)計(jì)案例教程
- C/C++程序員面試指南
- 玩轉(zhuǎn).NET Micro Framework移植:基于STM32F10x處理器
- C++17 By Example