Cocos2dx工程总结

Cocos2dx 学习过程

1. 学习 Cocos2dx

  1. Cocos官网 (这个不用说)
  2. 天涯海阁
  3. 红孩儿的博客
  4. 老G的小屋
  5. 子龙山人
  6. Himi的博客
  7. 笨木头的博客

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 层传递数据的几种解决方案

  1. 在 C 端采用全局变量,将数据存到全局变量中,只能主动读取全局变量(缺点:不知道变量何时更新)
  2. 不管是 C 到 Java,还是 Java 到 C,就是把数据组装成json然后转成字符串传递(缺点:效率比较低)
  3. 在 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. 现在使用比较多的引擎

  1. Cocos Creator(多平台)
  2. 白鹭HTML引擎(多平台)
  3. Unity3d(3D)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Box2D和Cocos2D是两个游戏开发框架。Box2D是一个用于物理模拟的开源库,可以模拟刚体的运动和碰撞等物理效果。Cocos2D是一个用于2D游戏开发的跨平台框架,提供了丰富的图形渲染和用户交互功能。\[1\] 在使用Cocos2D和Box2D进行游戏开发时,你可以利用Box2D来处理游戏中的物理效果,比如重力、碰撞和刚体运动等。Cocos2D提供了与Box2D的集成,使得开发者可以方便地在Cocos2D中使用Box2D的功能。你可以通过创建物理世界、添加刚体和设置碰撞检测等来实现游戏中的物理效果。\[2\] 如果你刚刚接触Cocos2D和Box2D,建议你先学习Cocos2D和Box2D的基础知识,然后再深入学习如何在Cocos2D中使用Box2D。你可以参考一些入门教程,比如《Cocos2D入门》和《Box2D入门》。如果你对OpenGL ES 2.0和自定义Cocos2D 2.X着色器等背景知识感到困惑,你可以查阅相关教程来获取更多的帮助。\[3\] #### 引用[.reference_title] - *1* *3* [如何使用Box2D和Cocos2D制作一款像Fruit Ninja一样的游戏-第1部分](https://blog.csdn.net/kaka626/article/details/9397825)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [用Box2D和cocos2d-x制作弹弓类游戏](https://blog.csdn.net/qq55008307/article/details/8090839)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值