Click here to Skip to main content
12,998,054 members (59,751 online)
Click here to Skip to main content
Add your own
alternative version

Stats

26K views
13 bookmarked
Posted 5 Nov 2012

Intel x86 Android Game Development using RAD

, 5 Nov 2012
Rate this:
Please Sign up or sign in to vote.
Design of an x86 Android game that is cross-platform compatible
This is an old version of the currently published article.

The .zip file also contains the compiled "MonkeyGame-debug.apk" binary that can be run in the emulator. There is an HTML5 build in the folder "game.build". To test the game run the MonkeyGame.html in the Chrome browser.

Introduction

There are two ways you can build an Android NDK based game for x86 which is also truly cross platform

The hard way:

Build your game with low level native code for the target platform and use the NDK toolchain to call the native code via JNI and port it keeping in mind the native code idiosyncracies of different platforms.

The easy way:

Use a RAD cross-platform game development tool/engine that has support for Android on x86 as listed here http://software.intel.com/en-us/blogs/2012/03/13/game-engines-for-android

We will be using Monkey game engine because I have developed cross-platform games with it previously and it has the advantage of having pre-compiled NativeGL shared libraries for Android on ARM and x86 architectures. You can find these in the "nativegl" folder in the accompanying source.

Background

Memory Game is a variation on the classic game where you uncover cards two at a time to find matching pairs. When all matching pairs have been uncovered the game is over. The objective is to expose all pairs using the least number of moves. A partial deck of playing cards is used in this variation of the game.

Game Features:

  • 24 cards for increased difficulty
  • Animated cards with sound effects

Technical Features:

  • Game state class
  • Collision class
  • Procedural font generation class
  • Autofit class using hard coded virtual resolution for scaling to differing actual device aspect ratios and resolutions - very important since Android device fragmentation is a major issue

I chose this game as a pedagogic tool for this article because it is simplistic without being simple. That is, it contains all essential game elements and clearly demonstrates the real-time nature of the game loop and the design principles to be used. It is a 2D game because, for modern touchscreen based mobile devices, interacting with 2D sprites provides for a more intuitive interface.

Screenshot - Game Running in Browser

Technical Information

Some requirements for rapid prototyping which the engine has:

  • Fast Debug - Compile - Run cycles can be executed in any standard compliant HTML5 browser.
  • The game loop is well defined with OnCreate() , OnUpdate() and OnRender() methods.
  • The scripting language is object oriented. It has basic language constructs for sprite manipulation and game data structures. Automatic garbage collection.

Using the code

The GameState variable cycles the state machine through its various stages. It is initialized at start to the STATE_MENU. This variable also controls the update and rendering sections of code.

Method SetState (state:Int)

       GameState = state

       Select GameState

             Case STATE_MENU
                  //The initial menu layer

             Case STATE_PLAYING
                 //The game layer

             Case STATE_PAUSED
                 //The game layer paused

             Default
                 Print "ERROR: Unknown game state!"

       End

End

Let's check for input and update game state:

In the OnUpdate() Method we call the Card[i].Update() Method of the Collision class. Depending on whether the pointer collides with the card sprite, it returns the visible or hidden state of the card. If two cards have been clicked we increment the tries count.

Case STATE_PLAYING
//check for two card clicks. show cards that were clicked by hiding corresponding cardback
     For Local i : Int = 0 Until NUM_CARDS
	  Card[i].Update()
	  If Card[i].Pressed = True And Card[i].Visible = True And click < 2 Then 
		Card[i].Visible = False
		savecard[click] = i
		click = click + 1
		    If click = 2 Then
			slowdown = Millisecs()
			turns = turns + 1   //increment tries after two cards have been clicked
		    End If
		PlaySound boom

	   End If					
     Next

If a matching pair is found we leave those cards uncovered else if the pair doesn't match we make the corresponding cardbacks visible and hide the cards again. The delay of 1.5 seconds permits both cards to be visible long enough for the player to see that they don't match.

If click = 2  Then
    If coinplace[savecard[0]] = coinplace[savecard[1]] Then  //a matching pair is found
    click =0
    Else
       If  Millisecs()-slowdown > slowlimit Then  // wait before covering cards again
      Card[savecard[0]].Visible = True
      Card[savecard[1]].Visible = True
      click =0                          // reset to accept clicks on next two cards
       Endif
    Endif
End If

Local drawncard:Bool = False
For Local i : Int = 0 Until NUM_CARDS
    If Card[i].Visible = True Then
    drawncard = True
    End If
    Next
If drawncard = False Then Restart()    // If no cards are left to uncover End game

When none of the cards will have a backcard covering it because the collision class returns backcard visible state as False, drawncard Boolean will change state to False and the game has ended.

Shake up those cards:

A game without animations isn't much fun. Lets make the eye candy. The int variable n does the magic. n = -1*n toggles n between +1 and -1. The DrawImage() Method has rotation and scaling parameters. We adjust the card sprite rotation between +1 degree and -1 degree to create the vibrating card effect.

//refactored because the renderscreen method appeared to work in the pause state, and halts 
// game update, except for cards vibrating

Method RenderScreen()

     Cls
	
         // for a resolution of 800x600 render cards in 6 columns and 4 rows, starting at 
        // x offset 33 pixels and y offset 30 pixels
     For Local i:Int =  0 Until NUM_CARDS		
	  DrawImage coins[coinplace[i]], 33+((i Mod 6)*100), 30 +(Int(i/6)*140)
     Next
						
	//as n toggle between +-1, the card sprites oscillate(animation) between +-1 degree
	//if collision check returns visible attribute show cardback else hide it
     For Local i : Int = 0 Until NUM_CARDS						
	  If Card[i].Visible = True 						
                     n = -1*n
	        DrawImage (card, Card[i].PositionX, Card[i].PositionY, n*1.0, 1.0, 1.0)
	  Else
		DrawImage (cardclick, Card[i].PositionX, Card[i].PositionY, 0, 1.0, 1.0)
	  End If
     Next
						
     DrawImage (sidebar, 620, 0)

     DrawImage pointer.image, pointer.x, pointer.y
						
	font.Draw( turns, 710, 290, 3, 3, 0.5, 1.0 )  //render the procedural font for number of tries
	
End
The code in the download is heavily commented and requires little explanation, however class members and methods are detailed below.
  • MyGame Class :
  • OnCreate() Method : Instantiate game objects - images, sounds, members and variables.
  • OnUpdate() Method : Poll / Interrupt check for mouse/ touchscreen/ keyboard input and change game states and object states accordingly.
  • OnRender() Method : Render graphics depending on game state being Menu, Playing or Paused and the state attributes of game objects.
  • Collision Class : Takes touch/ mouse co-ordinates and colliding sprites and returns a visible or hidden attribute for the corresponding sprite object.
  • Font Class : This is a procedurally generated font.
  • Autofit Class : Provides a hard coded "virtual" resolution and scales the graphics to different screen resolutions (aspect ratios) without causing distortion along x,y screen space co-ordinate axes. Black borders will appear to the left/ right or top/ bottom if
  1. The physical device aspect ratio is different from the "virtual" aspect ratio.
  2. The screen orientation is changed.

Issues Faced

For mobile devices with less horsepower I attempted to implement a particle engine because the integrated particle class is a bit heavy on resources. The compiler didn't like me creating a list of sprite objects at a particular point in the game loop! But I'm sure there's a workaround to it, given time. I also sorely missed an integrated debugger.

Development and Testing

Initial development/ debugging was done in the browser for fast turnaround times. Device testing for scaling and actual run time performance was done on a 1024x600, 7" Android tablet. Final testing was on the x86 AVD in the Android emulator. Although the HTML5 compile was smooth, when testing on the Android target, a null object exception was thrown when returning handles to graphics objects from the collision class, but a suitable workaround was implemented.

Screenshot - game running on x86 AVD in the Android emulator

Game icon on start screen

Points of Interest - porting to different platforms

So the question is how easy is it to port this game to other platforms other than Android x86?

Non-native:

Browser based HTML5 - JavaScript build during prototyping is ready for deployment.

Native :

Android ARM - Compile with ARM nativeGL shared libraries

Windows desktop app for Intel AppUp® Store - Wrap the HTML5 build using the Intel AppUp® encapsulator available at http://software.intel.com/en-us/appup/encapsulator

XNA, iOS, etc. can be ported by selecting the required targets in the iDE.

Credits

My thanks to all the guys on the Monkey coder forums who were always ready to help out when issues popped up.

Wrapping up

The source code is there for you to play with, and I hope you can take it further in your own games on the x86 Android platform and other platforms as well. If any clarification or explanations are required please ask. Also, if you find anything that needs correcting do let me know.

License

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

Share

About the Author

Kurosh F.
Software Developer
India India
No Biography provided

You may also be interested in...

Pro
Pro

Comments and Discussions


Discussions posted for the Published version of this article. Posting a message here will take you to the publicly available article in order to continue your conversation in public.
 
QuestionTechnolgy Pin
davidfrnco9-Nov-12 18:44
memberdavidfrnco9-Nov-12 18:44 
AnswerRe: Technolgy Pin
Kurosh F.9-Nov-12 23:34
memberKurosh F.9-Nov-12 23:34 
GeneralMy vote of 1 Pin
pip0105-Nov-12 23:05
memberpip0105-Nov-12 23:05 
GeneralRe: My vote of 1 Pin
Kurosh F.6-Nov-12 0:53
memberKurosh F.6-Nov-12 0:53 
GeneralRe: My vote of 1 Pin
pip0106-Nov-12 1:40
memberpip0106-Nov-12 1:40 
GeneralRe: My vote of 1 Pin
Kurosh F.6-Nov-12 5:18
memberKurosh F.6-Nov-12 5:18 
GeneralRe: My vote of 1 Pin
pip0106-Nov-12 5:47
memberpip0106-Nov-12 5:47 
GeneralRe: My vote of 1 Pin
Kurosh F.6-Nov-12 5:50
memberKurosh F.6-Nov-12 5:50 
GeneralRe: My vote of 1 Pin
pip0107-Nov-12 4:14
memberpip0107-Nov-12 4:14 
GeneralRe: My vote of 1 Pin
Kurosh F.7-Nov-12 5:14
memberKurosh F.7-Nov-12 5:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170622.1 | Last Updated 5 Nov 2012
Article Copyright 2012 by Kurosh F.
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid