Android Question The Big Chase

MasterGy

Member
Licensed User
A game is in development, and I’d like to introduce it—I think it’s entertaining.

Gameplay:​

The gameplay is simple. Every ball wants to catch “something.” The player holding this “something” needs to bring it into the tornado. Whoever manages to bring it into the tornado wins. Once the ball is inside the tornado, the tornado ejects it far away, and the game starts over.

When the program starts, we see a match in progress. You can join the game, and you’ll randomly take control of one of the balls. Controlling the ball is based on a very simple principle: you either turn right or left. You can control it using a touchscreen or by tilting your phone left and right.

Technical Design:​

One of the primary goals was to make the game run at 60 FPS. Since the game involves high-speed action—flying, jumping, drifting—it’s crucial to deliver at least 60 frames per second for a smooth experience. Another key goal was to ensure the game runs on a Galaxy A13, which is a very basic phone. If it performs well on this device, it should run smoothly on many others.

In the menu, you can see performance metrics displayed at the bottom. The first metric shows how many times per second the positions of players are recalculated. Since I didn’t use delta time (which would have been too complex), I set it to 58 recalculations per second. This is the primary thread, and it must always maintain this rate. The speed of the balls does not change. Rendering has a secondary priority and runs as fast as the phone allows. This setup ensures that even if the visuals are fluid, physics calculations won’t slow down. Physics comes first! I aimed for both metrics to reach 58 FPS on my Samsung Galaxy A13. (It’s 58, not 60, because I’m unsure how OpenGL synchronizes with the phone’s display. Specifying 60 would be pointless if I can’t guarantee all 60 frames are shown.)

The key takeaway is that the game should theoretically maintain 58 FPS even on lower-performance phones. However, on my Xiaomi Redmi 12, the SoundPool library occasionally causes stuttering. This is noticeable when there are many sound effects, leading to dropped frames. I’ve been exploring solutions for this, such as using callSubDelayed with SoundPool, which slightly improves the situation but isn’t perfect. I plan to use threading for sound playback in the future.

Visual Effects:​

The game features smooth lighting effects. There’s a light source (moon or sun), which casts realistic shadows on everything.


OpenGL-Specific Questions:​

  1. Distance-Based Alpha Transparency for Textures:
    In the game, distant terrain generated using Perlin noise pops into view abruptly, which is distracting. It would look much better if the textures faded in with alpha blending. One approach is to pre-generate multiple alpha versions of the terrain textures, but that’s inefficient—requiring more memory, pre-calculation time, and results in choppy transitions if the fade distance is short. I’d prefer an elegant, OpenGL-supported solution. Any suggestions?
  2. Rendering the Tornado with Z-Buffer Issues:
    I wanted the tornado to always be visible, even from a distance. However, the rendered scene ends where the visible terrain does. (Why not increase the render distance? Because increasing the rendering range isn’t recommended due to Z-buffer resolution limits.)
    To address this, I scaled the tornado proportionally to its distance. While it appears distant, it’s actually rendered nearby. It’s a hack and feels unnecessary. Z-buffer toggling would solve this, but I’ve encountered issues with OpenGL ES: enabling and disabling Z-buffer tests and writes can’t be separated—they occur simultaneously.
    Here’s the problem:
    • If I disable the Z-buffer, I can draw something that’s always visible, but it doesn’t write to the depth buffer.
    • When I re-enable the Z-buffer, subsequent objects overwrite it as if it’s not there.
    • This limitation feels unnecessary. I spent an entire day trying to solve this and grew frustrated with the removal of this functionality in OpenGL ES, likely due to optimization on modern systems. Has anyone faced this issue and found a workaround?



I’m looking for OpenGL-specific answers, testing suggestions, and feedback.

The program is available for download, and the necessary libraries (OpenGL and threading) are included.

Unfortunately, the recording is weak, low fps, choppy.
 

Attachments

  • download.txt
    82 bytes · Views: 73

MasterGy

Member
Licensed User


Hi !

The game, using the old method with simplified, low-resolution spheres and tornado effects, rendered around 1,000-1,200 triangles at 60 FPS. When I increased this on my Samsung Galaxy A13, the device barely managed to maintain the frame rate. If I specified higher-resolution objects, it unfortunately started dropping frames. (I solved this by ensuring that the physics remained constant so that performance limitations only affected rendering, not game logic.) As a result, FPS dropped further.

With the new approach, however, the phone is barely under any load. I can now set it to 150 FPS with higher-resolution objects, and it maintains 100% performance. I took advantage of this massive performance difference to increase the resolution of the balls, tornado, and sky.

Performance comparison on the same phone:
(Old) DRAWARRAYS:

~1,200 triangles @ 60 FPS = 72,000 triangles/sec
(New) DRAWELEMENTS:

~5,000 triangles @ 150 FPS = 750,000 triangles/sec
Same phone, same hardware, but a huge performance boost.

I wanted to share this experience in detail because if someone is working with OpenGL and only needs to render a small number of triangles, DRAWARRAYS is fine. But if you're working with thousands or tens of thousands of triangles, DRAWELEMENTS is a must!

The downside of the new approach is that it’s not as straightforward or universal to feed triangles dynamically with simple parameters. Instead, you have to create the most efficient algorithm tailored to each object's specific properties. The different attributes of objects require unique approaches to generating the necessary arrays for DRAWELEMENTS commands.

It took me about three weeks to transition the program to this new method. But it was totally worth it—the performance difference is enormous!

You can verify it yourself. For now, I don’t plan to share the source code. In the game, you can open the menu to view statistics, including the number of triangles, rendering speed, and physics update cycles per second.

To enhance the gameplay experience, I’ve added many improvements:

A speed-based distance multiplier
Sky darkening as you turn away from it
Tons of small details that you might not notice consciously, but you would miss if they weren’t there

I'll share the APK.

 
Last edited:
Upvote 0

MasterGy

Member
Licensed User

The essential part of the game has not changed.
  • Rain, snow, fairies, water bubbles, and so on... These are passive elements, they do not affect gameplay. They provide a visual experience. Flat shapes, but influenced by light.
  • The meteor crashes and explodes, and the closer someone is, the more it scatters. With the addition of the meteor, dynamic changes in lighting are needed. Strong light, crystal, meteor. These are the three light sources. Many factors influence which one is dominant.
  • Underwater bubbles, the deeper you go underwater, the darker the image becomes.
  • The placement of the MENU, SKIP, LEAVE, radar, and level indicator on the screen depends on which side of the screen you're using. Depending on whether you touch the left or right side of the screen, these elements are animatedly positioned in the correct place to avoid interfering with the controls.

There are many other changes, but I can't list them because I don't take notes. Essentially, it's better now.
I don’t receive feedback, so there's no point in writing in more detail.

download APK:

I would like to ask about this, will there be a VULKAN lib? Is it expected?
 
Upvote 0
Top