通过Android平台移植魂斗罗游戏来阐述下jni的用法(把魂斗罗游戏嵌入到FC游戏模拟器里,省去了SD卡加载ROM)

出发点: 传统的游戏模拟器(FC,neo,fba,gba,mame,n64,nds,psp)都陆陆续续移植到Android手机里了,然后把游戏ROM保存到SD卡里通过模拟器运行,但是考虑到手机游戏要遵循快进快出的原则,所以我在此基础上实现了如下几点微创新

1. 直接把游戏ROM放在Android的APK里,点击应用就开始游戏,省去了通过文件浏览器查找游戏的过程。

2. 通过插值算法把游戏画面放大到支持Android平板分辨率

3. 充分利用手机重力感应器的独有特性(相对于其它两块屏,PC显示器和电视),通过手机sensor作为方向键

 

移植步骤:

1. 选择开源的基于Linux的FC游戏模拟器

2. 实现java访问C层的JNI接口

 public class Game { public static native void loadGame(byte[] data) throws IllegalStateException; public static native void destroyGame() throws IllegalStateException; public static native void sendEvent(int keyState,int event) throws IllegalStateException; public static native void setVideoSurface(Surface surface) throws IllegalStateException; public static native void setSkipFrame(int skip); }

3. Android的Acitvity Layout布局时用RalativieLayout,将五项键和按键分别浮动在游戏界面的两端。

 

 

常用的JNI实战经验可以通过jni spec获取,这里要注意以下几点:

1. 如果定义的是static native方法,在C/C++代码里不能用GetObjectClass获取对象的类

2. 如果是Java和C/C++层需要共享内存,可以用GetDirectBufferAdress() API

3. jchar占两个字节(typedef unsigned short  jchar;)

4. 全局引用记得释放(NewGlobalRef,DeleteGlobalRef)

5  可以在jni里(也就是在C/C++层)抛出Java需要捕获的异常,如:

int jniThrowException(JNIEnv* env, const char* className, const char* msg) { jclass exceptionClass = env->FindClass(className); if (exceptionClass == NULL) { __android_log_print(ANDROID_LOG_ERROR, TAG, "Unable to find exception class %s", className); return -1; } if (env->ThrowNew(exceptionClass, msg) != JNI_OK) { __android_log_print(ANDROID_LOG_ERROR, TAG, "Failed throwing '%s' '%s'", className, msg); } return 0; }

6. 最好是把native方法一次性注册。

 

运行结果:

 

 

下载:魂斗罗

 

你可能感兴趣的:(Android平台)