版本说明
3.x的最新版本是 cocos2d-x 3.17.2 ,4.x的最新版本是 cocos2d-x4.0
。
3.x的架构图:
4.x的架构图:
可以明显地看出:从4.0开始,不再只是JavaScript
引擎,也不再支持网页端,支持网页端的JavaScript
部分被单独剥离出来,统一使用Cocos Creator
来完成。因此定位就比较清晰了,Cocos Creator
主打小游戏的开发,当然也支持网页端,cocos2dx4.0
开始只支持原生端的Lua和C++。因为网页端的小游戏本身就可以在原生端运行,因此以后主推的开发平台就是Cocos Creator
,并配合TypeScript
语言进行开发。cocos2dx
基本上已经成为了过去式,但是也不代表无法使用,如果需要,仍然可以使用该引擎进行开发,相信很多团队都有很多适合自己的版本。
环境配置
官方的安装编译环境要求:Build Requirements - cocos2d-x
下载解压 cocos2d-x 3.17.2 ,并把
X:\cocos2d-x-3.17.2\tools\cocos2d-console\bin
设置到环境变量Path
中,使得可以直接使用cocos
命令。如果未设置到环境变量中,使用绝对路径也可以。Python 2.7.5+, Python 2,7.10 reccomended, NOT Python 3+
- 安装Python2,并设置Python安装路径到环境变量
Path
中,使得直接使用python
命令能够调用到该Python2。
- 安装Python2,并设置Python安装路径到环境变量
NDK r91c+ is required to build Android games (tested with r19c) May be called 19.2.xx from within Android Studio
Android Studio 3.4+ to build Android games (tested with 3.0)。 也可以不安装,不影响使用命令行打包。
Java8 Downloads - Oracle download java from oracle without login
安装。执行:
python setup.py
,主要是按照提示设置两个路径:NDK
路径和AndroidSDK
路径,设置好后重新打开控制台终端。新建项目:
cocos new HelloWorld -p com.xx.yy -l lua -d F:\CocosProjects
,提示是否同意发送数据时,可以选择N(不同意。)修改64位支持:修改
gradle.properties
:PROP_APP_ABI=arm64-v8a
运行项目
Windows版本:
VisualStudio
打开\frameworks\runtime-src\proj.win32
目录下的sln
文件即可。Android版本:进入
frameworks\runtime-src\proj.android
文件夹,运行如下命令:cocos run -p android
待
gradle
相关配置更新或下载完成,运行至真机/模拟器查看效果。或者直接用AndroidStudio打开frameworks\runtime-src\proj.android
编译
AndroidStudio老版本
使用官方推荐的AndroidStudio
版本,以及老的gradle
版本:
// 配置java8
classpath 'com.android.tools.build:gradle:3.1.0'
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
如果不想安装老版本的AndroidStudio
,则可以直接用gradle
进行命令行编译。如果官方的gradle比较慢的话,可以使用国内镜像,例如:
https://mirrors.cloud.tencent.com/gradle/gradle-4.4-all.zip
编译完成后,在app\build\outputs\apk
目录下生成相应的debug
和release
(未签名)的APK
,其中debug
版本的lua
脚本是明文的,release
版本的lua
脚本被编译为luajit
,文件扩展名为.luac
。Lua编译工具使用的是tools\cocos2d-console\plugins\plugin_luacompile
,cocos2d-x-3.17.2
使用的 LuaJIT 版本信息为:LuaJIT 2.1.0-beta2
,GitHub镜像:https://github.com/LuaJIT/LuaJIT
错误及解决方法。
Invalid revision: 3.18.1-g262b901-dirty
解决:这个是因为使用了较高版本CMake导致,手动修改使用较低版本即可,步骤如下:
- 打开AndroidStudio菜单的Tools - SDK Manager,选择 SDK Tools , 勾选「Show Package Details」,向下滑动一直找到CMake,把CMake高版本的都去掉,只保留一个3.6版本的。
- 这个时候可能还不行,还需要删除安卓SDK目录(例如:D:\Android\Sdk)下的临时文件夹(.temp),清除缓存后才能生效。
gradle Task :Demo:lint FAILED
解决:这个是因为编译的时候把lint警告也当做错误,从而终止了编译。解决办法就是不把警告当错误即可,在app/build.gradle
文件中添加配置:
android {
//...
lintOptions {
abortOnError false
}
}
参考: Gradle build: Execution failed for task :app:lint
AndroidStudio新版本(推荐)
笔者使用的AndroidStudio
版本信息如下:
Android Studio Iguana | 2023.2.1 Patch 2
Build #AI-232.10300.40.2321.11668458, built on April 4, 2024
Runtime version: 17.0.9+0--11185874 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
Windows 10.0
GC: G1 Young Generation, G1 Old Generation
Memory: 512M
Cores: 16
Registry:
ide.instant.shutdown=false
配置gradle
使用一个稍高的版本,但也不能太高,例如:
// 配置java8
classpath 'com.android.tools.build:gradle:4.2.2'
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
// 国内镜像:https://mirrors.cloud.tencent.com/gradle/
// 如果要使用更高版本的gradle,可能需要配置较高的Java版本,例如:Java 11
distributionUrl = https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
classpath 'com.android.tools.build:gradle:7.2.2'
Android Gradle 插件 8.3 版本说明 Android Developers
Android Studio Gradle插件版本与Gradle 版本对应关系_gradle版本对应关系
配置NDK版本:
// 如果后面so文件通过外部工具进行编译,则该可以不用该配置
// 使用该配置后,可以无须再设置 ndk.dir 配置,使用AndroidStudio的SDKManager下载的NDK版本
android {
ndkVersion = "19.2.5345600" //"major.minor.build"
}
配置lib的cpu架构:
// 这样配置后,也无须设置 PROP_APP_ABI
android {
defaultConfig {
ndk {
abiFilters = ["arm64-v8a"]
//abiFilters.addAll(PROP_APP_ABI.split(':').collect { it as String })
}
}
}
配置sourceSets
:
android {
sourceSets.main {
java.srcDir "src"
res.srcDir "res"
// libs 目录设置到和 CMakeLists.txt 同级目录
//jniLibs.srcDir "libs"
jniLibs.srcDir "../../../../libs"
manifest.srcFile "AndroidManifest.xml"
}
}
文件目录结构如下:
WinAppRun.bat # 运行Win版可执行程序
libs # 存放lib文件的
arm64-v8a
libcocos2dlua.so
frameworks
res # 游戏资源目录
src # 游戏脚本目录
runtime
simulator
.cocos-project.json
.project
CMakeLists.txt
config.json
README.md
UserDefault.xml
移除jni
工程,因为AndroidStudio
加载cpp太卡了,修改调试c++
代码还是用VisualStudio
比较丝滑。直接注释下面的代码即可:
// 临时注释:工程不再包含cpp项目,否则太卡了
// externalNativeBuild {
// if (project.hasProperty('PROP_REBUILD_NDK') && PROP_REBUILD_NDK=='true') {
// if (PROP_BUILD_TYPE == 'ndk-build') {
// ndkBuild {
// path "jni/Android.mk"
// }
// } else if (PROP_BUILD_TYPE == 'cmake') {
// cmake {
// path "../../../../CMakeLists.txt"
// }
// }
// }
// }
为了灵活期间,可以增加一个配置开关来控制:
// 通过修改 gradle.properties 中的 PROP_BUILD_NDK 开关(true/false),来决定是否导入cocos的jni工程
externalNativeBuild {
if (project.hasProperty('PROP_BUILD_NDK') && PROP_BUILD_NDK=='true') {
if (PROP_BUILD_TYPE == 'ndk-build') {
ndkBuild {
path "jni/Android.mk"
}
} else if (PROP_BUILD_TYPE == 'cmake') {
cmake {
path "../../../../CMakeLists.txt"
}
}
}
}
gradle.properties
文件中增加一个 PROP_BUILD_NDK
默认设置为false
即可。
修改variant.mergeAssetsProvider.get().doLast
任务,使得可以根据gradle版本不同进行不同的处理:
// 打印当前Gradle版本
println "Current Gradle version: ${gradle.gradleVersion}"
// 判断Gradle版本并执行不同逻辑
if (gradle.gradleVersion.startsWith("4.")) {
tempDir = "${buildDir}/intermediates/assets/${variant.dirName}"
} else {
tempDir = "${buildDir}/intermediates/merged_assets/${variant.dirName}/out"
}
println "intermediates path: ${tempDir}"
def tempSrc = "${tempDir}/src"
def resSrc = "${tempDir}/res"
完整的gradle
文件内容见后文。
常见错误
错误:cvc-complex-type.2.4.a: 发现了以元素 'base-extension' 开头的无效内容。应以 '{layoutlib}' 之一开头。
解决:升级Gradle。
Unable to start the daemon process.
The project uses Gradle 4.6 which is incompatible with Java 11 or newer.
Possible solution:
- Upgrade Gradle wrapper to 7.2 version and re-import the project
// 解决办法:settings搜索gradle,修改gradle sdk版本为1.8
No version of NDK matched the requested version 20.0.5594570. Versions available locally: 23.1.7779620, 25.1.8937393, 25.2.9519653, 26.1.10909125
// 解决办法:local.properties添加:
ndk.dir=D\:\\NDK\\android-ndk-r19c
// 新版本在gradle里配置:
android {
ndkVersion = "19.2.5345600" //"major.minor.build"
}
ld: error: lib/libluacocos2d.a(CCLuaEngine.cpp.o): unable to find library from dependent library specifier: lua51.lib
// 解决办法:
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
#pragma comment(lib,"lua51.lib")
#endif
Cocos 4.0新建lua项目安卓打包报错,CCLuaEngine,lua51.lib
API 'variant.getMergeAssets()' is obsolete and has been replaced with 'variant.getMergeAssetsProvider()'.
// 解决办法:修改build.gradle,将:
variant.mergeAssets.doLast {
}
// 修改为:
variant.mergeAssetsProvider.get().doLast {
}
This app only has 32-bit [armeabi-v7a] native libraries. Beginning August 1, 2019 Google Play store requires that all apps that include native libraries must provide 64-bit versions. For more information, visit https://g.co/64-bit-requirement
Affected Modules: Bricks
// 解决办法:修改gradle.properties
// PROP_APP_ABI=armeabi-v7a
PROP_APP_ABI=arm64-v8a
缺失的类
LocalStorage
https://github.com/yangc999/jfclient/tree/master/frameworks/cocos2d-x/cocos/scripting/lua-bindings/manual/localstorage
打开VisualStudio工程,为libluacocos2d
项目添加头文件和源文件,然后在 frameworks/cocos2d-x/cocos/scripting/lua-bindings/manual/lua_module_register.cpp
中添加:
#include "scripting/lua-bindings/manual/localstorage/lua_cocos2dx_localstorage_manual.h"
register_localstorage_module(L);
还缺少对Init函数的注册,需要添加:
int lua_cocos2dx_localstorage_Init(lua_State* L) {
int argc = 0;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertable(L, 1, "cc.LocalStorage", 0, &tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
if (argc == 1) {
#if COCOS2D_DEBUG >= 1
if (!tolua_isstring(L, 2, 0, &tolua_err))
goto tolua_lerror;
#endif
std::string fullpath = tolua_tostring(L, 2, "");
localStorageInit(fullpath);
return 0;
}
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L, "#ferror in function 'lua_cocos2dx_localstorage_removeItem'.", &tolua_err);
return 0;
#endif
}
// 在 lua_register_cocos2dx_localstorage 函数中添加注册:
tolua_function(L, "init", lua_cocos2dx_localstorage_Init);
并修复lua_cocos2dx_localstorage_getItem
一个BUG:
if (localStorageGetItem(key, &value)) {
lua_pushlstring(L, value.c_str(), value.length());
return 1;
}
完整代码如下。
//lua_cocos2dx_localstorage_manual.h
#ifndef COCOS_SCRIPTING_LUA_BINDINGS_LUA_COCOS2DX_LOCALSTORAGE_MANUAL_H
#define COCOS_SCRIPTING_LUA_BINDINGS_LUA_COCOS2DX_LOCALSTORAGE_MANUAL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "tolua++.h"
#ifdef __cplusplus
}
#endif
TOLUA_API int register_localstorage_module(lua_State* L);
#endif // #ifndef COCOS_SCRIPTING_LUA_BINDINGS_LUA_COCOS2DX_CONTROLLER_MANUAL_H
//lua_cocos2dx_localstorage_manual.cpp
#include "scripting/lua-bindings/manual/localstorage/lua_cocos2dx_localstorage_manual.h"
#include "scripting/lua-bindings/manual/tolua_fix.h"
#include "scripting/lua-bindings/manual/LuaBasicConversions.h"
#include "storage/local-storage/LocalStorage.h"
int lua_cocos2dx_localstorage_setItem(lua_State* L)
{
int argc = 0;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertable(L,1,"cc.LocalStorage",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
if (argc == 2)
{
#if COCOS2D_DEBUG >= 1
if (!tolua_isstring(L, 2, 0, &tolua_err) ||
!tolua_isstring(L, 3, 0, &tolua_err))
goto tolua_lerror;
#endif
std::string key = tolua_tostring(L, 2, "");
//std::string value = tolua_tostring(L, 3, "");
size_t size = 0;
const char* data = (const char*)lua_tolstring(L, 3, &size);
std::string value(data, size);
localStorageSetItem(key, value);
return 0;
}
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_localstorage_setItem'.",&tolua_err);
return 0;
#endif
}
int lua_cocos2dx_localstorage_getItem(lua_State* L)
{
int argc = 0;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertable(L,1,"cc.LocalStorage",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
if (argc == 1)
{
#if COCOS2D_DEBUG >= 1
if (!tolua_isstring(L, 2, 0, &tolua_err))
goto tolua_lerror;
#endif
std::string key = tolua_tostring(L, 2, "");
std::string value;
if (localStorageGetItem(key, &value)) {
lua_pushlstring(L, value.c_str(), value.length());
return 1;
}
}
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_localstorage_getItem'.",&tolua_err);
return 0;
#endif
}
int lua_cocos2dx_localstorage_removeItem(lua_State* L)
{
int argc = 0;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertable(L,1,"cc.LocalStorage",0,&tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
if (argc == 1)
{
#if COCOS2D_DEBUG >= 1
if (!tolua_isstring(L, 2, 0, &tolua_err))
goto tolua_lerror;
#endif
std::string key = tolua_tostring(L, 2, "");
localStorageRemoveItem(key);
return 0;
}
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L,"#ferror in function 'lua_cocos2dx_localstorage_removeItem'.",&tolua_err);
return 0;
#endif
}
int lua_cocos2dx_localstorage_clear(lua_State* L)
{
int argc = 0;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertable(L, 1, "cc.LocalStorage", 0, &tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
if (argc == 0)
{
localStorageClear();
return 0;
}
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L, "#ferror in function 'lua_cocos2dx_localstorage_removeItem'.", &tolua_err);
return 0;
#endif
}
int lua_cocos2dx_localstorage_Init(lua_State* L) {
int argc = 0;
#if COCOS2D_DEBUG >= 1
tolua_Error tolua_err;
if (!tolua_isusertable(L, 1, "cc.LocalStorage", 0, &tolua_err)) goto tolua_lerror;
#endif
argc = lua_gettop(L) - 1;
if (argc == 1) {
#if COCOS2D_DEBUG >= 1
if (!tolua_isstring(L, 2, 0, &tolua_err))
goto tolua_lerror;
#endif
std::string fullpath = tolua_tostring(L, 2, "");
localStorageInit(fullpath);
return 0;
}
return 0;
#if COCOS2D_DEBUG >= 1
tolua_lerror:
tolua_error(L, "#ferror in function 'lua_cocos2dx_localstorage_removeItem'.", &tolua_err);
return 0;
#endif
}
int lua_register_cocos2dx_localstorage(lua_State* L)
{
tolua_usertype(L,"cc.LocalStorage");
tolua_cclass(L,"LocalStorage","cc.LocalStorage","",nullptr);
tolua_beginmodule(L,"LocalStorage");
tolua_function(L, "init", lua_cocos2dx_localstorage_Init);
tolua_function(L, "setItem", lua_cocos2dx_localstorage_setItem);
tolua_function(L, "getItem", lua_cocos2dx_localstorage_getItem);
tolua_function(L, "removeItem", lua_cocos2dx_localstorage_removeItem);
tolua_function(L, "clear", lua_cocos2dx_localstorage_clear);
tolua_endmodule(L);
std::string typeName = "localStorage";
g_luaType[typeName] = "cc.LocalStorage";
g_typeCast["LocalStorage"] = "cc.LocalStorage";
return 1;
}
int register_all_cocos2dx_localstorage(lua_State* L)
{
tolua_open(L);
tolua_module(L,"cc",0);
tolua_beginmodule(L,"cc");
lua_register_cocos2dx_localstorage(L);
tolua_endmodule(L);
return 1;
}
int register_localstorage_module(lua_State* L)
{
lua_getglobal(L, "_G");
if (lua_istable(L,-1))//stack:...,_G,
{
register_all_cocos2dx_localstorage(L);
}
lua_pop(L, 1);
return 1;
}
还要为Android工程添加这俩文件,步骤如下:
找到文件 /frameworks/cocos2d-x/cocos/scripting/lua-bindings/CMakeLists.txt
添加上述的头文件和源文件:
set(
...
manual/localstorage/lua_cocos2dx_localstorage_manual.h
)
set(
...
manual/localstorage/lua_cocos2dx_localstorage_manual.cpp
)
Gradle优化
模板创建的build.gradle
太复杂了,简单优化了下:
import org.gradle.internal.os.OperatingSystem
apply plugin: 'com.android.application'
android {
compileSdkVersion PROP_COMPILE_SDK_VERSION.toInteger()
lintOptions {
abortOnError false
}
ndkVersion = "19.2.5345600" //"major.minor.build"
defaultConfig {
applicationId "com.sing.demo"
minSdkVersion PROP_MIN_SDK_VERSION
targetSdkVersion PROP_TARGET_SDK_VERSION
versionCode 1
versionName "1.0"
ndk {
abiFilters = ["arm64-v8a"]
//abiFilters.addAll(PROP_APP_ABI.split(':').collect { it as String })
}
externalNativeBuild {
if (PROP_BUILD_TYPE == 'ndk-build') {
ndkBuild {
targets 'cocos2dlua'
arguments 'NDK_TOOLCHAIN_VERSION=clang'
arguments '-j' + Runtime.runtime.availableProcessors()
def module_paths = [project.file("../../../cocos2d-x").absolutePath,
project.file("../../../cocos2d-x/cocos").absolutePath,
project.file("../../../cocos2d-x/external").absolutePath]
if (OperatingSystem.current().isWindows()) {
module_paths = module_paths.collect { it.replaceAll('\\\\', '/') }
arguments 'NDK_MODULE_PATH=' + module_paths.join(";")
} else {
arguments 'NDK_MODULE_PATH=' + module_paths.join(':')
}
}
} else if (PROP_BUILD_TYPE == 'cmake') {
cmake {
arguments "-DCMAKE_FIND_ROOT_PATH=", "-DANDROID_STL=c++_static", "-DANDROID_TOOLCHAIN=clang", "-DANDROID_ARM_NEON=TRUE"
cppFlags "-frtti -fexceptions -fsigned-char"
}
}
}
}
sourceSets.main {
java.srcDir "src"
res.srcDir "res"
//jniLibs.srcDir "libs"
jniLibs.srcDir "../../../../libs"
manifest.srcFile "AndroidManifest.xml"
}
// 通过修改 gradle.properties 中的 PROP_BUILD_NDK 开关(true/false),来决定是否导入cocos的jni工程
externalNativeBuild {
if (project.hasProperty('PROP_BUILD_NDK') && PROP_BUILD_NDK == 'true') {
if (PROP_BUILD_TYPE == 'ndk-build') {
ndkBuild {
path "jni/Android.mk"
}
} else if (PROP_BUILD_TYPE == 'cmake') {
cmake {
path "../../../../CMakeLists.txt"
}
}
}
}
signingConfigs {
release {
if (project.hasProperty("RELEASE_STORE_FILE")) {
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
}
buildTypes {
release {
debuggable false
jniDebuggable false
renderscriptDebuggable false
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
if (project.hasProperty("RELEASE_STORE_FILE")) {
signingConfig signingConfigs.release
}
externalNativeBuild {
ndkBuild {
arguments 'NDK_DEBUG=0'
}
}
}
debug {
debuggable true
jniDebuggable true
renderscriptDebuggable true
externalNativeBuild {
ndkBuild {
arguments 'NDK_DEBUG=1'
}
}
}
}
}
def getCocosCommandPath() {
if (OperatingSystem.current().isWindows()) {
return 'cocos.bat'
} else {
// on unix like system, can not get environments variables easily
// so run a shell script to get environment variable sets by cocos2d-x setup.py
new ByteArrayOutputStream().withStream { os ->
def result = exec {
executable = project.file('get_environment.sh')
standardOutput = os
}
ext.console_path = os.toString().trim()
}
return new File(console_path + '/cocos').absolutePath
}
}
// a method used to invoke the cocos luacompile command
def compileLua(srcDir, dstDir, doCompile, is64bit, doEncrypt) {
def compileArgs = ['luacompile', '-s', srcDir, '-d', dstDir]
if (!doCompile) {
compileArgs << '--disable-compile'
} else if (is64bit) {
compileArgs << '--bytecode-64bit'
}
if (doEncrypt) {
compileArgs << '-e'
compileArgs << '-k'
compileArgs << project.property('PROP_LUA_ENCRYPT_KEY')
compileArgs << '-b'
compileArgs << project.property('PROP_LUA_ENCRYPT_SIGN')
}
// commandLine compileArgs
println 'running command : ' + 'cocos ' + compileArgs.join(' ')
exec {
// if you meet problem, just replace `getCocosCommandPath()` to the path of cocos command
executable getCocosCommandPath()
args compileArgs
}
// remove the lua files in dstDir
delete fileTree(dstDir) {
include '**/*.lua'
}
}
android.applicationVariants.all { variant ->
// delete previous files first
delete "${buildDir}/intermediates/assets/${variant.dirName}"
variant.mergeAssetsProvider.get().doLast {
def tempDir = ""
// 打印当前Gradle版本
println "Current Gradle version: ${gradle.gradleVersion}"
// 判断Gradle版本并执行不同逻辑
if (gradle.gradleVersion.startsWith("4.")) {
tempDir = "${buildDir}/intermediates/assets/${variant.dirName}"
} else {
tempDir = "${buildDir}/intermediates/merged_assets/${variant.dirName}/out"
}
println "intermediates path: ${tempDir}"
def tempSrc = "${tempDir}/src"
def resSrc = "${tempDir}/res"
copy {
from "${buildDir}/../../../../../res"
into "${resSrc}"
}
copy {
from "${buildDir}/../../../../../src"
into "${tempSrc}"
}
// compile & encrypt the scripts if necessary
def compileScript = (variant.name.compareTo('release') == 0)
if (project.hasProperty('PROP_COMPILE_SCRIPT')) {
compileScript = (PROP_COMPILE_SCRIPT.compareTo('1') == 0)
}
def encryptLua = project.hasProperty('PROP_LUA_ENCRYPT') && (PROP_LUA_ENCRYPT.compareTo('1') == 0)
if (compileScript || encryptLua) {
// -1 means not build bytecode
// 0 means build 32bit only
// 1 means build 64bit only
// 2 means build both 32bit & 64bit
def buildType = -1
if (compileScript) {
def need64 = false
def need32 = false
android.defaultConfig.ndk.getAbiFilters().each { abi ->
if (abi == 'arm64-v8a') {
need64 = true
} else {
need32 = true
}
}
if (need64 && need32) {
buildType = 2
} else if (need64) {
buildType = 1
} else {
buildType = 0
}
}
println "buildType is ${buildType} "
// invoke cocos command to compile & encrypt the lua files
switch (buildType) {
case -1:
compileLua("${tempSrc}", "${tempSrc}", false, false, encryptLua)
break
case 0:
compileLua("${tempSrc}", "${tempSrc}", true, false, encryptLua)
break
case 1:
compileLua("${tempSrc}", "${tempSrc}", true, true, encryptLua)
break
case 2:
compileLua("${tempSrc}", "${tempSrc}/64bit", true, true, encryptLua)
compileLua("${tempSrc}", "${tempSrc}", true, true, encryptLua)
break
}
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':libcocos2dx')
}
可以在gradle.properties
中添加一个配置:
PROP_REBUILD_NDK=true
# uncomment it and fill in sign information for release mode
RELEASE_STORE_FILE=../sign.keystore
RELEASE_STORE_PASSWORD=xxxxx
RELEASE_KEY_ALIAS=xxx
RELEASE_KEY_PASSWORD=xxxxx
编译SO的脚本
BuilSO.bat
:
@REM set abi=armeabi-v7a
set abi=arm64-v8a
set ANDROID_SDK_HOME=D:/Android/Sdk
set ANDROID_NDK_HOME=D:/Android/Sdk/ndk/19.2.5345600
set CMAKE_VERSION=3.10.2.4988404
set CMAKE=%ANDROID_SDK_HOME%/cmake/%CMAKE_VERSION%/bin/cmake
set NINJA=%ANDROID_SDK_HOME%/cmake/%CMAKE_VERSION%/bin/ninja
if not exist %abi% md %abi%
cd %abi%
%CMAKE% ^
-DANDROID_ABI=%abi% ^
-DANDROID_NDK=%ANDROID_NDK_HOME% ^
@REM -DCMAKE_BUILD_TYPE=Debug ^
-DCMAKE_BUILD_TYPE=Release^
-DCMAKE_TOOLCHAIN_FILE=%ANDROID_NDK_HOME%/build/cmake/android.toolchain.cmake ^
-DANDROID_NATIVE_API_LEVEL=16 ^
-DANDROID_STL=c++_static ^
-DANDROID_TOOLCHAIN=clang -DCMAKE_GENERATOR="Ninja" ^
-DCMAKE_MAKE_PROGRAM=%NINJA% ^
..
%NINJA%
cd ..
把该批处理文件放置在和CMakeLists.txt
同级目录下,运行后会创建一个临时目录,目录下会有生成的so文件,复制出来使用即可。为了优化so的编译体积,可以在CMakeLists.txt
中增加如下设置:
# 优化编译的so体积
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Os -Wall -s")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Os -Wall -s")
日常开发
维持
cocos2dx
的命令行创建的项目工程目录不变,需要做的主要是修改目录res
和src
下的文件。使用
CocosStudio
设计的UI素材发布后直接复制到res
目录下即可。src
下就是编辑脚本代码。在Windows上使用VisualStudio编译的可执行程序运行,方便直接查看运行效果,效率会高很多,一旦将要发布的时候再进行编译打包。
运行测试:在项目的根目录下(res所在目录)创建一个
WinAppRun.bat
,日常测试就运行它就可以了,非常方便。call .\simulator\win32\AppName.exe
如果有少量的代码需要编写Java代码时,可以用AndroidStudio打开项目进行Java代码的编写。如果是C++代码,仍然建议使用VisualStudio进行编写,效率会高很多。
AndroidStudio可以用新版,但是gradle版本仍旧用默认的老版本,无论AndroidStudio怎么提示都不要升级,能保证在IDE里正常编写Java代码即可,最后用命令行的方式编译打包。
打包发布
Windows
VisualStudio直接编译,也可以使用VisualStudio的命令行编译。
Android
使用老版本gradle
(4.4版本)直接命令行打包,不建议使用AndroidStudio
打开,太卡了。
下载地址:
https://mirrors.cloud.tencent.com/gradle/gradle-4.4-all.zip
下载好之后解压,老版本gradle
只能使用Java8,因此环境变量JAVA_HOME要修改为指向Java8
的安装目录。其实不修改系统的环境变量也可以,直接修改gradle.bat
文件中JAVA_HOME指向Java8路径即可,这样最绿色环保。
然后进入到项目目录下,直接使用gradle build
命令进行编译:
F:\CocosProjects\Demo\frameworks\runtime-src\proj.android> F:\gradle\gradle-4.4\bin\gradle.bat build
也可以只生成release版本,节省时间:
gradle assemblerelease
三方SDK
SDK | 功能作用简介 | 官方链接 |
---|---|---|
Google Play Services | 提供了广泛的 Google API 功能,包括广告服务、地图、身份验证等。 | Google Play Services SDK |
提供了 Facebook 社交平台集成,包括登录、分享、分析等功能。 | Facebook SDK for Android | |
Facebook Audience Network | 将 Audience Network SDK 添加到您的 Android 应用 | |
AppLovin | 提供了移动广告解决方案,包括广告展示、收益最大化等功能。others-AppLovin广告接入_applovin 拉取applovin官方广告 | AppLovin SDK |
Unity Ads | 提供了 Unity 游戏开发平台的广告服务,用于在游戏中展示广告并获取收益。 | Unity Ads SDK |
Firebase | 提供了一系列的移动应用开发工具,包括分析、远程配置、消息推送等功能,全面支持应用开发和增长。将 Firebase 添加到您的 Android 项目 Firebase for Android | Firebase SDK |
appsflyer | ||
使用入门:在 Android 项目中使用 AdMob Firebase with Google AdMob |
参考资料
文档信息
- 本文作者:zhupite
- 本文链接:https://zhupite.com/cocos/cocos2dx.html
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)