Critical Velocity is a fun little open source arcade style scrolling game that I made after finishing my Android developer class. It was my first released game using the libGDX engine, an open source graphics engine that is great for making games. Due to my inexperience, however, I didn’t take into account that all screens are not created equal. Some screens are bigger than others, and some have lower resolution than the phone I built the game on.
This caused a problem. After releasing the game, I quickly was alerted to the issue through the GitHub issue tracker, where several players let me know that it was crashing on startup with their phones. It took a little bit of time to figure out, but I came to realize that the app was crashing on phones that were smaller than 800×480 screen resolution.
At first I thought there were all sorts of problems with graphic asset sizes, and memory issues. I tried numerous things to fix it, but nothing worked. Finally, I gave up. But, a few days ago, I decided to take another look. By God’s grace, this time I got it figured out! Before, I was working off of the information provided by people with smaller resolution screens, but I decided that I should load up the game in an emulator with a 320×240 resolution screen, and watch the logs. That’s when I found the problem.
The issue didn’t have anything to do with libGDX, the graphic assets, or the amount of memory the game takes (about 15 MB). As it turns out, the math just didn’t add up. Literally!
In the game, the upper and lower walls are separated by a gap. The size of the screen and the size of the gap is used to determine where the next set of walls opening can be (up or down) from the previous wall. The idea was that as you went faster, an opening at the top of the screen followed by an opening at the bottom of the screen is technically impossible to reach, so this math would keep it “near” the other opening within reason, but still allow it to be randomly placed, up or down from the previous one.
The math looked like this:
Place of the next wall opening = randomly based off of (1/2 of the screen height – the size of the gap) from the center of the screen.
This worked great on my test phone that had a screen resolution of 1920×1080. With the standard gap that I set of 450, the math looked like this:
Place of the next wall opening = randomly based off of (960 – 450 = 510) from the center of the screen.
But it didn’t work for a screen as small as 320×240 because:
Place of the next wall opening = randomly based off of (160 – 450 = -290) from the center of the screen.
For a random number, you can have a negative outcome, but you cannot put in a negative input. The random number is based on starting at 0, and create UP TO X random numbers. So if X is negative, then the random number generator doesn’t know what to do!
So I had to invent a way to fix this problem. Fortunately, that was easy. I used an if/then statement to ask what the screen size was, and then changed the gap size to be less than 1/2 of the screen size. I also had to edit a few parameters, such as thrust, speed, and distance also based on screen size. You can check out my code and commits here and here, if you’d like.
Long story short: Don’t make assumptions, check the logs and they WILL lead right to the problem! If I had run the emulator myself before, not having a small screen phone anymore, I hopefully would have seen this right away. Here are some screen shots of the game on different phones. Unfortunately, I still have a lot to learn to make sure that the game LOOKS the same on different sized screens, but at least now it doesn’t crash!
Linux – keep it simple.