技术面

  1. HTTP/WebSocket/Socket

    • 单工、半双工、全双工

      • 单工:只能单向通信,如:电视、广播。
      • 半双工:可以双向通信,但不能同时,如:对讲机。
      • 全双工:可以同时双向通信,如:电话。
      • HTTP1.1 以下是单工,HTTP1.1 是半双工,HTTP2.0 是全双工。
    • TCP/UDP

      • TCP/UDP 是传输层协议,解决数据在网络中的传输和组织方式。
      • UDP 不需要建立连接,数据是不可靠的,有丢包情况,因此无法保证数据的完整性,但是结构简单,资源占用少,传输速度快。
      • TCP 是面向连接的,建立连接需要三次握手,数据传输是可靠的,有序的,但结构较为复杂,且传输速度较慢,对系统资源要求多。
      • 短连接的优点是管理起来比较简单,存在的连接都是有用的连接,不需要额外的控制手段。
      • 长连接可以省去较多的 TCP 建立和关闭的操作,减少浪费,节约时间,对于频繁请求资源的客户端适合使用长连接,但需要维护连接,且连接多了占用资源。
    • 三次握手

      • 第一次:客户端向服务器发生 Sync 包,进入等待状态;(客户端说明都不能确认,服务器确认了对方发送正常,自己接收正常)
      • 第二次:服务器收到客户端的 Sync 包,确认之后向客户端发送 Sync+Ack 包,进入收到状态;(客户端确认了自己和对方发送和接收正常,服务器确认了对方发送正常,自己接收正常)
      • 第三次:客户端收到服务器的 Sync+Ack 包,向服务器发送 Ack 确认包,客户端和服务器即进入连接建立状态。(客户端和服务器分别确认了自己和对方发送和接收正常)
    • 四次挥手

      • 第一次:A 向 B 发送 Fin 终止包,同时停止发送数据,并进入终止等待状态;
      • 第二次:B 收到 A 的 Fin 包,发送 ACK 包予以确认,进入关闭等待状态;A 收到 B 的 Ack 包后进入终止等待状态 2;
      • 第三次:B 发送完有数据后,再给 A 发送 Fin 包予以确认表示可以断开连接了;
      • 第四次:A 收到 B 的 Fin 包,再发送 Ack 包给 B,此时 A 关闭到 B 的连接,B 收到包后也关闭到 A 的连接,连接彻底关闭。
    • Socket

      • Socket 不属于协议层,它是一组对 TCP/IP 协议包装的接口。
    • HTTP

      • HTTP 是应用层协议,主要解决如何包装数据。
      • HTTP 是短连接或伪长连接(keep-alive,它可以在一段时间内使用同一个 TCP 连接,但每个请求仍需单独发送 Header,且只能由客户端发起请求、服务器响应)。
      • 致命缺点:只能由客户端发起,做不到服务器主动向客户端推送消息。
    • WebSocket

      • WebSocket 是基于 HTTP 的应用层协议,属于 HTML5 标准的一部分。
      • WebSocket 借用了 Socket 的概念,并模拟了 Socket 的接口,实现了双向通信,但与 Socket 完全是两个东西。
  2. Protobuf/JSon/XML/Buffer

    • JSon
      • 可读性强,有类型,比 XML 小巧
      • 传输效率不高,比 XML 快,比 PB
    • XML
      • 格式统一,解析方便
      • 数据量大,传输效率低
    • Buffer
      • 数据量小,传输效率高
      • 可读性差,需要一套成熟的解析器
    • PB
      • 数据量小,有类型,解析快,效率高
      • 学习成本高,需要手写 PB 文件
  3. Cocos2d-x 内存优化

    • 使用静态合图
    • 按照从大到小的顺序加载合图
    • 使用对象池
    • 减少音频文件大小
    • 使用极少的内容使用完毕后立即释放
    • 切换场景时释放无用资源
    • 使用 Spine 骨骼动画替换序列帧动画
    • 使用预制体,且单个预制体不宜过大
    • 使用 BMFont
    • 使用异步/分帧加载等多种方式,避免内存激增,导致性能下降
    • 减少 Mask 组件的使用
  4. Cocos2d-x Drawcall 优化

    • 使用静态合图
    • UI 层级拆分和调整,分离图像节点和文本节点
    • 文本使用 BMFont 或开启 char 缓存模式
    • 需要使用一个 Spine 文件创建多个节点时,开启 Spine 的合批
    • 尽量减少使用 shader 和更换材质,因为它们都会打断合批
  5. Cocos2d-x 渲染过程

    • 导演类的 mainLoop 中会调用 drawScene
    • drawScene 中会调用场景类的 render
    • render 中会递归执行节点类的 visit
    • visit 中会调用精灵类的 draw
    • draw 中会执行渲染类的 addCommand 将渲染指令加入渲染队列
    • 场景树遍历完成后,会对渲染队列进行排序,最后才调用 OpenGL API 进行渲染
    • 特别地,在生成材质的时候,如果 ProgramStateUniform 数量大于 0,也就是设置了 Uniform,那么材质 ID 就会被赋值为 MATERIAL_ID_DO_NOT_BATCH,这是一个特殊的材质 ID,意为不可批次渲染。因为 Uniform 属于一个 Shader 的变量,每次使用同一个 Shader 进行渲染时,Uniform 都可能不一样,这里进行合并的话,后面设置的变量就会失效,也就意味着,需要增加一个 drawcall
  6. Lua

    • 轻量
    • 动态语言,语法简单,高效简洁
    • 支持热更新
    • 代码写起来约束少,较为灵活,但随着开发的深入,如果没有严谨的代码质量把关,会制造大量垃圾代码
    • 支持脚本加密
    • 扩展较少,需要疯狂造轮子
  7. A 星寻路

    • 公式:F = G + H
    • F:起点移动到当前点的总代价
    • G: 起点移动到当前点的移动代价;
    • H: 当前点移动到终点的预估代价,通常使用曼哈顿距离计算;
    • A 星算法伪代码:
      • 创建开放列表和封闭列表;
      • 首先将起点放入开放列表,将终点放入封闭列表;
      • 开始循环,从开放列表中找 F 值【总代价】最小的节点,设置为 current;
      • 如果找到目标,则结束搜寻并回传结果;否则将它所有尚未检验过的所有相邻节点加入队列中;
      • 假如某邻近点既没有在开放列表或封闭列表里面,则计算出该邻近点的 G 值和 H 值,并设其父节点为 P,然后将其放入开放列表;
      • 继续循环,直至没有节点可以访问。
    • 多拐点优化:改公式为 F = G + H + E(拐点值)
  8. Cocos2d-x 与 Creator

    • Cocos2d-x 是游戏引擎
    • Creator 是游戏开发工作流一体化的方案,其内部引擎是 Cocos2d-x
  9. JS 与 TS

    • JS
      • 动态语言
      • 运行时进行类型检查,类型约束差,代码较为自由
      • 开发环境无法提供丰富的帮助
      • 无成员访问控制权限
      • 无高级特性
    • TS
      • 静态语言
      • 编译期进行类型检查,类型约束强,代码较为严谨
      • 开发环境能提供丰富的信息
      • 拥有完整的成员访问控制权限
      • 拥有泛型、装饰器等高级特性
      • TSJS 的超集,最终运行时,TS 会转换为 JS
  10. Cocos2d-x 的事件分发机制

    • EventDispatcher 整个流程包含 3 个类,第一个是 EventListener,负责监听并实现事件触发后的回调,第二个是 Event,这是一个结构体,用于记录事件内容,作为参数传递到回调中,最后是 EventDispatcher,用来管理事件和触发事件。
    • EventDispatcher 除了实现最基本的监听者管理和消息分发外,还实现了消息的优先级,以及监听者与节点的关联
    • EventDispatcher 将事件按照 fixedPriority 从小到大的顺序通知该监听者队列的所有监听者,所有绑定到节点的监听者的 fixedPriority 都为 0,EventDispatcher 会根据所关联节点的 ZOrder 从大到小的顺序进行回调
    • 实现一个消息派发类,说难不难,但也不简单,这种类一般都是底层类,所以特别注重两点,一是稳定性,二是效率。主要体现在注册了大量监听者之后,在事件回调中注册、注销,以及连环触发其他的事件等各种复杂的情况下能够不崩溃,并且保证程序运行效率。
  11. 音频优化

    • wav 文件大,占用空间,且只支持同时播放一个文件
    • ogg 与 mp3 之争
      • ogg 可以支持多声道,而 mp3 最多支持双声道
      • 低码率下 ogg 音质较 mp3 好,且文件略小于 mp3
      • mp3 会砍掉音频高频部分,导致频谱丢失,直接结果就是音质变差
      • Android 支持 mp3 和 ogg,但是 iOS 不支持 ogg
      • 综合来看,建议 Android 使用 ogg,iOS 使用 mp3
    • 减少声音文件大小
      • mp3 可能采用立体声,可以把它转换为单声道,这样可以减少一半大小
      • 在 iOS 设备上,任何比特率大于 192kbps 的声音都是浪费,所以尽量采用低比特率来获得最好的音质效果,一般来说 96~128kbps 是比较合适的
      • 采样率越低,声音文件越小,但是音质也会越差,常用的采样率有 11、22、44、48kHz,一般来说采用 22/44kHz 是比较合适的
    • SimpleAudioEngine / AudioEngine / FMOD
      • SimpleAudioEngine 只封装了各平台的简单 API,支持有限,特别明显的是在播放音效时无法获取状态,也无法在播放完成后回调
      • AudioEngine 支持更多高级特性
      • SimpleAudioEngine/AudioEngine 都存在一些问题,比如:
        • 同时快速播放多个文件可能造成崩溃,
        • 存在播放卡顿问题
        • 播放长音效可能丢失
      • FMOD 跨平台,专业级的音频处理库,支持丰富的高级特性
    • 音频优化
      • 建议采用单声道,这样可以把文件大小和内存使用都减少一半
      • 尽量采用低比特率来获得最好的音质效果,一般来说,96~128kbps 对于 mp3 文件来说足够了
      • 降低文件的比特率可以减小声音文件的大小
  12. 图片优化

    • 存储格式 (文件存储)

      图片的文件格式决定了以何种方式来压缩图片 图片内容越简单,压缩率越高,而越复杂的图片,压缩率越低 单纯的文件压缩并不能减少其在内存中的占用,唯一的目的就是减小包体积。

      • jpg
        • 压缩率高,有损压缩,文件占用小
        • 不支持透明通道
        • 占用内存与 png 相当,画质却差很多
        • 解压所需时间和内存都比较高
      • png
        • 压缩率较高,无损压缩,支持透明通道
      • tiff
        • 比较复杂,高级特性比较多
        • 常用于印刷和扫描领域
      • tga
        • 无损压缩,高质量,支持透明通道,接哦古简单,支持不规则图形
        • 常用于工业、影视领域
      • webp
        • 有损压缩,在相同的质量下体积比 jpg 小 40%,但编码压缩时间比 jpg 场 8 倍
        • 目前在移动设备上加载效率比较低
    • 纹理压缩格式

      正常纹理在加载的时候需要开辟内存进行解析,将文件解压成可渲染的像素格式 而压缩纹理只需要进行简单的解析,即可载入 GPU 进行渲染,其存储大小即内存占用大小,效率自然快了很多 占用内存更低,也可以起到一定压缩文件大小的作用

      • pvrtc
        • pvrtc iOS 直接支持,解压快,效率高,只支持方形贴图,非方形会被处理成方形,且必须为 POT
        • pvrtc2 iOS 直接支持,解压快,效率高,相比 pvrtc2 质量高一些,支持 NPOT
        • pvr.ccz 是压缩后的 pvr 格式,将大量的文件压缩为 pvr.ccz 能够有效的减小文件大小
      • etc
        • etc1 仅支持安卓,压缩率高,不支持透明通道,部分显卡不支持 NPOT
        • etc2 仅支持安卓,压缩率高,支持透明通道,支持 NPOT,需要 OpenGL ES3
    • 显示 (像素) 格式 (内存存储)

      像素格式决定了纹理所占用的内存大小,以及图片显示的质量 计算公式:占用内存 = 图片宽度 x 图片高度 x 纹理位数 / 8

      • BGRA8888 32 位,效果好,兼容性高
      • RGBA8888 32 位,效果好,兼容性较差,需要转换为 BGRA
      • RGB888 24 位,效果好,不支持透明通道
      • RGB565 16 位,效果较好,不支持透明通道
      • RGB5A1 16 位,色彩较好,半透明效果良好,不支持透明通道
      • RGBA4444 16 位,色彩比 RGB5A1 略差,但半透明效果良好
      • RGBA5551 16 位,色彩较好,但半透明效果很差
      • RGBA5555 20 位,色彩较好,半透明效果也不错
    • 总结

      • 逐帧载入游戏资源,避免内存高峰
      • 载入纹理是按照内存占用从大到小的顺序
      • 可以使用 Loading 来预加载,优化体验
      • 打包大图,减少 drawcall
      • 避免载入超大纹理
      • 闲时或收到内存警告时释放空闲资源
      • 使用 NPOT 纹理,而非 POT,因为 POT 会占用额外内存
      • 在不影响画质的前提下,尽量使用低颜色深度的纹理
      • 优先考虑压缩纹理格式
  13. Cocos2d-x 内存管理

    • Cocos2d-x 的内存管理机制
      • 首先,要想让对象参与 Cocos2d-x 的内存管理机制,必须继承 CCRef
      • 然后,调用对象的 autorelease 函数,对象就会被 内存管理机制盯上,在游戏的每一帧,内存管理机制都会扫描一遍被盯上的对象,一旦发现对象无人认领,就会将对象杀死!
      • 如果不想让对象被杀死,那么就要调用对象的 retain 函数,这样对象就被认领了,一旦对象被认领,就永远不会被内存管理机制杀掉
    • 引用计数
      • 构造函数中,引用计数成员变量被设置为 1
      • 当调用 retain 的时候,引用计数自增 1
      • 当调用 release 的时候,引用计数自减 1,并判断引用计数是否为 0,如是则执行 delete this 操作
      • 当调用 autorelease 时,引用技术自增 1,并在切换至下一帧时自动减 1
      • retainrelease 需要成对地出现,一旦调用了该对象的 retain 方法,在不需要使用该对象时,必须调用该对象的 release 方法。
  14. Cocos2d-x 定时器 Schedule

    • Schedule 的整体结构由 ScheduleTimer 组成
      • Timer 负责将一个回调封装为一个对象,管理回调的计时、触发、保存回调的状态。一共有 3 种 Timer
        • TimerTargetSelector 封装了对象回调
        • TimerTargetCallback 封装了函数回调
        • TimerScriptHandler 封装了脚本回调
      • Schedule 管理着大量的 Timer,负责注册、注销,以及驱动执行回调等工作,是 Timer 的总调度室
    • Cocos2d-x 中共用一个 Schedule 对象,该 Schedule 对象由 Director 创建并维护。在 Director 启动的时候,会创建一个 Schedule 对象,通过 Director::setScheduler 可以获取到。可以自己创建一个 Schedule 对象来管理局部的某些计时回调,但一般直接使用全局的 Schedule
    • Director 在每一帧的主循环中,都会调用全局 Scheduleupdate,来驱动 Schedule 内部的计时回调。
    • Director 被销毁时(退出游戏的时候),全局的 Schedule 也会被销毁,同时清理 Schedule 自身的所有回调对象。
    • 在遍历的过程中动态地注册和注销都是安全的。对象回调、函数回调和脚本回调会在遍历的过程中被安全地移除,而 update 回调会在遍历完成之后,额外遍历一次,将标记为移除的回调移除。
    • Schedule 提供了一个比较实用的功能 performFunctionInCocosThread。该功能是 Cocos2d-x 3.0 之后新增的,用于线程安全。在其他线程中使用该方法可以安全地由主线程执行一些逻辑,因为当我们在其他线程中操作 Cocos2d-x 相关内容时,有可能会导致程序崩溃或出现一些渲染错误的问题。
    • 当节点被添加到场景里的时候,就会进入激活状态,而当节点从场景中删除的时候,就会进入非激活状态,甚至直接被销毁。Node 中有一个成员变量 _running 来标识这个状态,该变量的改变主要在 onEnteronExit 中,在游戏设计的时候经常会继承,然后重写这两个方法,并且忘记调用父类的 onEnteronExit,那么这个时候状态变量就没有被重置,而 runActionSchedule 等一系列的函数,在注册 Schedule 时会根据该变量来判断回调是否暂停,默认是非激活状态,所以 Schedule 的回调不会被执行。
  15. 排序算法性能及选择总结

  16. 查找算法总结及其算法实现