0%

游戏项目客户端开发备忘录(五) - Cocos2d-x 框架进阶

性能优化

  • 参考官方图形性能优化
  • 将同一个场景或节点下的散图打包为图集。
  • 将图片质量从 RGBA8888 降为 RGBA4444
  • 预加载游戏资源,缓存数据、图片、声音等。
  • 单一线程的游戏中,采取分帧处理或加载,减少单帧的运算量。

分辨率适配

  • 通过 GlView::setDesignResolutionSize 设置分辨率适配规则。

  • 适配策略 ResolutionPolicy

    • FIXED_HEIGHT,适配屏幕高度,宽度按比例缩放。
    • FIXED_WIDTH,适配屏幕宽度,高度按比例缩放。
    • NO_BORDER,按设计分辨率比例充满屏幕,多余部分被裁减,没有黑边。
  • 常用策略:

    • 采用 NO_BORDER,根据屏幕宽高比 frameSize 调整设计分辨率 designSize 大小。
1
2
3
4
Director* director = Director::getInstance();
GLView* glView = director->getOpenGLView();
Size designSize(1136, 640);
glView->setDesignResolutionSize(designSize.width, designSize.height, ResolutionPolicy::NO_BORDER);
Luadisplay.lua
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
local function setDesignResolution(r, framesize)
if r.autoscale == "FILL_ALL" then
view:setDesignResolutionSize(framesize.width, framesize.height, cc.ResolutionPolicy.FILL_ALL)
else
local scaleX, scaleY = framesize.width / r.width, framesize.height / r.height
local width, height = framesize.width, framesize.height
if r.autoscale == "FIXED_WIDTH" then
width = framesize.width / scaleX
height = framesize.height / scaleX
view:setDesignResolutionSize(width, height, cc.ResolutionPolicy.NO_BORDER)
elseif r.autoscale == "FIXED_HEIGHT" then
width = framesize.width / scaleY
height = framesize.height / scaleY
view:setDesignResolutionSize(width, height, cc.ResolutionPolicy.NO_BORDER)
elseif r.autoscale == "EXACT_FIT" then
view:setDesignResolutionSize(r.width, r.height, cc.ResolutionPolicy.EXACT_FIT)
elseif r.autoscale == "NO_BORDER" then
view:setDesignResolutionSize(r.width, r.height, cc.ResolutionPolicy.NO_BORDER)
elseif r.autoscale == "SHOW_ALL" then
view:setDesignResolutionSize(r.width, r.height, cc.ResolutionPolicy.SHOW_ALL)
else
printError(string.format("display - invalid r.autoscale \"%s\"", r.autoscale))
end
end
end

Director

每帧流程

  • 流程示意图
            graph TD
            subgraph drawScene
  bof(("BEGIN"))
  bof --> cal["calculateDeltaTime"]
  cal --> ebu["dispatchEvent(eventBeforeUpdate)"]
  ebu --> sch["scheduler->update(dt)"]
  sch --> eau["dispatchEvent(eventAfterUpdate)"]
  eau --> ebd["dispatchEvent(eventBeforeDraw)"]
  ebd --> nextscene{"nextScene"}
  nextscene --> |YES|setnextscene["setNextScene"]
  nextscene --> |NO|physics["physicsWorld->update(dt)"]
  setnextscene --> physics
  physics --> renderscene["openGLView->renderScene()"]
  renderscene --> eav["dispatchEvent(eventAfterVisit)"]
  eav --> render["renderer->render()"]
  render --> ead["dispatchEvent(eventAfterDraw)"]
  ead --> eof(("END"))
 end
          

mainLoop 实现

  • iOS 由 CADisplayLinkNSRunLoop 实现。

参考链接:

Objective-CCCDirectorCaller-ios.mm
1
2
3
id displayLink = [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self selector:@selector(doCaller:)];
[displayLink setFrameInterval: self.interval];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  • Android 由 Cocos2dxRenderer:onDrawFrame 实现。

参考链接:

JavaCocos2dxRenderer.java
1
2
3
4
5
6
7
8
public class Cocos2dxRenderer implements GLSurfaceView.Renderer {
// ...
@Override
public void onDrawFrame(final GL10 gl) {
// ...
Cocos2dxRenderer.nativeRender();
}
}
C++Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp
1
2
3
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeRender(JNIEnv* env) {
cocos2d::Director::getInstance()->mainLoop();
}

C++ 与 Lua 绑定

  • iOS 子工程
1
frameworks/cocos2d-x/cocos/scripting/lua-bindings/proj.ios_mac/cocos2d_lua_bindings.xcodeproj
  • Android
1
cocos/scripting/lua-bindings/proj.android/Android.mk

参考链接