using Cocos2d-x Android v2.2+
32.2 Using Cocos2d-
To show you what Cocos2d-x is capable of, we’ll cre- ate a normal Android application and we’ll make it snow. Using a particle system, we’ll add a chilling visual effect to our view. The finished work can be seen in figure 32.1.
For starters, you should understand that Cocos2d-x uses OpenGL to draw everything. In Android, to draw OpenGL, the developer will need to use a Surface- View. Let’s see how the SurfaceView works to under- stand how Cocos2d-x will get mixed into our application.
In the SurfaceView documentation (see section 32.4) we can read the following:
Figure 32.1 Application with a make-it-snow effect
The SurfaceView is a special subclass of View that offers a dedicated drawing surface within the View hierarchy. The aim is to offer this drawing surface to an application’s secondary thread, so that the application isn’t required to wait until the system’s View hierarchy is ready to draw. Instead, a secondary thread that has reference to a SurfaceView can draw to its own Canvas at its own pace.
The last paragraph holds a lots of important information, so let me try to explain it in an easier way. Every time we add a widget or a custom view to our application, it gets added to the view hierarchy. Our complete tree of views (which forms our Activity) gets drawn in what’s called the UI thread. On the other hand, the SurfaceView gets its own thread to draw and it won’t use the UI thread. If the SurfaceView doesn’t use the
UI thread to draw itself, how does Android deal with the mixture of the view hierarchy and surface views? To understand this, we must analyze the following paragraph (see section 32.4):
The surface is Z ordered so that it is behind the window holding its SurfaceView; the SurfaceView punches a hole in its window to allow its surface to be displayed. The view hierarchy will take care of correctly compositing with the Surface any siblings of the SurfaceView that would normally appear on top of it. This can be used to place overlays such as buttons on top of the Surface, though note however that it can have an impact on performance since a full alpha-blended composite will be performed each time the Surface changes.
The big conclusion we can get from this last paragraph is that we can mix both worlds but with certain restrictions. The SurfaceView will be placed in front of or in back of our view hierarchy. In our example, we’ll have our view hierarchy in the back and will place the SurfaceView in front of it. So let’s get started creating our view hierarchy first.
We’ll first create the XML for our Activity. Here’s the code: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/winter_text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_marginTop="5dp" android:gravity="center" android:text="Hello Winter!" android:textSize="30sp" /> <View android:id="@+id/separator" android:layout_width="fill_parent" android:layout_height="5dp" android:layout_below="@id/winter_text"
103
Empowering your application using Cocos2d-x
android:background="#FFFFFF" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerInParent="true" android:layout_marginTop="5dp" android:gravity="center" android:text="It's snowing!" android:textSize="30sp" />
<FrameLayout android:layout_width="fill_parent"
B
FrameLayout android:layout_height="fill_parent" android:layout_below="@id/separator"> <org.cocos2dx.lib.Cocos2dxEditText android:id="@+id/game_edittext"C
Creates an org.coco2dx.lib .Cocos2dxEditText android:layout_height="wrap_content" android:layout_width="fill_parent" android:background="@null"/> <org.cocos2dx.lib.Cocos2dxGLSurfaceViewD
Places SurfaceView inside the XML android:id="@+id/game_gl_surfaceview" android:layout_width="fill_parent" android:layout_height="fill_parent"/> </FrameLayout> </RelativeLayout>The layout has nothing special in it. I’ve organized the different views using a Rela- tiveLayout. The interesting stuff is inside the FrameLayout
B
. We can first see how an org.cocos2dx.lib.Cocos2dxEditText is createdC
. The Cocos2dxEditText is needed by Cocos2d-x to show the keyboard when the game demands text input from the user. It’s not something that we’ll use, but it’s required. The other important ele- ment is the SurfaceViewD
. Placing the SurfaceView inside the XML offers an unique way of positioning and providing a width and height to our Cocos2d-x’s view. We could’ve used the whole screen, but I wanted to show you how we can use Android resources to place the SurfaceView on the screen without worrying about device sizes, pixel density, and so on.Let’s continue with the Activity’s code. It’s just copied and pasted from the Cocos2d-x Hello World sample application. Here’s what it does:
public class MainActivity extends Cocos2dxActivity {
B
Extends Cocos2dxActivityprivate Cocos2dxGLSurfaceView mGLView;
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
if (detectOpenGLES20()) {
String packageName = getApplication().getPackageName();
C
Tells Cocos2d-x our application package super.setPackageName(packageName); setContentView(R.layout.game_demo); mGLView = (Cocos2dxGLSurfaceView) findViewById(R.id.game_gl_surfaceview);D
Informs Cocos2d-x where Cocos2dxEditText isCocos2dxEditText edittext = (Cocos2dxEditText) findViewById(R.id.game_edittext);
mGLView.setCocos2dxRenderer(new Cocos2dxRenderer()); mGLView.setTextField(edittext);
} else {
Log.d("activity", "do not support gles2.0");
finish();
B
Closes the app} } }
To use Cocos2d-x features in our Activity, we need to extend Cocos2dxActivity
B
. We tell Cocos2d-x our application packageC
. Cocos2d-x will use that package to read assets from the Assets folder. We also inform Cocos2d-x where the Cocos2dxEditText isD
. If the device we’re running doesn’t support OpenGL 2.0, then we need to close the appE
.We’ll also take the liberty of modifying Cocos2d-x’s Java code to place the SurfaceView on top of the view hierarchy and make its background translucent. To do so, we add the following lines in the initView() method of the Cocos2dxGL- SurfaceView class:
setEGLConfigChooser(8, 8, 8, 8, 16, 0);
getHolder().setFormat(PixelFormat.TRANSLUCENT); setZOrderOnTop(true);
Also add the following line in the onSurfaceCreated() method of the Cocos2dxRenderer class:
gl.glClearColor(0, 0, 0, 0);
We have all the Java code in place; we just need to write the C++ code to take care of the snow. Since this is just an example of what’s possible, I copied and pasted one of Cocos2d-x’s particle system tests that involves snow falling down. The code is all inside the HelloWorldScene.cpp file that comes with the sample code for this book.
If you’ve never used C++ in Android before, you should know that you need to use the Android NDK.
32.3
The bottom line
Using Cocos2d-x is a great way to improve how your application looks and an excel- lent way to avoid dealing with OpenGL directly. Unfortunately you’ll need to deal with its limitations and its complexity. You’ll need to write C++ code, deal with the NDK, and set up your views to place a SurfaceView correctly, among other things. In the end, it’s totally worth the effort.
105
Empowering your application using Cocos2d-x
32.4
External links
http://developer.android.com/sdk/ndk/index.html http://www.cocos2d-x.org/ http://developer.android.com/guide/topics/graphics/index.html#on-surfaceview http://www.cocos2d-iphone.org/archives/888 http://www.cocos2d-iphone.org/archives/1496 http://developer.android.com/guide/topics/graphics/2d-graphics.html http://developer.android.com/reference/android/view/SurfaceView.html107