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.
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.
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.
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.
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.
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.
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:
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:
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.
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:
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.
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.