Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Mobile / Android

One-Touch Casual 3D Game Based on OpenGL ES 2.0 3D Engine with Lua, Bullet, and Vorbis Support

4.75/5 (7 votes)
8 Nov 2012CPOL5 min read 52.6K   3.3K  
Android-x86 native game-engine - without JNI

1. Link to Android x86 Projects Archive

2. Link to CasualGame.apk for Android x86

3. Link to CasualGame.apk for ARM

Disclaimer

This article is part of our Android at Play: Android Game App Contest and has different requirements and requires less strict guidelines.

Introduction

This is a simple game that can be played in the simulator as well as on the device. Can you beat my x86 simulator best time of 19 secs? :)

Image 1

You need to touch the area near the bottom of the space-craft to make it rise. Once air-borne, touch to the left of the space-craft to make it go to the right. Experiment with the control till you get the knack of it. Beat my time!!!

For those experienced in Android NDK development, the brief detail about my dev setup and procedure should be sufficient to get the code built.

For those new to Android NDK development, you will need to do go through some basic Android NDK tutorials on the net and on CodeProject. :)

I eagerly look forward to any questions or suggestions you may have with regards to this code base and even its dev setup (as it is a tricky thing in Android NDK development).

Inspiration and Motivation

I have based my work off the Apache 2.0 licensed 'gameplay' engine for BB10 by RIM.

While the game itself appears simple, it covers key concepts like 3D physics using Bullet, importing assets from Maya (or Max), and dynamic light calculations.

Equally important, I would like to draw attention to the poweful engine used to create this game.

A large part of my effort was directed at porting, modifying and enhancing this game-engine for use on the Android x86 platform.

Based on my professional experience, findings, and learnings in cross-platform smartphone game development, I can confidently state that this framework strikes the best balance as a lean yet feature-rich collection of open-source technologies for Android x86 game development.

Important: This code base comprises of only C and C++. It has no Java code. It relies on the Native Activity feature of Android.

Game Implementation Details

The basic goal of this game is to pilot a space ship through a fixed distance in the shortest time.

Image 2

The art assets are modeled in Maya. They are kept simple. The roof and floor meshes are repeated to create a long tunnel. A simple texture is used for the tunnel. Dynamic lighting is used to create interest in the scene.

Controls (algo)

1. The player touches the screen near the ship to activate the throttle.

2. The distance between the finger and the center of the ship determines the throtle magniture.

3. The angle between the finger and the horizontal axis of the ship determine the thrust angle.

4. If no input is applied, the ship drops as a result of gravity.

5. For adding interest, the ship does spins, and adjust exhaust glow based on throttle magnitude.

6. The sound pitch too is proprtional to the throttle magnitude.

The 3D models, fonts and sounds for the game are initially exported as FBX, ttf and wav. However, they are encoded to the gpb format via the gameplay-encoder for use in the engine.

Font loading

Font *_font = Font::create( "res/airstrip.gpb" ); 

Scene and Model loading

C++
/ / contains spaceship, roof, ground etc..
Bundle *bundle = Bundle::create( "res/spaceship.gpb" ); 
_scene = bundle->loadScene(); 

/ / get a handle to the spaceship
Node *_shipNode = _scene->findNode( "pSpaceShip" ); 

SAFE_RELEASE( bundle );  

Using shaders from the shader library

material = _shipNode->getModel()->setMaterial( "res/shaders/colored,vert", " res/shaders/colored.frag", SPECULAR, 0 );  

Accessing the active camera in the scene

_scene->getActiveCamera()->setAspectRatio( 1.5 );

Camera movemement

void SpaceshipGame::updateCamera()
{
    if (_finished)        
        return;     

    / / Keep the camera focused on the ship    
    const Vector3& cameraPos = _cameraNode->getTranslation();    
    const Vector3& shipPos = _shipGroupNode->getTranslation();    
    float diff = cameraPos.x - shipPos.x;    
    if (diff > CAMERA_RANGE_BACK)    
    {        
       _cameraNode->translateX(-(diff - CAMERA_RANGE_BACK));    
    }    
    else if (diff < -CAMERA_RANGE_FRONT)    
    {        
        _cameraNode->translateX(-(diff + CAMERA_RANGE_FRONT));   
    } 
} 

Game rendering

void SpaceshipGame::render( float elapsedTime ) 
{ 
    clear( CLEAR_COLOR_DEPTH, Vector4::zero(), 1.0, 0 );
     
     / / for opaque drawing
    _scene->visit( this, &SpaceshipGame::drawScene, ( void * ) 0 );
    
     / / for transparent drawing    
    _scene->visit( this, &SpaceshipGame::drawScene, ( void * ) 1 ); 
     
    _font->drawText( "Click to Play again", getWidth() / 2 - 175, getHeight() / 2 - 40, Vector4::one(), _font->getSize() ); 
 }         

Handling game-over

C++
void SpaceshipGame::resetGame()
{
    _time = 0;
    _finished = false;
    _velocity.set(0, 0);
    _shipGroupNode->setTranslation(_initialShipPos);
    _cameraNode->setTranslation(_initialCameraPos);
}  

Nitty-gritties!!

The biggest challenge in using the stock engine on platforms other than the BB10 is that all the external dependencies of the engine are provided as prebuilt libraries. The problem only gets worse for Android x86 as it isn't even a supported platform for the stock engine.

Image 3

This was the primary roadblock that I faced while working on this game. I removed the dependencies on the prebuilt libraries and replaced them by the actual sources of the libraries. The library sources that I have added (and statically linked) to the engine include,

  1. Lua 5.2, for scripting. (Refer here for compiling Lua on Android - http://stackoverflow.com/questions/12299659/compiling-lua-lib-for-android-success-but-strange-segfaults)

  2. Bullet 2.7

  3. OpenAL - This was convoluted due to this project being a NativeActivity. Was made to think in the right direciton after reading this http://blog.tewdew.com/post/6852907694/using-jni-from-a-native-activity

  4. PNG

  5. Zlib

  6. Vorbis

Dev Setup

  1. Win7 x64 Host, Fedora 16 Guest. i.e. a Linux dev environment

  2. Android SDK r2.0.0.3, NDK r8b, API 15 (x86)

  3. Eclipse 3.7 (with ADT, CDT and Sequoyah)

  4. DS5 ARM Debugger Community Edition (the best for Android Native Activity debugging)

  5. Ant (for asset packing only)

  6. Maya 2013

  7. AVD (API 15 with GPU emulation enabled)

Steps to follow
  1. On unzipping the archive, you will get 2 Android NDK projects and an external-deps folder. These are the bare essentials needed for building this game, and they include all the modifications mentioned above.
    1. gameplay, this is the game engine
    2. CasualGame, this is the game
    Do check the Application.mk and Android.mk files. The original files are renamed to Application.mk.orig and Android.mk.orig respectively.
  2. From within Eclipse, import both projects as 'Existing Projects into Workspace' This will preserve all settings necessary to build these projects correctly. Remember to import from within the android sub-folder, else Eclipse won't recognize these projects as Android NDK projects.
  3. First build the gameplay project. This will build the engine as a static lib, libgameplay.a in the gameplay/android/obj/local/x86 folder.
  4. Next, build the CasualGame project. This will build the game as a shared lib, libCasualGame.so
  5. Now we have built the native parts of our code. Next we need to add the game assets to the apk. This is done from the command line via ant.
  6. Navigate to the android sub-folder of the CasualGame project, and type android update project -t 1 -p . -s
  7. Next type, ant debug install. This will generate the apk containing our NDK code and insert into it the assets for the game. Thus we end up with CasualGame.apk.
  8. Now come back to Eclipse and run/debug the project as a normal Android NDK application.

Points of Interest

Successfully created a game and ported a lean, feature-rich game-engine for use on the Android x86 platform. Yay!! Yay!! Yay!!

Do let me know if you run into any roadblocks. Will help out how I can. :)

History

v1.0 - gameplay for Android x86.

v1.1 (in progress) - Optimizing the 3D RacerDemo based on this framework. Adding 2D texture packing and animation tools.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)