【COCOS2DX-LUA 脚本开发之十四】解决自定义CPP类通过TOLUA++ BINDING LUACOCOS2D后编译到ANDROID运行黑屏(没有调用自定义CPP类)的问题!

本站文章均为 李华明Himi 原创,转载务必在明显处注明:(作者新浪微博: @李华明Himi 
转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/lua-game/1388.html
 

          ☞ 点击订阅 ☜
 本博客最新动态!及时将最新博文通知您!


                 

唉,首先说点闲话 – -。Himi搞了不短的时间,这个问题一直没有解决,最后终于在张大(cocos2dx引擎开发者之一 张小明)的指导下解决了此问题。

本章基于上一篇  【COCOS2DX-LUA 脚本开发之十三】  与之前的项目整合 【Cocos2d-X(2.x) 游戏开发系列之二】cocos2dx最新2.x版本跨平台整合NDK+Xcode,Xcode编写&编译代码,Android导入打包运行即可!

在进入正文之前,讲解下一些基础知识:(当前Himi的版本是cocos2xx 2.1.2 hotfix)

第一部分:

编译过项目到Android的童鞋们肯定知道创建好的Android项目下的jni下的Android.mk 这个文件,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE := game_shared
 
LOCAL_MODULE_FILENAME := libgame
 
LOCAL_SRC_FILES := hellocpp/main.cpp \
                    ../../Classes/AppDelegate.cpp
 
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes
 
LOCAL_STATIC_LIBRARIES := curl_static_prebuilt                
 
LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocosdenshion_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_lua_static
LOCAL_WHOLE_STATIC_LIBRARIES += cocos_extension_static
 
include $(BUILD_SHARED_LIBRARY)
 
$(call import-module,cocos2dx)
$(call import-module,CocosDenshion/android)
$(call import-module,scripting/lua/proj.android/jni)
$(call import-module,cocos2dx/platform/third_party/android/prebuilt/libcurl)
$(call import-module,extensions)

这个文件中,主要我们关注如下几个配置:‘

1.  LOCAL_SRC_FILES  :  编译到Android的本地的类cpp或c,比如自定义了一个类HSprite.h  HSprite.cpp

那么需要添加到这个 LOCAL_SRC_FILES 中,如下:

1
2
3
LOCAL_SRC_FILES := hellocpp/main.cpp \
                    ../../Classes/AppDelegate.cpp \
                    ../../Classes/HSprite.cpp

 

2. LOCAL_C_INCLUDES  :编译的本地类所在的路径,例如你有一个HSprite类放在Himi的文件夹中,那么你可以如下形式添加:

1
2
3
4
5
6
7
8
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes \
                     $(LOCAL_PATH)/../../Classes/Himi
 
那么在你其他的类进行引用Himi文件夹下的HSprite时,无需写完整路径,如下:
#include "Himi/HSprite.h"
 
可以直接如下导入:
#include "HSprite.h"

3.     LOCAL_STATIC_LIBRARIES  : 添加所需要链接的静态库

 

本章需要关注的是如下的配置:

4.    call import-module    :   编译对应的模块!

       $(call import-module,cocos2dx)  :具体是从 NDK_MODULE_PATH 路径下的cocos2dx文件夹下的Android.mk

 

那么 NDK_MODULE_PATH 是指向哪里呢?哪里设置呢?下面详细讲解!

 

第二部分:

编译过项目到Android的童鞋们肯定也知道build_native.sh 这个文件,NDK_MODULE_PATH的路径也在此文件中进行设置, 如下图:

如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
APPNAME= "Tuc4Android"
 
# options
 
buildexternalsfromsource=
 
usage(){
cat << EOF
usage: $0 [options]
 
Build C/C++ code for $APPNAME using Android NDK
 
OPTIONS:
-s  Build externals from source
-h  this help
EOF
}
 
while getopts "sh" OPTION; do
case "$OPTION" in
s)
buildexternalsfromsource=1
;;
h)
usage
exit 0
;;
esac
done
 
# paths
 
if [ -z "${NDK_ROOT+aaa}" ];then
echo "please define NDK_ROOT"
exit 1
fi
 
DIR= "$( cd " $( dirname "${BASH_SOURCE[0]}" ) " && pwd )"
# ... use paths relative to current directory
COCOS2DX_ROOT= "/Users/slater/Documents/cocos2d-2.1rc0-x-2.1.2-hotfix"
APP_ROOT= "/Users/slater/Desktop/TestUserCpp/TestUserCpp"
APP_ANDROID_ROOT= "/Users/slater/Desktop/TestUserCpp/TestUserCpp/proj.android"
 
echo "NDK_ROOT = $NDK_ROOT"
echo "COCOS2DX_ROOT = $COCOS2DX_ROOT"
echo "APP_ROOT = $APP_ROOT"
echo "APP_ANDROID_ROOT = $APP_ANDROID_ROOT"
 
# make sure assets is exist
if [ -d "$APP_ANDROID_ROOT" /assets ]; then
     rm -rf "$APP_ANDROID_ROOT" /assets
fi
 
mkdir "$APP_ANDROID_ROOT" /assets
 
# copy resources
for file in "$APP_ROOT" /Resources/*
do
if [ -d "$file" ]; then
     cp -rf "$file" "$APP_ANDROID_ROOT" /assets
fi
 
if [ -f "$file" ]; then
     cp "$file" "$APP_ANDROID_ROOT" /assets
fi
done
 
# copy icons (if they exist)
file= "$APP_ANDROID_ROOT" /assets/Icon-72.png
if [ -f "$file" ]; then
     cp "$file" "$APP_ANDROID_ROOT" /res/drawable-hdpi/icon.png
fi
file= "$APP_ANDROID_ROOT" /assets/Icon-48.png
if [ -f "$file" ]; then
     cp "$file" "$APP_ANDROID_ROOT" /res/drawable-mdpi/icon.png
fi
file= "$APP_ANDROID_ROOT" /assets/Icon-32.png
if [ -f "$file" ]; then
     cp "$file" "$APP_ANDROID_ROOT" /res/drawable-ldpi/icon.png
fi
 
if [[ "$buildexternalsfromsource" ]]; then
     echo "Building external dependencies from source"
     "$NDK_ROOT" /ndk-build -C "$APP_ANDROID_ROOT" $* \
         "NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/source"
else
     echo "Using prebuilt externals"
     "$NDK_ROOT" /ndk-build -C "$APP_ANDROID_ROOT" $* \
         "NDK_MODULE_PATH=${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt"
fi

在之前我们整合项目编译到Android时其中我们需要关注的是 COCOS2DX_ROOT、 APP_ROOT、 APP_ANDROID_ROOT这三个路径的设置。

那么本次我们关注的是最下方  NDK_MODULE_PATH  是用于配置搜索编译模块的基础路径! 此路径与第一部分的Android.mk中 call import-module  相关!

${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt”

表示两个路径,一个是COCOS2DX_ROOT的路径,另外一个是COCOS2DX_ROOT路径下的/cocos2dx/platform/third_party/android/prebuilt

 

通过如上两个知识点的简单的介绍,大家可能会对编译过程更深一步的理解。

现在开始讲解本章重点:  解决自定义cpp类通过tolua++ binding LuaCocos2d后编译到Android运行黑屏(没有调用自定义cpp类)的问题!

如果大家没有自定义类binding到LuaCocos2d中那么编译Android绝对是正确运行的,但是难免会自定义一些类供lua脚本使用,一般我们可以通过tolua++进行binding到LuaCocos2d中(参考Himi的另外一篇文章:【COCOS2DX-LUA 脚本开发之四】使用tolua++编译pkg,从而创建自定义类让Lua脚本使用

当正确binding到LuaCocos2d后,我们iphone模拟器运行后一切正常,那么当编译到Android后,总是出现黑屏,并屏幕显示有0个精灵 !

错误出在哪里呢?!首先我们最容易想到的是检查看 Android项目下jni下的Android.mk中的LOCAL_SRC_FILES 是否包含了你自定义的类!确定是否参与编译了!

如果确定参与编译了,并Android项目能正常运行,但是还是运行黑屏的话,那么你可以打印lua中调用的自定义类!最后会发现打印语句编译到Android后,根本没打印!基本上那就可以判定是LuaCocos2d这个类中并没有binding你自定义类!

有些童鞋就奇怪说可以确定xcode项目下的LuaCocos2d类中确实binding了自定义类啊!!

是的,但是你看到的只是ios项目所用的LuaCocos2d, 真正编译到Android后的LuaCocos2d根本不是ios项目下的LuaCocos2d这个类!!

那么到底是哪里的LuaCocos2d被编译到Android了呢?其实不难发现,通过Android.mk中看到编译lua模块的语句:

$(call import-module,scripting/lua/proj.android/jni)   : 我们可以知道它指向cocos2dx引擎下的scripting/lua/proj.android/jni/Android.mk

路径如下:

QQ20130427-1

 

打开后内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
 
LOCAL_MODULE    := cocos_lua_static
 
LOCAL_MODULE_FILENAME := liblua
 
LOCAL_SRC_FILES :=../../lua/lapi.c \
                   ../../lua/lauxlib.c \
           ../../lua/lbaselib.c \
           ../../lua/lcode.c \
           ../../lua/ldblib.c \
           ../../lua/ldebug.c \
           ../../lua/ldo.c \
           ../../lua/ldump.c \
           ../../lua/lfunc.c \
           ../../lua/lgc.c \
           ../../lua/linit.c \
           ../../lua/liolib.c \
           ../../lua/llex.c \
           ../../lua/lmathlib.c \
           ../../lua/lmem.c \
           ../../lua/loadlib.c \
           ../../lua/lobject.c \
           ../../lua/lopcodes.c \
           ../../lua/loslib.c \
           ../../lua/lparser.c \
           ../../lua/lstate.c \
           ../../lua/lstring.c \
           ../../lua/lstrlib.c \
           ../../lua/ltable.c \
           ../../lua/ltablib.c \
           ../../lua/ltm.c \
           ../../lua/lua.c \
           ../../lua/lundump.c \
           ../../lua/lvm.c \
           ../../lua/lzio.c \
           ../../lua/print.c \
           ../../tolua/tolua_event.c \
           ../../tolua/tolua_is.c \
           ../../tolua/tolua_map.c \
           ../../tolua/tolua_push.c \
           ../../tolua/tolua_to.c \
           ../../cocos2dx_support/CCLuaBridge.cpp \
           ../../cocos2dx_support/CCLuaEngine.cpp \
           ../../cocos2dx_support/CCLuaStack.cpp \
           ../../cocos2dx_support/CCLuaValue.cpp \
           ../../cocos2dx_support/Cocos2dxLuaLoader.cpp \
           ../../cocos2dx_support/LuaCocos2d.cpp \
           ../../cocos2dx_support/tolua_fix.c
 
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../lua \
                            $(LOCAL_PATH)/../../tolua \
                            $(LOCAL_PATH)/../../cocos2dx_support
 
LOCAL_C_INCLUDES := $(LOCAL_PATH)/ \
                     $(LOCAL_PATH)/../../lua \
                     $(LOCAL_PATH)/../../tolua \
                     $(LOCAL_PATH)/../../../../cocos2dx \
                     $(LOCAL_PATH)/../../../../cocos2dx/include \
                     $(LOCAL_PATH)/../../../../cocos2dx/platform \
                     $(LOCAL_PATH)/../../../../cocos2dx/platform/android \
                     $(LOCAL_PATH)/../../../../cocos2dx/kazmath/include \
                     $(LOCAL_PATH)/../../../../CocosDenshion/include
 
LOCAL_CFLAGS += -Wno-psabi
LOCAL_EXPORT_CFLAGS += -Wno-psabi
 
include $(BUILD_STATIC_LIBRARY)

从这个mk文件的内容中我们可以看到参与编译的LuaCocos2d类是相对于当前Android.mk 路径的  ../../cocos2dx_support/LuaCocos2d.cpp \

从上面的附上的图可以清楚的看到这个路径,是当前Android.mk的路径的上两层后的目录下的cocos2dx_support的LuaCocos2d.cpp文件!

可能讲到这里,很多童鞋应该恍然大悟了吧!

虽然我们自定义类通过tolua++ binding到项目下的LuaCococs2d 中,但是参与Android编译的LuaCocos2d并不是你项目下的!

      OK,那下面给出几种解决方式:

      第一种:将我们项目下的已经binding好的LuaCococs2d类替换参与编译的LuaCococs2d类!

                     (注:LuaCococs2d.h中导入的自定义类路径,引用你项目下的对应类即可)

     

    第二种: 将编译的Lua模块的Android.mk中的参与编译的LuaCococs2d路径改成自己项目下的LuaCococs2d路径即可。

    

    第三种: 通过修改 NDK_MODULE_PATH 路径,将其指向我们项目下的libs路径,然后将参与编译的缺少模块copy到我们的项目下对应路径即可!

这个问题其实比较容易解决,但是主要的是理解原理!否则会越忙越乱!

更多 0
### Cocos2d-x Lua 基础教程和资源 #### 初始化环境设置 为了开始使用Cocos2d-x Lua进行游戏开发,首先需要加载`cocos/init.lua`文件,并依据`config.lua`配置文件完成对整个框架的初始化工作[^1]。 ```lua require "cocos.init" ``` 这段代码通常位于项目的入口处,负责引入必要的模块并按照预设参数调整引擎行为。通过这种方式,开发者能够确保每次运行程序时都处于一致的状态下。 #### 使用Lua绑定C/C++ API 对于希望扩展原生功能或是优化性能的应用来说,在Quick-Cocos2d-x环境中利用自定义的C/C++接口是非常重要的技能之一。这涉及到将底层逻辑暴露给高层脚本语言的过程——即所谓的Lua Binding[^2]。虽然当前版本仍然依赖于tolua++作为主要工具来自动化这部分流程,但随着技术进步,未来的迭代可能会探索更先进的解决方案。 #### 平台优势概述 数以百计的成功案例表明,无论是独立开发者还是大型工作室都可以信赖Quick-Cocos2d-x及其前身所提供的强大能力。该平台不仅具备高效的生产力特性(如快速原型制作),还提供了稳定的架构基础以及庞大的社区网络支持[^3]。这些因素共同构成了一个理想的创作环境,使得即使是初学者也能够在短时间内掌握核心概念和技术要点。 #### 图集管理与优化技巧 当处理大量图像资产时,合理运用Texture Atlas可以帮助显著提升渲染效率。具体而言,就是把多张小图片打包成一张较大的图集,从而减少GPU状态变化次数,进而加快绘制速度。在Cocos2d-x里,可以通过继承自`cc.Node`的对象`AtlasNode`轻松创建这样的合批对象[^4]: ```cpp auto atlas = cc::TileMapAtlas::create("tiles.png", "tilemap.plist"); this->addChild(atlas); ``` 此段代码展示了如何实例化一个新的瓦片地图图集节点,并将其添加至场景树结构之中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值