cocos2dx - ljatsh/Test GitHub Wiki

cocos2dx笔记

修改历史:

  1. 2018-12-05:初始版本(iphonex适配问题)
  2. 2019-03-26: UserDefault问题
  3. 2019-04-03: Android刘海
  4. 2019-05-09: Android编译
  5. 2019-05-10: Android帧率调整 音频调整
  6. 2021-01-06: HTTPS请求

iphonex适配

如果采取全屏适配方案,iphonex的顶部刘海会覆盖某些关键UI。cocos2dx 3.17版本为了适配iphonex的安全区而提供了接口Director::getSafeAreaRect。全屏UI的大小是能在安全区内适配,另外提供全屏背景图,使其能够充满全屏。

  local visible_size = cc.Director:getInstance():getVisibleSize()
  local safe_area = cc.Director:getInstance():getSafeAreaRect()

  if (visible_size.height - safe_area.height) < 10 then
    -- 全屏幕居中
    self:makeFullScreen()
    self:center()
  else
    -- 调整为安全区大小
    self:setSize(safe_area.width, safe_area.height)
    self:setPosition(safe_area.x, safe_area.y)
  end

UserDefault

Mac平台和ios平台中,UserDefault的设置不再是以文件形式,而是以NSUserDefaults形式存储。其对应的实体文件在~/Library/Preferences/{bundle identifier}.plist, 貌似直接删除这文件并不能生效,通过defaults delete {bundle identifier}可以完全删除,通过defaults read {bundle identifer}可以读取内容。

CMake

Android平台编译,3.17.0版本开始推荐CMake。但是NDK默认安装的CMake版本3.10和cocos2dx指定的Gradle版本并不匹配,主要的解决过程:

  • NDK安装指定的CMake3.6版本, 可以正常编译

    ${ANDROID_HOME}/bin/sdkmanger --list
    ${ANDROID_HOME}/bin/sdkmanger --uninstall cmake;3.10.2.4988404
    ${ANDROID_HOME}/bin/sdkmanager --install cmake;3.6.4111459
  • Release版本发现COCOS2D_DEBUG仍然被定义, 为了使用generator expressions,需要升级CMake到3.10

    target_compile_definitions(${target} PUBLIC "COCOS2D_DEBUG$<$<CONFIG:Debug>:=1>")
    target_compile_definitions(${target} PUBLIC "COCOS2D_DEBUG$<IF:$<CONFIG:Debug>,=1,=0>")
  • 升级到CMake3.10带来的问题 cocos2dx支持CMake3.6编译,但是在处理COCOS2DX_DEBUG宏定义时候,需要升级到CMake3.10。主要问题有

    1. bash Error:Error occurred while communicating with CMake server
      可以选择变更gradle的版本
    buildscript {
        repositories {
            google()
            jcenter()
        }
    
        dependencies {
            classpath 'com.android.tools.build:gradle:3.2.1'
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }

    也可以尝试过滤CMake Server的版本检测日志, 这一点并未尝试

    1. APK中的Asset目录为空 Gradle从3.2.0开始,变更了mergeAsstes任务的实现方式
    android.applicationVariants.all { variant ->
      // delete previous files first
      delete "${buildDir}/intermediates/merged_assets/${variant.dirName}"
    
      variant.mergeAssets.doLast {
          if (variant.name.compareTo('debug') == 0) {
              copy {
                  from "${buildDir}/../../../../../res"
                  into "${buildDir}/intermediates/merged_assets/${variant.dirName}/merge${variant.dirName}Assets/out/res"
              }
    
              copy {
                  from "${buildDir}/../../../../../src"
                  into "${buildDir}/intermediates/merged_assets/${variant.dirName}/merge${variant.dirName}Assets/out/src"
              }
          }
          else {
              copy {
                  from "${buildDir}/../../../../../android_res"
                  into "${buildDir}/intermediates/merged_assets/${variant.dirName}/merge${variant.dirName}Assets/out"
              }
          }
      }
    }

Android帧率

GLSurfaceView默认采用RENDERMODE_CONTINUOUSLY模式渲染,帧率不可调整。Cocos2dx3.17.1调整的方式为线程阻塞等待,感觉很怪异。可以更改为渲染模式RENDERMODE_WHEN_DIRTY,按需调用requestRender

    @Override
    public void doFrame(long frameTimeNanos) {
        Choreographer.getInstance().postFrameCallback(this);

        long interval = Cocos2dxRenderer.getAnimationInterval();
        if (mIdleDuration == 0) {
            mLastFrameTime = frameTimeNanos - interval;
        }
        mIdleDuration += frameTimeNanos - mLastFrameTime;
        mLastFrameTime = frameTimeNanos;

        if (interval <= mDefaultDrawInterval) {
            if (mPaused)
                return;
            requestRender();
        }
        else {
            if (mIdleDuration >= interval) {
                mIdleDuration -= interval;
                if (mPaused)
                    return;

                requestRender();
            }
        }
    }

Android音频

Cocos2dx3.17.1提供了音频播放的Java实现C++实现。两者的音实现都很粗糙,竟然出现了阻塞IO,不预先加载可能会出现卡帧。临时的优化方案是仅仅采用C++实现,小文件没有预加载的情况下先使用UrlAudioPlayer异步播放,再同步预加载PCM缓存,下次播放可以避免IO

    // Prepare Small File Asynchronously for future usage
    if (isSmallFile(info))
    {
        // Put an empty lambda to preloadEffect since we only want the future object to get PcmData
        auto pcmData = std::make_shared<PcmData>();
        auto isSucceed = std::make_shared<bool>(false);
        auto isReturnFromCache = std::make_shared<bool>(false);
        auto isPreloadFinished = std::make_shared<bool>(false);

        std::thread::id threadId = std::this_thread::get_id();

        void* infoPtr = &info;
        std::string url = info.url;
        preloadEffect(info, [infoPtr, url, threadId, pcmData, isSucceed, isReturnFromCache, isPreloadFinished](bool succeed, PcmData data){
            // If the callback is in the same thread as caller's, it means that we found it
            // in the cache
            *isReturnFromCache = std::this_thread::get_id() == threadId;
            *pcmData = data;
            *isSucceed = succeed;
            *isPreloadFinished = true;
            ALOGV("FileInfo (%p), Set isSucceed flag: %d, path: %s", infoPtr, succeed, url.c_str());
        }, true);
    }

    player = createUrlAudioPlayer(info);
    ALOGV_IF(player == nullptr, "%s, %d: player is nullptr, path: %s", __FUNCTION__, __LINE__, audioFilePath.c_str());

HTTPS

TLS协议的握手过程参考这里, 具体握手、非对称加密, 数据传输又开始转为对称加密,暂未去了解。

创建CA认证的证书:

  1. 创建CSR

    openssl req -new -newkey rsa:2048 -nodes -keyout ngx.key -out ngx.csr

  2. 申请Certificate 实际申请卡在了域名验证上。缺少域名、外部主机情况下,尝试通过tp-link路由器暴露内部主机,但是tp-link的路由器80端口貌似并不对外开放

创建自签证书: 直接参考这里

cocos2d-x考虑后台下载,移动平台分别封装了对应的web下载器,但是对于断点续传、重定向的支持不太完善,最终统一使用了CURL版本的下载器。

Reference

Fonts

TODO

Game Resources

⚠️ **GitHub.com Fallback** ⚠️