Sensors – 1

How to Use Android Sensors in Games

In this post, we’re going to learn how to access just one of the multitude of sensors present on an Android device by building a very small game that uses the accelerometer on the device. This game will simply show a red ball on the screen whose motion is tied to the device’s accelerometer. For example, tilting the device will cause the ball to accelerate in the direction of the tilt.

Download the full source code here.

Let’s get started! Create an Android Studio project called SensorsDemo and we’ll leave the defaults as is (but create an Empty Activity). We can go ahead and delete the activity_main.xml file in the layout folder since we’ll be using a custom view that will fill our entire screen and setContentView(...)  has an overload where we can pass in a View object. Also, copy-and-paste the ball from the provided source code’s res/drawable directory to our res/drawable directory. If there isn’t a directory, create one. We’re going to create a custom view that will handle updating our ball.

However, we still have much to do before we can get to the custom View. As a placeholder, let’s just create our BallView private inner class inside MainActivity towards the end of the file like the following.

We’ll populate it with the logic to move the ball, but we first need to declare some top-level members representing our ball’s position, acceleration, and velocity in the x and y directions. We’ll also need members to represent the maximum x and y so we define boundaries restricting the ball’s motion so it doesn’t roll off the screen! Of course, we’ll need a member to be the ball itself as a Bitmap object. Finally, we need a SensorManager object so that we can register and unregister the listener for the accelerometer sensor.

Now that we’ve done this, let’s complete our onCreate(...)  method. Since we’re using the accelerometer, it’s a good idea to keep our app in portrait mode so that the system doesn’t think we want to change orientations if we tilt a bit too much in one direction. We can do this to a call in setRequestedOrientation(...)  method. Then we can create our custom BallView and set the view of our Activity to be the new BallView object. Then we need to grab the our device’s size so that the ball doesn’t roll off of the screen. Finally, we need to instantiate our SensorManager object by grabbing a reference to the system’s sensor manager.

In onStart()  and onStop() , we need to register and unregister our SensorManager, respectively. This is a great place to do this because these Activity lifecycle methods are called before the screen is visible to the user and after the screen has disappeared off the screen, respectively. We need to specify that we need the accelerometer sensor and we’ll need to specify a refresh rate, SENSOR_DELAY_GAME, in our case. Note that we perform our method calls after the call to the superclass in onStart() , but, in onStop() , we perform method calls before the call to the superclass. This is because we’d like to unregister our listener before the system does it’s tasks to free up resources, for example.

This will force us to implement the SensorEventListener2 interface, which will make us implement onSensorChanged(...) , onFlushCompleted(...) , and onAccuracyChanged(...) . We won’t have to do anything in the latter two methods, but the former is the most important since this is where we actually retrieve data from the accelerometer.  To gain a better understanding of why we have positive/negative values in our code, look at the following diagram of the orientation of the sensors with respect to the device.

(Source)

Also, according to the documentation, sensorEvent.values[i]  stores data on our accelerometer, where i is a value from 0 to 2 representing the acceleration in the x, y, and z directions. From the diagram, note that we have to negate our y value, else the ball will just move in one dimension! After we get their values, we need to update our ball’s location. This is a common practice in game development to update the location of all of the entities of the game per frame. In our case, our only entity is the ball, and, since that’s tied to the accelerometer, our “frame” depends on the refresh rate of the sensors, which is still very fast.

Now in our updateBall()  method, we need to change our velocities and calculate how far our ball has moved in that time. Then we need to combine our ball’s current location with the displacement and we now have the ball’s new position! Notice that because of the coordinate axes on the device, we have to actually subtract the delta position from the current position! Feel free to play around with these calculation to make your ball game more or less difficult! We also need to handle the cases where it goes off the screen. We can set the position to be the min or the max depending on how it goes off the screen.

Now we need to code our custom view to actually display the ball on the screen. Since our entire Activity is comprised of the BallView, we can just position the ball on the view and we’re sure that the ball will be on the screen. Note that we are forced to implement the constructor that calls the superclass’s constructor. In our constructor, we need to grab our Bitmap and resize it so it’s the appropriate size for our screen.

When we’re creating a custom view, we have to override a method called onDraw()  since that’s called to draw the view once. However, we don’t just want to draw our ball once, we want to keep refreshing it. We can call an instance method inside View called invalidate() . This will tell the view to call onDraw(...)  again sometime in the future.

This should be all we need to get our app running and using the accelerometer! Here’s what our app looks like running on a physical device.

Sensors – 1

As we move the device, the ball accelerates in the appropriate direction! For those of you that might not have an Android device, we can still use the accelerometer. However, instead of having a physical device, we need to manually connect with the emulator’s console through a client called telnet. If you’re on a Mac or Linux computer, you already have this installed. However, if you’re on Windows, you’ll need to enable it by following this procedure. To simulate the accelerometer, we’ll need to start up our emulator and open up a terminal window. Note the 4-digit number at the top of the emulator’s window. That’s called the port number and we need it to log into the emulator. In the console, type  telnet localhost #### with #### as your emulator’s port number. Now we should see something like Android Console: type 'help' for a list of commands in the console. Now we can type sensor status  to show the status of all of the emulator sensors. We know everything is good if we can see acceleration: enabled.  in the list of sensors. Now if we wanted to change the acceleration, we can run the following command to set the acceleration: sensor set acceleration 0:0:0 or sensor set acceleration 50:50:50 . We can use this to change the acceleration of the emulator and play our game!

Conclusion

In this post, we learned how to access the accelerometer on our device/emulator to build a game using it as well. We built a game that has a ball on the screen whose motion is tied to the accelerometer. When we move the accelerometer, we also move the ball. Even though we only covered the accelerometer, this same approach can be done with different types of sensors as well. Make sure to check out the documentation on how to use the other kinds of sensors!

Published by

Mohit Deshpande

Mohit Deshpande is a professional mobile application developer, contractor, and instructor. He started programming at the age of eleven. During the great mobile revolution, he shifted focus to developing mobile apps with his first Android app running on a Samsung Galaxy S1 running Android 2.1 Eclair. Since then, he has been involved in industry and research. He is a computer science and engineering student at The Ohio State University and works for the Department of Computer Science and Engineering as a researcher. During the university hackathon, he came in second place with an Android app that links a task with a location using a geofence. In what little spare time he has, he plays jazz and rock guitar and performs in the Ohio State Athletic Band on trumpet at various sporting events.

Share this article

  • Ashish

    Hi, Thanks for the great tutorial. I managed to get the ball moving by following the steps but how would it work without using a custom view?

  • Mohit Deshpande

    Hi Ashish! Performing a task like this would be a little difficult without a custom view. You could look into getting a ball rolling with OpenGL. Game developers use it to render their games on mobile devices, and I believe you can integrate sensors with it too. However, it’s fairly complicated with a steep learning curve, which is why I thought a custom view would be easier to understand.

  • ay

    thanks for the tutorial, but how do i make the ball stop at the middle of the screen