Cocos android Analysis

Source: Internet
Author: User

Cocos2d-x Android Environment Construction
Cocos2d-x environment is relatively simple to build, but there are still a lot of small problems, I try to cover some of the comprehensive.


Download Software
Cygwin, NDK (ADT): C ++ related
If you do not have an Android development environment, you also need the Android SDK, Eclipse
Cocos2d-x source code
My environment is ndk r7, cygwin1.7, Android SDK is 2.2 and. In addition, I am debugging on a real machine and cannot do it on the simulator. It is estimated that I still have a problem with the T410 video card.
Install cygwin and set the path in the cygwin file.
Add the following code to. bash_profile of cygwin \ home \ Administrator:


1: ANDROID_NDK_ROOT =/cygdrive/e/ADT/android-ndk-r7c


2: export ANDROID_NDK_ROOT


3: NDK_ROOT =/cygdrive/e/ADT/android-ndk-r7c


4: export NDK_ROOT
Copy libgnustl_static.a from the android-ndk-r7c \ sources \ cxx-stl \ gnu-libstdc ++ \ libs \ armeabi in the ndk to the cocos2d-1.0.1-x-0.13.0-beta \ HelloWorld \ android \ obj \ local \ armeabi, this solution should be caused by inconsistent stl references, but the "png. a can not find ", but the path does not have any problems, so it is a bit difficult. In short, this is done, and I have not studied it in depth.
Go to the cocos2d-1.0.1-x-0.13.0-beta \ HelloWorld \ android directory and modify the following content to the specified path


1: NDK_ROOT_LOCAL =/cygdrive/e/ADT/android-ndk-r7c


2: COCOS2DX_ROOT_LOCAL =/cygdrive/f/cocos2d-1.0.1-x-0.13.0-beta
Cygwin in the cocos2d-1.0.1-x-0.13.0-beta \ HelloWorld \ android directory, execute. /build_native.sh. Compile the C ++ and JNI interfaces for Android Java. If the interfaces are successful, generate libhelloworld in libs. so dynamic library, we have done so much work for it
Import cocos2d-1.0.1-x-0.13.0-beta \ HelloWorld \ android project in Eclipse, familiar with Android at a glance, it is actually a Java project, we just the operation is only part of the jni, for Java implementation.
Execute Build Project in Eclipse to generate R. java
Run


Make
Ndk Make is an encapsulation Based on GNU Make. Next we will analyze what operations./build_native.sh has done. In short, it mainly involves copying resources and compiling code.


I found a problem when copying resources in my cygwin. The copied file is incorrect and cannot be deleted. I did not go into it and copied it manually. It is consistent with shell and easy to understand.


Ndk-build: Compile the HelloWorld project and compile Android under the jni folder. mk, similar to makefile, specifies the file to be compiled, the include path, and relies on the project cocos2dx_static for compilation. For example, the makefile of HelloWorld is roughly as follows:

LOCAL_PATH: = $ (call my-dir)

Include $ (CLEAR_VARS)

LOCAL_MODULE: = helloworld_shared

LOCAL_MODULE_FILENAME: = libhelloworld
LOCAL_SRC_FILES: = helloworld/main. cpp \

.../../Classes/AppDelegate. cpp \

.../../Classes/HelloWorldScene. cpp

LOCAL_C_INCLUDES: = $ (LOCAL_PATH)/.../../Classes

LOCAL_WHOLE_STATIC_LIBRARIES: = cocos2dx_static

Include $ (BUILD_SHARED_LIBRARY)

$ (Call import-module, cocos2dx)
LOCAL_PATH: = $ (call my-dir): Specify the current path as LOCAL_PATH.


Include $ (CLEAR_VARS): clears interference from environment variables other than LOCAL_PATH.


LOCAL_MODULE & LOCAL_MODULE_FILENAME: Module name & generated library name


LOCAL_SRC_FILES: compiled C ++ Source


LOCAL_WHOLE_STATIC_LIBRARIES: Dependent static library


BUILD_SHARED_LIBRARY: Shared library. Because Android dynamic libraries are used by JNI, they are called shared libraries, while static libraries are only used by other C ++ libraries.


$ (Call import-module, ): The module referenced by the NDK_MODULE_PATH environment variable And automatically include it in Android. mk.


In this way, if the include, library, and target of a compilation environment are basically specified, the final target file will be compiled, which is no different from the makefile idea. In addition, cocos2dx needs to be compiled here. a. The static library is compiled by make in the cocos2d folder. This script is more complicated, but the idea is not different. For more information about NDK Make, see Android Make.


JNI Interaction
After the C ++ interface is encapsulated, let's take a look at the Java code to understand the final implementation process and effect. The Java code is as follows:





The Java-layer framework is also very simple. Here there is no multi-Accelerometer, Music, Sound, and so on for analysis. It only analyzes the display-related aspects. The Java Process is as follows:





As shown above, if you are familiar with Android interface development, you can learn from the base class that the Java layer displays through Activity and GLSuffaceView. I will not go into details here. If you are interested, you can take a look at "view for game development or surfaceView". The View is similar to the traditional two-dimensional static interface and data-driven display, surfaceView is similar to the 3D mechanism for real-time rendering. Because Cocos2d is OpenGL, this can be explained as well.


There are a lot of things to be said about the entire framework, but I still don't know much about Java, so some things are not necessarily transparent, and some problems are inevitable.


Renderer
The Renderer class is responsible for rendering the driver for each frame. Call steps 1 and 2 and call nativeRender in jni in step 2 to render one frame, GLSurfaceView monitors UI interaction.


The advantage of this mechanism is that in Java, the Renderer is called by an independent thread, so there is no interaction with the UI, which ensures the user experience (user events are listened through GLSurfaceView, finally, the Renderer is passed to the C ++ layer for response), which ensures the anti-interference of the rendering process and still performs rendering through the C ++ layer ., The jni encapsulation used in the entire display process is mainly as follows:

 private static native void nativeTouchesBegin(int id, float x, float y); private static native void nativeTouchesEnd(int id, float x, float y);private static native void nativeTouchesMove(int[] id, float[] x, float[] y);private static native void nativeTouchesCancel(int[] id, float[] x, float[] y);private static native boolean nativeKeyDown(int keyCode);private static native void nativeRender();private static native void nativeInit(int w, int h);private static native void nativeOnPause();private static native void nativeOnResume();




Jni Encapsulation
Jni encapsulation consists of two parts: one is cocos2d JNI encapsulation, which is mainly used to call the jni interface of cocos2d in Java, one is the jni interface encapsulation in HelloWorld. This is something I was interested in, because jni encapsulation is quite complicated. Finally, I found that cocos2d is essentially no different, and the trouble is still encapsulation. Second, cocos2d is mainly a game engine. Therefore, basically all functions are implemented at the C ++ layer, rendering one frame and event processing, while the Java layer is mainly responsible for logic processing, jni is used to call the C ++ interface. The third point is that cocos2d encapsulation is still very concise. I think it is very elegant. in design, it is based on the Java logic, I think this is very desirable. Although cocos2d is implemented by C ++, it does not force interface consistency to ensure the consistency of each platform, in the jni layer, the SDK is encapsulated according to the application characteristics of the SDK on a specific platform. This reduces the implementation difficulty and increases the ease of use of the Code. The sacrifice is the local inconsistency of the application platform interfaces. The jni layer is mainly the interface encapsulation of event transfer and window rendering. For game developers, the core part can be completed on the Windows platform, then, the unique event is transmitted in the Android part. The rendering part is directly implemented using the standard example given by cocos2d, which greatly simplifies the work of developers to encapsulate jni themselves.


Window binding
The window binding is not very thorough. First of all, I think CCEGLView_Android is just a virtual window and has no substantive functions, just to facilitate architecture understanding.
void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv*  env, jobject thiz, jint w, jint h) {   if (!cocos2d::CCDirector::sharedDirector()->getOpenGLView())   {       cocos2d::CCEGLView *view = &cocos2d::CCEGLView::sharedOpenGLView();      view->setFrameWidthAndHeight(w, h);      // if you want to run in WVGA with HVGA resource, set it       // view->create(480, 320);  Please change it to (320, 480) if you're in portrait mode.       cocos2d::CCDirector::sharedDirector()->setOpenGLView(view);        AppDelegate *pAppDelegate = new AppDelegate();       cocos2d::CCApplication::sharedApplication().run();  }} void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) {  cocos2d::CCDirector::sharedDirector()->mainLoop();} 



Function 1 calls the function when onSurfaceCreated is called at the Java layer to obtain the GLView window for next rendering. The View window is not bound to handle similar to that in Windows, the second function is called when onDrawFrame in Java renders each frame, and finally calls the underlying Director rendering, complete a frame painting (for details, see HelloWorld sample analysis for cocos2d-x (I).


How can I understand this window binding method and ensure that the gl function I call can be drawn in the window? No similar handle is transmitted from Java to JNI in the whole article, C ++-level View is only a struct with the Width and Height attributes, so I understand GLSurfaceView. by default, Renderer is encapsulated in its own thread and bound to OpenGL. I think this should be reliable. In addition, you can render every frame in real time, and you can tune the Java interface as well, you can also tune the gl rendering by yourself. This is also quite good. I don't need to worry about this. As long as I know the location information for the height and width, I will render it directly.


Text
The rendering of other images is irrelevant to the system. The entire rendering process is also cross-platform. The integration of a platform mainly involves environment setup, message transmission between different languages, and View ing, the text is special. In Windows, CDC is used. In Linux, Freetype is used. How can this problem be implemented in Android? I think cocos2d has a good idea: C ++ draws a BitMap on the Java layer through JNI, generates a BitMap to C ++, and then completes the texture. This advantage is simple. The disadvantage is that if there are too many texts, there will still be some loss of efficiency. In fact, I think we can try it if we have the opportunity to use Freetype.


Of course, I also learned a new trick. C ++ also provided the method of calling Java in jni. Haha, the code will be posted below:



bool getBitmapFromJava(const char *text, int nWidth, int nHeight, CCImage::ETextAlign eAlignMask, const char * pFontName, float fontSize){  JniMethodInfo methodInfo;if (! JniHelper::getStaticMethodInfo(methodInfo, "org/cocos2dx/lib/Cocos2dxBitmap", "createTextBitmap",        "(Ljava/lang/String;Ljava/lang/String;IIII)V"))    {      CCLOG("%s %d: error to get methodInfo", __FILE__, __LINE__);      return false;   }    jstring jstrText = methodInfo.env->NewStringUTF(text);    jstring jstrFont = methodInfo.env->NewStringUTF(pFontName);   methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, jstrText,     jstrFont, (int)fontSize, eAlignMask, nWidth, nHeight);    methodInfo.env->DeleteLocalRef(jstrText);   methodInfo.env->DeleteLocalRef(jstrFont);   methodInfo.env->DeleteLocalRef(methodInfo.classID);  return true;}static bool getStaticMethodInfo_(cocos2d::JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode){   jmethodID methodID = 0;  JNIEnv *pEnv = 0;  if (! getEnv(&pEnv))    {        break;   }   jclass classID = getClassID_(className, pEnv);    methodID = pEnv->GetStaticMethodID(classID, methodName, paramCode); 




With reference to the annotations in it, the C ++ driver implements Java rendering. After Java completes the painting, call the Java_org_cocos2dx_lib_Cocos2dxBitmap_nativeInitBitmapDC interface to copy the memory. m_pData in s_bmp DC is used to save the texture, transfer the Rectification Process.


Summary
After the introduction, the technology used by cocos2d is not mysterious throughout the process. It is mainly a familiar process. the most commendable is the comparative use of JNI encapsulation. It is used for game development. Basically all functions will be closed in C ++. You only need to provide a standard Java shell, it is efficient across platforms. in addition, cocos2d makes a trade-off between the language of each platform, Java for convenience, and C ++ for platform consistency.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.