Showing posts with label 3d. Show all posts
Showing posts with label 3d. Show all posts

Sunday, August 18, 2013

Developing 3d game for Android - part 2

Well, it is done!

I finished version 1.0 of my 3D space arcade game based on  Rajawali framework and published it on  Google Play.

You can check it out here: https://play.google.com/store/apps/details?id=com.mabuga.gravity.android.before4&hl=en

And here is gameplay video on youtube:





I enjoyed developing with Rajawali, it was very fun and the issues I run into were not critical.
Issue that I spent most time dealing with is rendering explosions. I wanted to use simple animated sprites for explosions and Rajawali supports that via Particle primitive. Basically, you set spritesheet texture to a Particle, define how many tiles spritesheet has, and Rajawali shader will render the particle using given spritesheet creating animation from it's tiles.

What I wanted is just one big animated sprite to render explosion. And that was where the problem appears - the size of single particle.  Actually there are two problems related to particle size.

1. There is a bug in Particle code that is causing particle look smaller as as the distance from world origin gets bigger, regardless of camera position.

2. Particle is rendered as textured point and unfortunately OpenGL implementations limit the size of the rendered point. Even worse, different implementation has different values for point size limit. OpenGL specification doesn't guarantee point size bigger then 1 px.

My workaround for first problem was to update particle code (GL shader and java) to fit my needs. Unfortunately, my solution did not solve the bug in generic way (since the problem is not just bug in calculation but conceptual as well) so I could not commit it back to the project.

Second problem actually can not be really solved since it it hardware specific, so I just accepted imposed point size limit. Quick test on few devices I own showed me that point size limit is around 100 px on my HTC Explorer with 480x320 px screen and around 500 px on my Samsung Galaxy Tab 2 with 1280x800 px screen. That was ok for my explosions, however, there are probably devices with big screen and small point size limit and my explosions probably look bad on those.

Also, I experienced some weird rendering issues when returning from RajawaliActivity with RajawaliRendered to normal Activity, but that was solved by setting android:hardwareAccellerated to false on activity elements in android manifest.

So, there were actually very few problems with Rajawali framework.
Besides the issues, I would like to share some thoughts about challenges of optimizing the game for low CPU powered devices.

Crucial part of almost any game is collision detection. Rajawali already has built in collision detection features, but checking collisions too often can have significant CPU cost causing glitches in gameplay.
In every frame (about 30 times per second) we have to check collision of every moving object with all other objects on the scene. Let's say that we have 30 moving objects (ships + bullets) and about 20 - 30 static objects (meteors) on the scene at the same time, this means we have to handle ~ 30 * 50 = 1500 checks per frame which makes 45 000 per second. And that's a lot.
In order to minimize number of collision checks per frame, I divided game space into "sectors". For static objects I only calculate in which sector they are in game init phase, and for moving objects I had to calculate in which sector they are every time they move.
Also, I added global sector map that maps sector name to a list of objects currently in that sector. This map is also updated on every object sector calculation.
So, now for every moving object we only need to check collisions with objects currently in same sector , and this is usually 0-5 objects. This reduces CPU usage big time. This way number of collision checks doesn't increase at all if we add more static (non moving) objects.

Another thing I optimized in order to achieve better game performance is to handle object creation little bit smarter then just create them when ever I need them. Actually, I recycle them.
Whenever new bullet is fired or new ship should appear, it should be added to scene, and whenever ship is destroyed or bullet hits something, it should be removed from the scene.  But adding and removing new objects can also be costly, especially if it happens often. If we instantiate new bullet every time ship fires, we spend CPU cycles on initiation of the bullet. After that we have to add it to a scene (renderer), and this also takes some CPU time since renderer must register new object to it's list of objects in synchronized way. Rajawally uses synchronized "copy on write" list for this purpose.

So, instead of creating and destroying new objects all the time, I used well known technique called "object pooling" . It boils down to creating certain number of objects and store them in a pool (a list or a map) , then take it from that pool when we need new object and return it when the object should be destroyed/removed.
In my case, I had two different pools, one for bullets, another for explosions. Using two pools for specific object types instead using one generic pool also makes things faster since we don't have to do any type checking.
If new object is required and the pool is empty, we simple create new object and add it to the pool, so our pool will grow depending on demands.

When object need to be removed from the scene, I don't actually remove it, I just hide it by setting visibility to false and by setting its position far out of the camera view. I also remove it from my internal list of movable objects, so I don't move it or check collisions for it while it is in the pool (kind of object passivation).

When taken from the pool, object is set to visible, its position/rotation is updated as needed, and it is added to movable objects list, so it can be managed by game logic (moving and collision checking).
And that's it. Simple, but effective.

OpenGL handles rendering in most optimized way it can, and besides the few tricks described above there are several other things developer can do to make the game run smooth:
- use low poly 3D models
- keep number of objects on the scene as low as you can
- keep objects static (non movable) whenever possible

I covered some basic and common things related to game optimization, but every game is specific and it has specific things that can be optimized.

Friday, July 5, 2013

Developing 3d game for Android

To develop real 3D game is not trivial task no matter what platform you target.

Five or six  years ago I was experimenting with JOGL - Java Binding for the OpenGL API trying to develop 3D game in java for PC.
In that time it was common opinion that 3D games can only be devleoped with C++ since java is too slow. Even then that was not true. JOGL delegates all rendering to OpenGL , and in initialization phase you can create complex objects in OpenGL memory so later you can reference it from java and give short instructions to OpenGL in order to move or rotate that object. That means that java only have to manage positions and rotations of the objects, check collisions and of course game logic.

Since rendering is most demanding part of 3D game and it is handled by OpenGL ,  C++ being faster then java doesn't matter so much. Of course , in Java you will probably have to optimize more, but it is definitely fast enough.

I was very happy how my experiment turned out. Although I never finished and published the game, I managed to make nice little space combat with real LAN multiplayer so players could fight in space. It had laser guns, missiles that follow the targets, radar, etc. It was running smooth both on Windows and Linux.

Today, even cheap smartphones (like my HTC Explorer) have similar CPU power and memory my PC had at time I was playing with JOGL.

Smartphones support OpenGLES - The Standard for Embedded Accelerated 3D Graphics. Most phones support OpenGL ES 2.0, only older models still use OpenGL ES 1.x.

Working with JOGL, developer actually has to know much about OpenGL since JOGL is not a 3D engine, it is just a bridge between Java and OpenGL which allows us to call OpenGL commands from Java code.

In recent years several good 3D libraries emegred, making 3D apps development much easier. Since they manage low level OpenGL calls, you can focus more on your game logic.

There is a great OpenGL ES 2.0 based 3D engine for Android platform called Rajawali, developed by Dennis Ippel (great job Dennis). There is also Android Demo app that demonstrate Rajawali engine features.

Basic feature that every 3D engine provides is loading external 3D model, adding it to 3D scene and manipulating it's position and rotation. Most 3D engines provide much more features including collision checking, physics, lighting, various visual effects, etc.

Rajawali's set of features amazed me so I decided to try it out by  making simple 3D game that focuses on playability  rather then on visual attraction. As a kid a loved games like Galaga and Phoenix because they were dynamic and addictive. My goal is to achieve similar gameplay dynamic in 3D world.  Although I limited ships freedom to move to a plane (can't go up or down), 3D perspective gives me more "space" (player can see distant enemy ships much earlier that it would be possible if the view was from above) and of course 3D models of ships and meteors look more realistic then it can be achieved in 2D.

Here are first screenshots of the game :




So far everything works fine on HTC Explorer (Android 2.3.5) and HTC Desire C (Android 4.0). 
I'll keep you posted about my progress here.