您的位置:首页 > 移动开发 > Cocos引擎

Cocos2dx工程总结

2016-02-29 00:12 429 查看

Cocos2dx 学习过程

1. 学习 Cocos2dx

Cocos官网 (这个不用说)

天涯海阁

红孩儿的博客

老G的小屋

子龙山人

Himi的博客

笨木头的博客

2. 学习 JNI 与 NDK 开发

JNI 与 NDK 开发这个必须要掌握的知识点。网上没看到比较全面的介绍。1. 学习JNI 与 NDK 开发推荐大家看Android框架揭秘第4章-JNI与NDK,讲解的简单易懂,也比较全。2. 了解 jni.c 代码

3. 解决技术难点

将图片从 Android 传递到 Cocos

* //解决思路:android 端将图片生成 byte[], 通过 jni 接口传到C生成 Texture2D*
signed char* data = (signed char*)info.env->GetByteArrayElements(bitmapinfo_byte, 0);
Texture2D* textureView = new Texture2D();
Image* image = new Image();

bool bRet = image->initWithImageData((unsigned char*)data, bitmapinfo_length);
if (textureView && textureView->initWithImage(image))
{
image->release();
}
info.env->ReleaseByteArrayElements(bitmapinfo_byte, data, 0);


将对象从 Android 传递到 Cocos (由 C 调用 JAVA 返回对象)

JniMethodInfo info;

const char* clazzName = "org.cocos2dx.cpp.AppActivity";
const char* clazzSingle = "getInstance";
const char* clazzSingleSignature = "()Ljava/lang/Object;";

const char* ExxName = "getViewBitmap";
const char* ExxSignature = "()Lcom/cocos2dx/JniClass/BitmapInfo;";

const char* BitmapInfo_getBitByte = "getBitByte";
const char* getBitByteSignature = "()[B";

const char* BitmapInfo_getLength = "getLength";
const char* getLengthSignature = "()I";

if (JniHelper::getStaticMethodInfo(info, clazzName, clazzSingle, clazzSingleSignature))
{
jclass header_class = info.env->FindClass(clazzName);
jmethodID instance_id = info.env->GetStaticMethodID(header_class, clazzSingle, clazzSingleSignature);
jobject instance_object = (jobject)info.env->CallStaticObjectMethod(header_class, instance_id);

jmethodID Exx_id = info.env->GetMethodID(header_class, ExxName, ExxSignature);
jobject bitmapinfo_object = (jobject)info.env->CallObjectMethod(instance_object, Exx_id);

jclass bitmapinfo_class = info.env->GetObjectClass(bitmapinfo_object);
jmethodID bitByte_id = info.env->GetMethodID(bitmapinfo_class, BitmapInfo_getBitByte, getBitByteSignature);
jbyteArray bitmapinfo_byte = (jbyteArray)info.env->CallObjectMethod(bitmapinfo_object, bitByte_id);

jmethodID length_id = info.env->GetMethodID(bitmapinfo_class, BitmapInfo_getLength, getLengthSignature);
jint bitmapinfo_length = (jint)info.env->CallIntMethod(bitmapinfo_object, length_id);
}


JAVA 编写的代码

public static AppActivity appInstance;// 定义单例

public static Object getInstance() {
return appInstance;
}

public BitmapInfo getBitmap() {

BitmapInfo info = new BitmapInfo();
return info;
}

public class BitmapInfo{

private byte[] bitByte;
private int length;

public byte[] getBitByte() {
return bitByte;
}

public void setBitByte(byte[] bitByte) {
this.bitByte = bitByte;
}

public int getLength() {
return length;
}

public void setLength(int length) {
this.length = length;
}
}


将对象从 Android 传递到 Cocos (由 JAVA 将对象传给 C )

JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_strokeViewonPenUp(JNIEnv *env, jobject clazz, jobject object)
{
const char* fuctionA = "A";
const char* fuctionASignature = "()Z";

const char* fuctionB = "B";
const char* fuctionBSignature = "()I";

const char* fuctionC = "C";
const char* fuctionCSignature = "()I";

JudgementResult* result = new JudgementResult();

jclass result_class = env->GetObjectClass(object);

jmethodID A_id = env->GetMethodID(result_class, fuctionA, fuctionASignature);
result->setA((bool)env->CallBooleanMethod(object, A_id));

jmethodID B_id = env->GetMethodID(result_class, fuctionB, fuctionBSignature);
result->setB((int)env->CallIntMethod(object, B_id));

jmethodID C_id = env->GetMethodID(result_class, fuctionC, fuctionCSignature);
result->setC((int)env->CallIntMethod(object, C_id));

result->retain();

NotificationCenter::getInstance()->postNotification(msg_HYH_Penup, result);
}


JAVA 编写的代码

public native void strokeViewonPenUp(Object result);


将数组对象从 Cocos 传递到 Android (由 C 将数组对象传给 JAVA )

void CLASS::initView(__Array* mDataArray)
{
if (mDataArray == nullptr)
{
return;
}

int size = mDataArray->count();

JniMethodInfo info;

const char* clazzName = "org.cocos2dx.cpp.AppActivity";
const char* clazzSingle = "getInstance";
const char* clazzSingleSignature = "()Ljava/lang/Object;";
const char* fuctionName = "initView";
const char* fuctionSignature = "([Lcom/cocos2dx/ViewData;)V";

const char* ViewDataClazz = "com/cocos2dx/ViewData";
const char* ViewDataConstructor = "<init>";
const char* ViewDataConstructorSignature = "()V";

const char* SetA = "setA";
const char* setASignature = "(Ljava/lang/String;)V";

const char* setB = "setB";
const char* setBSignature = "(I)V";

if (JniHelper::getStaticMethodInfo(info, clazzName, clazzSingle, clazzSingleSignature))
{
jclass header_class = info.env->FindClass(clazzName);
jmethodID instance_id = info.env->GetStaticMethodID(header_class, clazzSingle, clazzSingleSignature);
jobject instance_object = (jobject)info.env->CallStaticObjectMethod(header_class, instance_id);
jmethodID fuction_id = info.env->GetMethodID(header_class, fuctionName, fuctionSignature);

jobjectArray viewDataArray;

jclass clsViewData = info.env->FindClass(ViewDataClazz);
if (clsViewData == NULL)
{
cocos2d::log("null");
return;
}
viewDataArray = info.env->NewObjectArray(size, clsViewData, NULL);
if (viewDataArray == NULL) {
cocos2d::log("null");
return;
}
for (int i = 0; i < size; ++i) {

ViewData *data = (ViewData *)mDataArray->objectAtIndex(i);

jmethodID viewDataFuction_id = info.env->GetMethodID(clsViewData, ViewDataConstructor, ViewDataConstructorSignature);
jobject viewDataObject = info.env->NewObject(clsViewData, viewDataFuction_id);//对象无参构造函数

viewDataFuction_id = info.env->GetMethodID(clsViewData, SetA, setASignature);
jstring jword = info.env->NewStringUTF(data->getA());
info.env->CallVoidMethod(viewDataObject, viewDataFuction_id, jword);
info.env->DeleteLocalRef(jword);

viewDataFuction_id = info.env->GetMethodID(clsViewData, setB, setBSignature);
info.env->CallVoidMethod(viewDataObject, viewDataFuction_id, data->getB());

info.env->SetObjectArrayElement(viewDataArray, i, viewDataObject);
info.env->DeleteLocalRef(viewDataObject);
}
//
info.env->CallVoidMethod(instance_object, fuction_id, viewDataArray);
}
return;
}


读取SD卡中图片

有时图片资源太大,如果直接放在apk中,会使安装包很大。采用的策略:将资源单独下载,资源缓存到SD卡中,然后读取SD卡中的资源

Texture2D* getTexture(const char* filePath)
{
char * TextureBuffer;
long length;
ifstream in(filePath, ios::in | ios::binary | ios::ate);
length = in.tellg();
log("length.2=%ld", length);
in.seekg(0, ios::beg);
TextureBuffer = new char[length + 1];
in.read(TextureBuffer, length);
in.close();
TextureBuffer[length] = '\0';//防止内存问题

Image *image = new Image();
if (false == image->initWithImageData((unsigned char*)TextureBuffer, length))
{
log("cocos2dx can not load PNG");
}
delete[] TextureBuffer;
Texture2D * texture2D = new Texture2D();
texture2D->initWithImage(image);
image->release();
return texture2D;
}


Cocos2dx 由 JAVA 与 C 层传递数据的几种解决方案

在 C 端采用全局变量,将数据存到全局变量中,只能主动读取全局变量(缺点:不知道变量何时更新)

不管是 C 到 Java,还是 Java 到 C,就是把数据组装成json然后转成字符串传递(缺点:效率比较低)

在 C 端使用 NotificationCenter 消息机制,将数据打包分发(优点:异步回调)

使用 Android View 控件

之前做过一个项目,需要用到 Android 中的自定义的 View 控件,如何解决呢,这就需要了解 Android 框架。参考Android源码设计模式解析与实战第15章的深度拓展。

查看 Cocos2dxActivity.java 中

@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CocosPlayClient.init(this, false);

onLoadNativeLibraries();

sContext = this;
this.mHandler = new Cocos2dxHandler(this);

Cocos2dxHelper.init(this);

this.mGLContextAttrs = getGLContextAttrs();
this.init();

if (mVideoHelper == null) {
mVideoHelper = new Cocos2dxVideoHelper(this, mFrameLayout);
}

if(mWebViewHelper == null){
mWebViewHelper = new Cocos2dxWebViewHelper(mFrameLayout);
}
}


查看 init();

protected FrameLayout mFrameLayout = null;
// ===========================================================
// Methods
// ===========================================================
public void init() {

// FrameLayout
ViewGroup.LayoutParams framelayout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT);
mFrameLayout = new FrameLayout(this);
mFrameLayout.setLayoutParams(framelayout_params);

// Cocos2dxEditText layout
ViewGroup.LayoutParams edittext_layout_params =
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
Cocos2dxEditText edittext = new Cocos2dxEditText(this);
edittext.setLayoutParams(edittext_layout_params);

// ...add to FrameLayout
mFrameLayout.addView(edittext);

// Cocos2dxGLSurfaceView
this.mGLSurfaceView = this.onCreateView();

// ...add to FrameLayout
mFrameLayout.addView(this.mGLSurfaceView);

// Switch to supported OpenGL (ARGB888) mode on emulator
if (isAndroidEmulator())
this.mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

this.mGLSurfaceView.setCocos2dxRenderer(new Cocos2dxRenderer());
this.mGLSurfaceView.setCocos2dxEditText(edittext);

// Set framelayout as the content view
setContentView(mFrameLayout);
}


setContentView(mFrameLayout); 这个就是需要找到的。

所以对于 Android 自定义 View 添加到 mFrameLayout 即可。

4. 现在使用比较多的引擎

Cocos Creator(多平台)

白鹭HTML引擎(多平台)

Unity3d(3D)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: