Android Popping Bubbles Example

This example is a bit simpler than the bouncing ball demo I posted ten days ago. When you tap the screen, a bubble appears. This bubble grows until it pops. Tapping several times makes several bubbles.

Android Bubbles Example from Eric Burke on Vimeo.

Goals:

  • Animate many different objects. In this case, growing circles. There is only one background thread running the “game loop”. It keeps a list of circle positions and sizes. You could easily apply this same concept to any kind of animation.
  • Play a popping sound when each bubble pops.

The pop sounds like crap on the phone, even worse in the video. You can find the original popping sound on freesound.org. I clipped the sound (using Audacity) to make it play faster, I suspect it can be improved with some work.

You can find the source code for BubblesModel.java and BubblesActivity.java on GitHub.

This app still has a serious bug, described in this Android Developer’s Post. Let me know if you know how to fix this!

Aside from that bug, this is not production-ready code. It is pretty sloppy with memory, copying a List of Bubble objects on each iteration of the game loop. I opted for brute force synchronization just to make it work. For a real game, I’d spend more time on fine-tuned locking and sharing objects to minimize garbage collection.

State Capitals is Now Free

After several weeks on the Android Market, my State Capitals application is now free. I made ten sales. Of those ten, two were returned and one person’s credit card didn’t work.

At $2.00 for each of the seven completed sales, my app grossed $14. Subtract 30% for T-Mobile, and I get $9.80. Since I paid $25 to join the market, I am $15.20 in the red.

This is mildly disappointing, but I didn’t really expect to get rich selling state capital flash cards. I suppose I could try reducing the price to $0.99, but this feels like a dead end. I’d rather focus on game programming…and thus begins my next wild-goose chase.

Android Bouncing Ball Demo

I just added a new demo to my Android Game Examples project. This sample reacts to the accelerometer to control a ball. As you rotate the screen, the ball falls towards the earth. When it bounces off the edge of the screen, the phone vibrator kicks in for a few milliseconds.

Android Bouncing Ball on G1 from Eric Burke on Vimeo.

I’m doing this to learn how to write games. The source code demonstrates a few things:

  • Using the phone’s accelerometer
  • Activating the phone’s vibrator
  • Simulating gravity and acceleration
  • Painting graphics using Android’s SurfaceView
  • Writing a super simple “game loop” that updates physics in a background thread safely

JavaFX Fail

JavaFX never seems to work for me. I assumed it was because I use a Mac, but developers assure me the examples work on Leopard. Not my Leopard, apparently.

Step 1

Click the Launch button at this page. This is on Leopard with Firefox version 3.0.7.

Step 2

Receive error.

Step 3

The details:

This happened to me the other day on a completely different web site with a similar kind of example. The error message — Server response code: 500 — makes it look like the problem is on Sun’s end.

Not good enough.

UPDATE

Now it works. This makes me believe the frequent errors I see are on Sun’s servers.

Android Sensors

Android devices like the G1 phone support different sensors. Tonight I wrote some code that reports which sensors your Android device supports. Unfortunately, the emulator supports none:

When I run this on my G1, the program reports true for these sensors:

  • Accelerometer
  • Magnetic Field
  • Orientation
  • Orientation Raw
  • Tricorder (not really)

Sample Code

First, grab the SensorManager:

SensorManager sensorMgr = (SensorManager)     context.getSystemService(Context.SENSOR_SERVICE);

Next, get a list of supported sensors:

int sensorIds = sensorMgr.getSensors();

And finally, test if the device supports the sensor your application needs:

boolean deviceSupportsAccelerometer =   (sensorIds & SENSOR_ACCELEROMETER) == SENSOR_ACCELEROMETER;

Note that SENSOR_ACCELEROMETER is a constant in the SensorManager class.

The Complete Example

My SensorListAdapter produces the screen shown above. The complete project is available on GitHub.

Android Accelerometer

If you follow me on Twitter (@burke_eric), you may have seen me commenting on accelerometer problems with my G1 phone. In the Labyrinth Lite game, the ball always pulls hard to the right, even after calibration. See this video:

Android G1 Accelerometer from Eric Burke on Vimeo.

I initially thought my phone was defective, because the same game works for other people. But another game, Papi Jump, works fine after calibration. Before calibration, that game also pulls hard to the right.

Accessing the Accelerometer

You access the accelerometer via the SensorManager:

public class Accel extends Activity implements SensorListener { ...   SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);   boolean accelSupported = sensorMgr.registerListener(this,         SENSOR_ACCELEROMETER,         SENSOR_DELAY_UI); ... }

That boolean result is true if the device supports the requested sensor, so it returns false on the emulator and true on the G1 phone.

The SensorListener has two methods: onAccuracyChanged(...) and onSensorChanged(...). My example updates the GUI whenever the sensor changes.

Disclaimer: if you update the GUI on every single event, your application will slow down, the garbage collector will kick in repeatedly, and your app will probably crash. The events from the sensor arrive very fast, faster than the GUI can display. If you check out the complete code, you’ll see I intentionally slow down the GUI updates to once every 100 milliseconds.

Calibration

The screen shot illustrates the “problem” with my phone and the Labyrinth Lite game. The X, Y, and Z values constantly change. When the phone rests on a level surface, X and Y should be around zero. On my phone, however, X is approximately 0.83.

My application stores three values representing the calibration. When you click the Calibrate button, I store the negative X, Y, and Z values in three variables: cx, cy, and cz. Those are the numbers shown in parenthesis. When I display the values for X, Y, and Z, I simply add cx, cy, and cz to the current sensor readings.

Papi Jump and Labyrinth

The Papi Jump game seems to calibrate just fine. I suspect they do exactly what I do: detect how far out of whack the phone’s sensor is, and apply that delta to the current sensor readings.

For whatever reason, Labyrinth fails to calibrate enough on my phone. I believe this is a bug in their application. Perhaps the phones they test with do not require as much calibration as my phone. I have read reports from several people who say Labyrinth works on their phones, and it works on my wife’s G1 as well.

G1 Tolerance?

My phone sensor clearly works, it just requires around -0.83 X-axis adjustment. Is this within acceptable tolerance? I do not know.

I do know, however, that game developers cannot assume all Android hardware is perfectly calibrated. Games like Labyrinth need to expect a wider range of hardware and adjust accordingly. Papi Jump does it, and my simple demo is able to calibrate with a trivial subtraction.

Source Code

The complete source code is available in my Android Game Examples project on GitHub.

Ban Software Patents

Remember in 2006 when patent troll Firestar sued Red Hat for patent 6,101,502?

These patents are bullshit.

On one side, you have an object model. On the other, you have a relational database. When programmers must bridge two different data models, we eventually write little code generators to help us automate the conversion and avoid mundane boilerplate code. In this case, the conversion is called ORM, or Object-Relational-Mapping. The concept is obvious, and is the kind of things programmers do all the time.

Unfortunately, people can patent these obvious ideas and sue each other, punishing companies and individuals who have the audacity to create successful products.

Now, another troll is suing Red Hat for patent 6,163,776. Guess what this patent is for? Yep, just like the last one, this is another ORM patent.

As far as I can tell, both of these patents cover the exact same technology. If the concept of ORM was unique — and it is not — there still shouldn’t be two patents for the exact same thing.