Multi table tennis is a ping pong clone that I developed for the sake of learning game development on the android platform. Right after completing the game I realized that there was something strange going on with it.
The frame rate of the would drop to around 30fps, about 4 days after installation. Uninstalling and reinstalling the game or killing the game process using a task manager didn't seem to work. The only way to temporarily fix the issue was to reboot the android device.
The only possible reason I could come with up with for this behavior was some kind of a strange memory leak. So I carefully reviewed the code and actually found some pieces of code that could produce memory leaks. But fixing these didn't really work. Eventually, after 2 months of random bug fix attempts, I decided to move on.
After an year or so I decided port the code to use a new simple android game library I created and started reordering the code. While doing so I came across the following lines.
float curT, prevT=0, deltaTime;
void onDrawFrame(GL10 gl) {
curT=System.nanoTime(); <- nanoTime() returns a 'long'
deltaTime=curT-prevT;
prevT=curT;
gameScreen.update(deltaTime/1000000);
.
.
.
}
And I realized the careless mistake I had made. Basically I was using a bunch of 'float' variables to store the 'long' value of Sytem.nanoTime() in order to calculate the time elapsed between the previous frame and current one. Java will implicitly convert 'long's to 'float's. But when doing so, the least significant bits(LSBs) that are outside the capacity of 'float's will be discarded.
Now this code will work fine as long as the value returned by nanoTime() is less than the max value a float can hold. As soon as the long value gets past this point there will some information lose.
And thus deltaTime value will be calculated as zero for 'long' values which differ only in the LSBs that are outside the float's range, resulting in drawing a frame which would look exactly the previous frame. This will end up creating a virtual frame rate drop in the game.
This mistake taught me to actively contemplate possible bugs right when writing code rather than passively executing the code and waiting for any possible bugs to reveal themselves.