Nostalgiachild 2012-01-13
一、问题
下午花了几个小时看ONScripter on Android的代码
http://onscripter.sourceforge.jp/android/android.html
http://code.google.com/p/onscripter/
它是基于libsdl-android的
http://libsdl-android.sourceforge.net/
https://github.com/pelya/commandergenius/archives/sdl_android
我尝试把原有的ONScripter核心代码删除,只保留libsdl.so
然后用原有框架运行SDL代码包中的示例graywin(单击窗口画一个随机大小的灰色矩形),
如下图所示:

移植graywin的过程中发现以下问题:
1)DrawBox有时会突然退出程序
我把它改为矩形不越出舞台,这个问题就消除
(另外,貌似无法使用双缓冲模式,
虽然我执行了videoflags = SDL_DOUBLEBUF,但
screen->flags & SDL_DOUBLEBUF总是false
)
void DrawBox(SDL_Surface *screen, int X, int Y, int width, int height)
{
static unsigned int seeded = 0;
SDL_Rect area;
Uint32 color;
Uint32 randc;
__android_log_print(ANDROID_LOG_INFO, "libgraywin", "DrawBox 01");
/* Seed the random number generator */
if ( seeded == 0 ) {
srand(time(NULL));
seeded = 1;
}
__android_log_print(ANDROID_LOG_INFO, "libgraywin", "DrawBox 02");
/* Get the bounds of the rectangle */
area.w = (rand()%width);
area.h = (rand()%height);
area.x = X-(area.w/2);
area.y = Y-(area.h/2);
if (area.x < 0)
area.x = 0;
if (area.y < 0)
area.y = 0;
if (area.x > width)
area.x = width;
if (area.y > height)
area.y = height;
if (area.x + area.w > width)
area.w = width - area.x;
if (area.y + area.h > height)
area.h = height - area.y;
randc = (rand()%NUM_COLORS);
if (screen->format->BytesPerPixel==1)
{
color = randc;
}
else
{
color = SDL_MapRGB(screen->format, randc, randc, randc);
}
__android_log_print(ANDROID_LOG_INFO, "libgraywin", "DrawBox 03, %x", color);
/* Do it! */
SDL_FillRect(screen, &area, color);
__android_log_print(ANDROID_LOG_INFO, "libgraywin", "DrawBox 04");
if ( screen->flags & SDL_DOUBLEBUF ) {
__android_log_print(ANDROID_LOG_INFO, "libgraywin", "DrawBox 05");
SDL_Flip(screen);
} else {
__android_log_print(ANDROID_LOG_INFO, "libgraywin", "DrawBox 05 else, %d, %d, %d, %d",
area.w, area.h, area.x, area.y);
SDL_UpdateRects(screen, 1, &area);
}
__android_log_print(ANDROID_LOG_INFO, "libgraywin", "DrawBox end");
}2)SDL_main入口被两次调用。
原来的代码中调用了两次SDL_main(在Java中的JNI接口是Video.java中的DemoRenderer类native函数nativeInit)
private native void nativeInit(String currentDirectoryPath, boolean oo, boolean dr);
第一次调用在构造函数,第二次调用在onDrawFrame
我把构造函数的那个调用注释掉。
二、总结
我猜测它的显示模块运行原理是
Java端:在SurfaceView中初始化OpenGL ES,然后通过JNI调用graywin的SDL_main(被宏替换掉的main函数)
JNI(C/C++)端:接收鼠标输入消息,然后调用OpenGL ES的C接口显示灰色矩形。
总体来说:
1. 比OpenGL要容易移植(代码改动很少)
2. JNI的代码实在很难调,所以移植这库的人应该是神级了。
3. 虽说SDL库和OpenGL一样是底层库(玩过SDL的人都知道,它没有画线的API)。
不过它用途较广泛(可以处理输入设备和音频输出),基于它的开源库似乎也较多些(更适合C开发者使用)。