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? :)
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.
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
/ / 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
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.
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,
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)
Bullet 2.7
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
PNG
Zlib
Vorbis
Dev Setup
Win7 x64 Host, Fedora 16 Guest. i.e. a Linux dev environment
Android SDK r2.0.0.3, NDK r8b, API 15 (x86)
Eclipse 3.7
(with ADT, CDT and Sequoyah)
DS5 ARM Debugger Community Edition (the best for Android Native Activity debugging)
Ant (for asset packing only)
Maya 2013
AVD (API 15 with GPU emulation enabled)
Steps to follow
- 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.
- gameplay, this is the game engine
- 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. - 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.
- First build the gameplay project. This will build the engine as a static lib, libgameplay.a in the gameplay/android/obj/local/x86 folder.
- Next, build the CasualGame project. This will build the game as a shared lib, libCasualGame.so
- 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.
- Navigate to the android sub-folder of the CasualGame project, and type android update project -t 1 -p . -s
- 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.
- 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.