描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302461258
Cocos2d-x创始人王哲先生倾情推荐!
Cocos2d-x实用技术 → Lua技术 → 网络游戏开发 → 跨平台开发;
专注于Cocos2d-x引擎的实际应用,致力于让你成为一个高水平的程序员;
紧跟技术趋势,以当前主流的Cocos2d-x游戏引擎版本3.x进行讲解;
重点介绍实际开发中碰到的各种问题的不同解决思路及其优缺点;
用简洁和通俗易懂的语言写作,读者阅读起来不会枯燥乏味;
深入介绍热更新、加密与解密、骨骼动画、调试技巧、Shader特效及物理引擎等实用技术;
详解在Cocos2d-x中使用Lua的技巧,以及Quick-Cocos2d-x框架和原生Lua框架的区别;
详解网络及实时同步技术,涵盖弱联网、强联网和局域网三种网络游戏的前后端开发;
详解iOS和Android平台下的开发和打包,涵盖证书签名、ABI和JNI等实用技术;
详解如何使用AnySDK在iOS和Android下快速接入第三方SDK;
提供QQ交流群和E-mail等交流方式,为读者答疑解惑。
《精通Cocos2d-x游戏开发》分为《基础卷》和《进阶卷》两册。这两册都有明确的写作目的。《基础卷》专注于Cocos2d-x引擎基础,致力于让Cocos2d-x初学者成为一个基础扎实、靠谱的程序员。《进阶卷》专注于各种实用技术,是作者多年开发经验的结晶,书中的技术点大多是从实际工作中碰到的问题提炼而来的,从问题的本质出发到解决问题的思路,提供了多种解决方案,并对比各方案的优缺点,启发读者思考。
本书为《精通Cocos2d-x游戏开发》的《进阶卷》,共36章,分为4篇。第1篇为“实用技术篇”,主要内容有加密解密、增量更新、分辨率适配、调试技巧、Shader特效、裁剪遮罩、物理引擎、骨骼动画、CocoStudio*实践等实用技术。第2篇为“Lua篇”,主要内容有Lua的基础知识、Lua的table与面向对象、C/C 与Lua的通信、Cocos2d-x原生Lua框架与Quick-Cocos2d-x Lua框架等。第3篇为“网络篇”,主要内容有网络基础、select IO复用、Socket和Libcurl等基础知识,以及弱联网、强联网、局域网等网络游戏的客户端和服务端开发。第4篇为“跨平台篇”,主要内容有Android和iOS平台的开发和打包知识,以及如何使用AnySDK快速接入第三方SDK。
本书适合使用Cocos2d-x进行游戏开发的中高级读者阅读,尤其适合在使用Cocos2d-x开发过程中碰到问题的程序员,以及希望学习一些实用技术,从而丰富自身经验的程序员。对于大中专院校的学生和社会培训班的学员,本书也是一本不可多得的学习教程。
实用技术篇
文件读写
加密与解密
声音与音效
分辨率适配
CocoStudio*实践
调试Cocos2d-x
调试技巧总结
物理引擎——Box2d基础
物理引擎——应用到Cocos2d-x
图元渲染
Spine骨骼动画
2D、3D粒子特效
裁剪与遮罩
使用Shader——GLSL基础
使用Shader——常用特效
Lua篇
Lua基础语法
Lua——Table
Lua与C的通信
Cocos2d-x原生Lua框架详解
Cocos2d-x Quick框架详解
Quick框架实践——MVC框架
网络篇
网络游戏——网游开发概述
弱联网游戏——Cocos2d-x客户端实现
弱联网游戏——PHP服务器实现
强联网游戏——TCP和Socket
强联网游戏——单机版动作游戏
强联网游戏——C 服务器实现
网络游戏——前后端网络同步
局域网游戏——使用UDP
局域游戏——建立、搜索、加入房间
跨平台篇
Android环境搭建
使用JNI实现C 与Java互调
iOS环境搭建与真机调试
Objective-C与C 互调
接入AnySDK
第1篇 实用技术篇
第1章 文件读写
1.1 使用UserDefault
1.2 读写XML文件
1.2.1 XML格式简介
1.2.2 使用TinyXML读取XML
1.2.3 使用TinyXML写入XML
1.3 读写Plist文件
1.3.1 Plist格式简介
1.3.2 读写Plist文件
1.4 读取CSV文件
1.4.1 解析CSV
1.4.2 描述复杂结构
1.5 读写二进制文件
第2章 加密解密
2.1 加密解密基础
2.1.1 公钥/私钥与非对称加密
2.1.2 信息摘要与数字签名
2.1.3 数字证书
2.2 防止内存修改
2.3 对资源的加密解密
2.3.1 使用TexturePacker加密纹理
2.3.2 对Lua脚本进行加密
2.3.3 自定义Lua脚本加密解密
2.3.4 自定义图片加密解密
2.4 使用加固工具
2.4.1 360加固保加固步骤
2.4.2 Android应用签名
第3章 增量更新
3.1 使用AssetsManagerEx
3.2 搭建增量更新服务器
3.3 Manifest文件详解
3.4 AssetsManagerEx内部实现流程简析
3.5 自动打包工具
第4章 声音与音效
4.1 选择音频格式
4.2 使用SimpleAudioEngine
4.3 使用AudioEngine
4.4 声音音效相关的经验和技巧
第5章 分辨率适配
5.1 Cocos2d-x适配策略
5.1.1 分辨率适配策略
5.1.2 坐标编码
5.1.3 OpenGL窗口与可视化窗口
5.1.4 setDesignResolutionSize详解
5.2 分辨率适配经验
5.2.1 宽度或高度锁定
5.2.2 计算设计分辨率
5.2.3 场景固定内容
5.2.4 经验小结
5.3 CocoStudio分辨率适配
第6章 CocoStudio实践
6.1 高效创建CSB
6.1.1 简单方案
6.1.2 缓存方案
6.1.3 克隆方案
6.2 异步加载CSB
6.3 高效播放CSB动画
第7章 调试Cocos2d-x
7.1 控制台调试
7.2 使用KxDebuger调试Cocos2d-x
第8章 调试技巧总结
8.1 初级调试技巧
8.1.1 基础操作
8.1.2 启动调试
8.1.3 条件断点
8.1.4 监视技巧
8.2 高级调试技巧
8.2.1 远程调试
8.2.2 coredump调试
8.2.3 使用Bugly捕获崩溃堆栈
8.2.4 命中断点
8.2.5 数据断点
8.2.6 即时窗口
8.2.7 多线程调试
8.2.8 性能调试
8.3 记一次内存泄漏调试
8.3.1 内存泄漏表象
8.3.2 初步分析
8.3.3 排查问题
8.3.4 修改代码定位泄漏点
8.3.5 开始调试
第9章 物理引擎——Box2d基础
9.1 核心概念
9.2 工作流程
9.3 物理世界World
9.4 Body和Shape
9.4.1 刚体的碰撞
9.4.2 创建刚体
9.5 关节Joint
9.5.1 使用关节
9.5.2 旋转关节RevoluteJoint
9.5.3 平移关节PrismaticJoint
9.5.4 距离关节DistanceJoint
9.5.5 滑轮关节PulleyJoint
9.5.6 鼠标关节MouseJoint
9.5.7 齿轮关节GearJoint
9.5.8 滚轮关节WheelJoint
9.5.9 焊接关节WeldJoint
9.5.10 摩擦关节FrictionJoint
9.5.11 绳索关节RopeJoint
第10章 物理引擎——应用到Cocos2d-x
10.1 物体的运动
10.1.1 施加力和冲量
10.1.2 角力矩和角冲量
10.2 碰撞检测
10.2.1 碰撞监听
10.2.2 碰撞过滤
10.3 Box2d的调试渲染
10.4 在Cocos2d-x中使用Box2d
10.4.1 物理世界
10.4.2 物理Sprite
10.4.3 碰撞处理
10.5 Box2d的相关工具
10.5.1 PhysicsEditor介绍
10.5.2 BoxCAD介绍
10.5.3 Physics Body Editor介绍
10.5.4 Vertex Helper介绍
第11章 图元渲染
11.1 使用DrawingPrimitives接口绘制图元
11.1.1 如何绘制图元
11.1.2 半透明效果
11.1.3 抗锯齿
11.2 使用DrawNode绘制图元
11.3 渲染接口详解
11.3.1 绘制点
11.3.2 绘制线段、矩形、多边形与圆形
11.3.3 绘制贝塞尔曲线
11.3.4 绘制CardinalSpline
11.3.5 绘制凯特摩曲线
11.3.6 绘制实心图元
11.4 小结
第12章 Spine骨骼动画
12.1 Spine功能简介
12.2 Spine结构
12.3 使用Spine
12.3.1 加载Spine
12.3.2 播放动画
12.3.3 动画回调
12.3.4 显示控制
12.4 Spine高级技巧
12.4.1 混合动画
12.4.2 缓存Spine骨骼动画
12.4.3 异步加载Spine骨骼
12.4.4 Spine的性能优化
第13章 2D、3D粒子特效
13.1 2D粒子特效
13.1.1 粒子系统简介
13.1.2 手动创建粒子系统
13.1.3 使用Cocos2d-x内置的粒子系统
13.1.4 使用Plist文件加载粒子系统
13.1.5 操作粒子系统
13.2 2D粒子系统运行流程
13.2.1 流程简介
13.2.2 粒子的更新和渲染
13.3 3D粒子特效
13.3.1 组件系统
13.3.2 Particle Universe支持的组件
13.4 使用Particle Universe粒子系统
13.4.1 使用PUParticleSystem3D
13.4.2 PUParticleSystem3D相关接口
13.5 3D粒子系统源码简析
13.5.1 ParticleSystem3D结构
13.5.2 初始化流程
第14章 裁剪与遮罩
14.1 片段测试
14.1.1 裁剪测试
14.1.2 Alpha测试
14.1.3 模板测试
14.1.4 深度测试
14.2 裁剪
14.2.1 使用ClippingRectangleNode
14.2.2 ClippingRectangleNode的实现
14.3 遮罩
14.3.1 ScrollViewDemo示例
14.3.2 HoleDemo示例
14.3.3 详解HoleDemo示例
14.3.4 ClippingNode的实现
第15章 使用Shader——GLSL基础
15.1 Shader简介
15.2 图形渲染管线
15.2.1 顶点处理器
15.2.2 片段处理器
15.2.3 插值计算
15.3 GLSL基础语法
15.3.1 数据类型和变量
15.3.2 操作符
15.3.3 变量修饰符、统一变量和属性变量
15.3.4 易变变量
15.3.5 语句与函数
15.3.6 Shader简单示例
15.4 在OpenGL中使用Shader
15.4.1 在OpenGL中创建Shader
15.4.2 属性变量
15.4.3 统一变量
15.4.4 错误处理
15.4.5 清理工作
15.5 在Cocos2d-x中使用Shader
15.5.1 Cocos2d-x的Shader架构
15.5.2 Cocos2d-x内置Shader规则
15.5.3 编写Shader
15.5.4 使用Shader的步骤
第16章 使用Shader——常用特效
16.1 Blur模糊效果
16.2 OutLine描边效果
16.3 RGB、HSV与HSL效果
16.4 调整色相
16.5 流光效果
第2篇 Lua篇
第17章 Lua基础概述
17.1 类型与值
17.2 操作符
17.2.1 算术操作符
17.2.2 关系操作符
17.2.3 逻辑操作符
17.2.4 其他操作符
17.3 语句
17.3.1 赋值语句
17.3.2 语句块
17.3.3 条件语句
17.3.4 循环语句
17.4 函数
17.4.1 定义函数
17.4.2 调用函数
17.4.3 函数参数
17.4.4 尾调用
17.5 闭包与泛型for
17.5.1 闭包
17.5.2 泛型for
第18章 Lua——table
18.1 使用table
18.1.1 创建table
18.1.2 访问table
18.1.3 修改table
18.1.4 删除table
18.1.5 遍历table
18.2 元表metatable
18.2.1 元方法
18.2.2 算术、关系与连接元方法
18.2.3 特殊的元方法
18.2.4 __index元方法
18.2.5 __newindex元方法
18.2.6 __mode元方法
18.3 packages介绍
18.3.1 require()方法
18.3.2 编写模块
18.4 面向对象
18.4.1 定义类
18.4.2 实例化
18.4.3 继承
18.5 table库
18.5.1 插入
18.5.2 排序
18.5.3 pack()和unpack()方法
18.5.4 table长度
第19章 Lua与C的通信
19.1 准备工作
19.1.1 头文件与链接库
19.1.2 lua_State指针
19.1.3 堆栈
19.1.4 压入堆栈
19.1.5 访问堆栈
19.1.6 堆栈的其他操作
19.2 操作table
19.2.1 如何将table传入Lua
19.2.2 如何获取Lua返回的table
19.3 C/C 中调用Lua
19.3.1 执行Lua片段
19.3.2 执行Lua脚本文件
19.3.3 调用Lua函数
19.4 注册C/C 函数给Lua调用
19.5 将C 的类传给Lua
第20章 Cocos2d-x原生Lua框架详解
20.1 Cocos2d-x原生Lua框架结构
20.1.1 Lua核心层
20.1.2 Lua脚本引擎
20.1.3 Cocos2d-x到Lua的转换层
20.1.4 Lua辅助层
20.2 使用Cocos2d-x原生Lua框架
20.2.1 在Cocos2d-x中调用Lua
20.2.2 在Lua中操作Cocos2d-x
20.3 Cocos2d-x原生Lua框架运行流程
20.3.1 LuaEngine初始化流程
20.3.2 加载Lua脚本
20.3.3 Cocos2d-x到Lua的事件分发
20.3.4 Lua辅助层初始化流程
20.3.5 Lua辅助层的实用工具
20.4 使用genbindings.py导出自定义类
20.4.1 各个平台的环境搭建
20.4.2 编写要导出的C 的类
20.4.3 编写ini配置文件
20.4.4 修改并执行genbindings.py
20.4.5 注册并在Lua中使用
20.5 扩展Cocos2d-x Lua
20.5.1 编写扩展方法
20.5.2 注册到类中
20.6 lua-tests导读
第21章 Cocos2d-x Quick框架详解
21.1 Quick简介
21.2 Quick框架结构
21.3 使用Quick
21.3.1 创建Quick项目
21.3.2 个Quick程序
21.3.3 开发工具
21.4 Quick运行流程分析
21.4.1 初始化流程
21.4.2 MVC框架运行流程
21.5 Quick脚本框架详解
21.5.1 Quick脚本框架整体结构
21.5.2 Quick框架基础模块
21.5.3 Quick脚本框架初始化流程
第22章 Quick框架实践——MVC框架
22.1 组件系统详解
22.1.1 EventProtocol事件组件
22.1.2 StateMachine状态机组件
22.2 ModelBase详解
22.3 MVC示例详解
22.3.1 代码结构简介
22.3.2 启动流程详解
22.3.3 发射子弹
22.3.4 命中目标
22.4 小结
第3篇 网络篇
第23章 网络游戏——网游开发概述
23.1 弱联网游戏
23.2 强联网游戏
23.3 局域网游戏
第24章 弱联网游戏——Cocos2d-x客户端实现
24.1 客户端请求流程
24.2 Libcurl easy接口详解
24.2.1 关于请求链接
24.2.2 关于Post提交表单
24.2.3 关于读写
24.3 使用多线程执行请求
第25章 弱联网游戏——PHP服务器实现… 362
25.1 环境搭建… 362
25.1.1 安装PHP. 362
25.1.2 安装Nginx. 363
25.1.3 安装MySQL. 363
25.1.4 启动服务… 364
25.2 编写PHP. 365
25.2.1 基本语法… 365
25.2.2 表单处理… 366
25.2.3 操作MySQL. 366
25.3 实现签到服务… 366
第26章 强联网游戏——TCP和Socket 369
26.1 Socket接口与TCP. 369
26.1.1 TCP服务器与客户端交互流程… 370
26.1.2 Socket API 详解… 372
26.1.3 Windows Socket API详解… 376
26.2 简单的TCP服务器端与客户端… 376
26.2.1 TCP服务器实现… 377
26.2.2 TCP客户端实现… 379
26.3 非阻塞Socket与select()函数… 380
26.3.1 非阻塞Socket 380
26.3.2 select()函数的使用… 380
26.3.3 调整TCP服务器为Select模型… 382
26.4 半包粘包… 384
26.4.1 什么是半包粘包… 384
26.4.2 处理半包粘包… 385
26.5 心跳与超时… 387
26.5.1 TCP的死连接… 388
26.5.2 检测死连接… 389
第27章
强联网游戏——单机版动作游戏… 390
27.1 需求分析与类设计… 390
27.2 创建工程和场景… 393
27.3 添加实体… 396
27.4 实体显示组件… 399
27.5 消息定义… 400
27.6 添加SingleProxy. 401
27.7 游戏的主逻辑… 402
第28章
强联网游戏——C 服务器实现… 404
28.1 服务端需求分析… 404
28.2 kxServer的使用… 404
28.3 NetDemoServer服务器… 405
28.4 接收客户端请求… 409
28.5 移植前端代码… 412
28.6 梳理流程和总结… 412
第29章
网络游戏——前后端网络同步… 414
29.1 整理入口场景… 414
29.2 连接服务器… 416
29.3 添加OnlineProxy. 416
29.4 打包与恢复场景… 418
29.5 实时同步… 419
第30章
局域网游戏——使用UDP. 423
30.1 使用UDP. 423
30.2 UDP通信流程… 424
30.2.1 sendto()函数… 424
30.2.2 recvfrom()函数… 425
30.3 UDP广播… 425
30.3.1 什么是网络号和主机号… 426
30.3.2 A类、B类、C类地址与广播地址… 426
30.3.3 什么是子网和子网掩码… 426
30.3.4 本地网络的定义是什么… 427
30.3.5 发送广播… 427
30.4 简单的UDP服务器… 428
30.5 简单的UDP客户端… 429
第31章
局域网游戏——建立、搜索、加入房间… 430
31.1 建立房间… 430
31.2 移植后端代码… 432
31.3 搜索房间… 434
第4篇 跨平台篇
第32章
Android环境搭建… 440
32.1 Android环境搭建基础… 440
32.1.1 JDK和JRE. 440
32.1.2 关于ADK. 442
32.1.3 关于NDK. 443
32.2 使用Eclipse打包… 443
32.2.1 打开Android项目… 443
32.2.2 解决Java报错… 444
32.2.3 设置NDK. 448
32.2.4 解决打包报错… 450
32.2.5 解决运行报错… 451
32.3 使用Android Studio打包… 453
32.3.1 cocos compile命令… 453
32.3.2 编译打包Android Studio. 454
32.3.3 打包遇到的问题… 455
32.4 新建Android项目… 456
32.5 实用技巧… 458
32.5.1 关于版本问题… 458
32.5.2 关于减少包体积… 459
第33章
使用JNI实现C 与Java互调… 461
33.1 Android基本概念… 461
33.1.1 Activity简介… 461
33.1.2 Intent简介… 463
33.1.3 资源与R.java. 463
33.1.4 AndroidManifest.xml简介… 463
33.2 Hello JNI项目… 463
33.2.1 使用Eclipse创建项目… 463
33.2.2 使用Android Studio创建项目… 465
33.3 编写JNI的C 代码… 467
33.3.1 为Eclipse添加Android.mk和hello.c. 467
33.3.2 在Android Studio下编写JNI 468
33.3.3 C 的函数原型… 471
33.3.4 C 调用Java. 472
33.4 Java调用C . 473
33.5 在C 程序中使用Java. 474
33.6 在Cocos2d-x中实现Java和C 的互调… 479
33.6.1 Cocos2d-x的JNI初始化… 480
33.6.2 在Cocos2d-x中调用Java. 480
33.6.3 在Java中调用Cocos2d-x. 481
33.7 Android.mk和Application.mk详解… 481
33.7.1 认识Android.mk. 481
33.7.2 用Android.mk添加源文件以及指定头文件目录… 482
33.7.3 在Android.mk中引用其他模块(第三方库)… 482
33.7.4 Android.mk的一些变量和函数… 484
33.7.5 关于Application.mk. 484
33.8 ABI详解… 485
33.8.1 常见的ABI 485
33.8.2 如何选择ABI 485
33.8.3 如何生成对应ABI的so. 486
33.9 调试JNI代码… 486
33.9.1 Android Studio JNI 调试环境搭建… 487
33.9.2 Android Studio 的断点调试… 490
第34章
iOS环境搭建与真机调试… 492
34.1 iOS环境搭建… 492
34.1.1 环境搭建… 492
34.1.2 Windows移植iOS. 493
34.2 iOS证书… 494
34.2.1 Mac的证书… 495
34.2.2 注册开发者… 495
34.2.3 如何获得证书… 495
34.2.4 创建证书… 496
34.2.5 关于证书密钥… 498
34.3 iOS真机调试… 500
34.3.1 无证书调试… 500
34.3.2 使用证书调试… 502
34.4 打包IPA. 505
34.4.1 正确设置签名证书与授权文件… 505
34.4.2 使用Xcode打包… 506
34.4.3 其他打包方式… 509
第35章
Objective-C与C 互调… 511
35.1 Objective-C基础语法… 511
35.1.1 Objective-C的一些特性… 511
35.1.2 Objective-C的类… 512
35.2 Objective-C与C 混编… 514
第36章
接入AnySDK. 515
36.1 AnySDK概述… 515
36.1.1 为什么要接入AnySDK. 515
36.1.2 AnySDK架构简介… 516
36.1.3 AnySDK快速接入指引… 517
36.2 接入AnySDK Android框架… 520
36.2.1 导入Android AnySDK Framework. 521
36.2.2 初始化AnySDK Framework. 522
36.3 接入AnySDK iOS 框架… 526
36.3.1 导入AnySDK Framework. 527
36.3.2 初始化AnySDK Framework. 530
36.4 登录流程… 531
36.4.1 登录流程简介… 531
36.4.2 客户端接入登录… 532
36.4.3 服务端接入登录… 534
36.5 支付流程… 536
36.5.1 支付流程… 536
36.5.2 客户端接入支付… 537
36.5.3 服务端接入支付… 539
36.6 母包联调… 540
36.6.1 调试登录… 540
36.6.2 调试支付… 541
36.7 打包工具… 542
36.8 小结… 543
其实Cocos2d-x算不上是一款功能超强的游戏引擎,但它很简洁、小巧,是一款轻量级的游戏引擎。大多数程序员实际上更喜欢简洁的东西,而不是庞然大物。Cocos2d-x简洁的设计结合丰富的Demo,让人可以很快上手,并能使用它开发出一些简单的游戏。其代码的开源及跨平台特性也相当诱人。Cocos2d-x本身的这些特性结合市场的需求,使其很快就成为手游开发的主流引擎之一。
在Cocos2d-x刚开始“火”的那一段时间,市面上关于Cocos2d-x的书籍还十分匮乏。笔者利用业余时间对该引擎进行了深入研究,并使用它开发了几个小游戏,也总结了一些开发经验。之后一段时间,笔者萌生了按照自己的想法写一本Cocos2d-x游戏开发图书的想法。这个想法很快便进入了实施阶段,但进展远没有想象的顺利。其原因一方面是笔者写作的速度跟不上Cocos2d-x的更新速度,另一方面是笔者的工作任务也很重,加之写作期间还开发了四五个游戏作品,这使得本来就不充裕的时间更是捉襟见肘。
的确,Cocos2d-x的更新非常频繁,并且引擎更新的同时带来了很多接口的变化,一些代码甚至需要进行重构。除了原有内容的变化改动之外,日益增加的新功能也加大了写作的难度。虽然2013年底笔者已经完成了初稿,但是回过头来阅读一遍,发现书稿难以达到自己的预期。于是笔者做了一个决定:推翻重写。在经历了几个月的重写之后,Cocos2d-x版本已经升级到了3.0。笔者发现又有许多新增功能和新特性需要重新了解和学习,于是又经历了一段时间的学习和使用,不得不决定再次对书稿做较大的改动,几乎又推翻重写了一次。从开始写作直至完成书稿,整个过程一言难尽,饱含艰辛。在写作的过程中,Cocos2d-x的书籍如雨后春笋相继面市,加上自己工作繁忙,写作时间有限,一度产生了放弃的念头。但写一本自己满意的Cocos2d-x图书的信念支撑笔者走到了*后。当然,这一切对笔者而言很有意义,也很有价值:其一是有机会能和读者共享自己的心得体会;其二是笔者自己也得到了提升。毕竟写书相对于写代码而言需要考虑的东西更多。代码写错还可以改正,而书写错则将误人子弟。
考虑到读者群体的不同,笔者将本书分为《基础卷》和《进阶卷》两个分册。《基础卷》主要是为了让读者夯实Cocos2d-x游戏开发的基础知识,适合没有经验的零基础读者阅读。《进阶卷》内容全面,且实用性很强,可以拿来就用,快速解决问题,适合想要进阶学习的读者阅读,也可以作为一本解决实际问题的手册使用。当然,对于想要全面而深入学习Cocos2d-x游戏开发的读者而言,则需要系统阅读这两本书。
本书是《精通Cocos2d-x游戏开发》的《进阶卷》,是一种实用的Cocos2d-x进阶图书,是在笔者完成《基础卷》写作之后,用了一年多的时间编写的。这一年多笔者工作繁忙,压力巨大,几乎很难在晚上10点之前下班,通常晚上一两点下班是家常便饭。*长的加班记录是到了第二天早上9点,也就是正常上班的时间。笔者在这种情况下利用大量业余时间写作完成书稿,实属不易。在写作过程中,笔者不断地将之前已完成的书稿中的一些过时内容及难以令自己满意的内容推翻重写,力求完美。
虽然工作繁忙,但笔者在工作中积累的经验也成为了《进阶卷》的宝贵素材。本书介绍了丰富的实用技巧,针对开发过程中需要用到的各种技术及可能碰到的各种问题,做了全面而深入的介绍。无论是需要解决问题的读者还是需要增长经验的读者,都能通过阅读本书有所收获。本书对读者的要求略高,需要读者熟悉Cocos2d-x,*好能有一定的开发经验。虽然在编写时笔者尽量做到了图文并茂,让内容更加通俗易懂,但对于初学者而言还是有一定的难度。所以建议初学Cocos2d-x的读者先阅读《基础卷》,以巩固好基础,然后再来阅读《进阶卷》,这样学习效果会更好。如果是有针对性地解决某一问题,读者可以阅读相应章节。欢迎读者在本书的QQ群中对阅读中的疑问进行交流和讨论。相信本书能够让每一个基础扎实的Cocos2d-x程序员成为一个经验丰富的Cocos2d-x开发高手。
本书内容特色
1.内容新颖,紧跟趋势
本书内容新颖,紧跟技术趋势,以当前主流的Cocos2d-x游戏引擎版本3.x为主进行讲解,在一些必要的地方也兼顾了早期的2.x版本的内容,并对新旧版本之间的差异做了必要说明,适合更多的读者群体阅读。
2.覆盖面广,实用性强
本书专注于解决开发过程中碰到的各种问题,介绍各种常用的开发技术,涵盖了游戏客户端开发的大部分问题。
3.追求原创,与时俱进
相较于市场上千篇一律的Cocos2d-x学习教程,本书力求做到与众不同,与时俱进。书中内容的组织不是堆砌知识点和简单地翻译技术文档,而是从学习和理解的角度出发,并结合了笔者的实际开发经验,使用绝大多数章节都是“干货满满”。
4.风格活泼,讲述准确
刻板的风格不是笔者所钟爱的行文风格。笔者更喜欢用较为简单和自由的文字和读 者交流,所以本书阅读起来并不会枯燥乏味。另外,讲解的准确性是对科技图书的基本 要求,只有准确的表达才能让读者不至于出现太多的理解偏差。所以笔者对书中的表述经过了反复斟酌和提炼,并采用了大量例图、举例和类比等手法,以便于读者更容易理解和掌握。
5.举一反三,扩展思维
本书并不满足于按部就班地介绍功能和API,而是从实际应用出发,扩散思维,在解决问题的同时,让读者思考问题的本质,以更深入地理解所学知识,从而达到举一反三、学以致用的效果。虽然本书介绍的是Cocos2d-x,但对技术点的介绍并不局限于Cocos2d-x,对于使用其他引擎的开发者,很多知识都是相通的,即所谓知行合一,方能真正掌握 知识。
本书内容及知识体系
第1篇 实用技术篇(第1~16章)
本篇深入介绍了Cocos2d-x游戏开发的各种实用技术,涵盖了热更新、加密解密、骨骼动画、调试技巧、Shader特效、物理引擎、分辨率适配等实用的技术点。读者可以根据自己的需求和兴趣挑选本篇的章节进行阅读。
第2篇 Lua篇(第17~22章)
本篇介绍了在Cocos2d-x中使用Lua开发的技巧,包含了Lua的基础知识,以及在Cocos2d-x中如何使用Lua,分析了Quick-Cocos2d-x框架和原生Lua框架的区别。
第3篇 网络篇(第23~31章)
本篇介绍了如何使用Cocos2d-x开发网络游戏,包含了网络基础知识的讲解,以及弱联网、强联网、局域网这3种网络游戏的前后端开发,并提供了一个简易横版实时对战游戏的Demo,相信读者可以在Demo中更好地了解网络游戏的开发知识。
第4篇 跨平台篇(第32~36章)
跨平台开发是Cocos2d-x程序员所必须掌握的知识,初次进行跨平台移植的读者难免会遇到不少问题,本篇详细介绍了iOS和Android平台下的开发和打包,涵盖了丰富的知识点,如证书签名、ABI、JNI等技术。打包也不是简单地罗列操作步骤,对打包过程中遇到的各种问题都会追本溯源。另外本篇还介绍了如何使用AnySDK在iOS和Android下快速接入第三方SDK。
本书阅读建议
由于Cocos2d-x游戏引擎是基于C 的,所以一些基础的C 知识是必须知道的。假如读者完全没有任何编程方面的经验,则不适合阅读本书。
书中部分章节的内容可能较为深入,如果读者对这部分内容一时难以理解,可以先跳过而阅读后续章节,等读完后续章节再回头阅读这部分内容,也许就豁然开朗了。如果是为了解决某个问题或者系统学*个技术点,这种有针对性的阅读效率会更高。
本书中的部分例子引用自Cocos2d-x引擎自带的TestCpp,本书的配套资源中也提供了本书的代码下载方式,读者在学习的过程中可以参照TestCpp中的例子。
本书读者对象
* 有一定Cocos2d-x游戏开发经验的人员;
* Cocos2d-x开发人员;
* 想系统学习Cocos2d-x的程序员;
* 想丰富Cocos2d-x开发经验的程序员;
* 想开发跨平台手机游戏的人员;
* 从其他开发转向Cocos2d-x的程序员;
* 大中专院校的学生和社会培训的学员。
本书配套资源获取方式
本书涉及的源代码等资源需要读者自行下载。请读者登录清华大学出版社网站,然后搜索到本书页面,在页面上找到“资源下载”栏目,然后单击“课件下载”或者“网络资源”按钮即可。读者也可以在笔者的github中获取。
本书的编写对笔者而言是一个不小的挑战,虽然笔者投入了大量的精力和时间,但只怕百密难免一疏。若读者在阅读本书时发现任何疏漏,希望能及时反馈给我们,以便及时更正。联系我们请发邮件至[email protected]。
*后祝各位读者读书快乐,学习进步!
编者著
本书作者拥有丰富的一线研发经验,对Cocos引擎也有着深入而独到的理解。整个写作期间,他对这本书倾注了大量的心血,精心打磨,多次对不满意的地方推翻重写。这份执着和热忱加精益求精的态度令人感动。这本书内容新颖,紧跟技术趋势,注重实际应用,讲述准确而深入,对游戏开发人员而言是一本不可多得的专业好书,认真阅读一定大有裨益。
——Cocos2d-x创始人 王哲
当在不同的分辨率下运行程序时,就会碰到分辨率适配的问题,如出现黑边、界面的一部分显示在屏幕外,我们希望程序在不同的分辨率下运行都能有良好的表现。在Cocos2d-x中,可以通过选择合适的分辨率适配策略,结合合适的坐标编码,适配各种不同的分辨率。而灵活使用Cocos2d-x的分辨率适配策略,还可以解决各种分辨率适配的难题。本章主要介绍以下内容:
* Cocos2d-x适配策略。
* 分辨率适配经验。
* CocoStudio分辨率适配。
5.1 Cocos2d-x适配策略
可以在Cocos2d-x中调用CCEGLView的setDesignResolutionSize方法设置游戏的分辨率策略,以及我们的设计分辨率。
setDesignResolutionSize()方法包含3个参数,分别是设计分辨率的宽和高,以及分辨率的适配策略。下面这行代码设置了960×640的设计分辨率,并使用了SHOW_ALL分辨率适配策略。
Director::getInstance()->getOpenGLView()->setDesignResolutionSize(960, 640, ResolutionPolicy::SHOW_ALL);
5.1.1 分辨率适配策略
Cocos2d-x的分辨率适配一般不是为每一种分辨率设计一种布局方案,而是在一种分辨率下进行设计(也就是设计分辨率),然后通过分辨率适配策略,让程序能够适应不同的分辨率。Cocos2d-x提供以下5种分辨率适配策略。
* EXACT_FIT以设置的分辨率为标准,按照该分辨率对x和y进行拉伸。
* NO_BORDER不留黑边,不拉伸,等比缩放,有一个方向(上下或左右)可能超出屏幕。
* SHOW_ALL设置的分辨率区域内全部可见,但上下左右都可能出现黑边。
* FIXED_HEIGHT锁定分辨率的高度,宽度不管,可能出现黑边也可能超出屏幕。
* FIXED_WIDTH锁定分辨率的宽度,高度不管,可能出现黑边也可能超出屏幕。
通过图5-1~图5-3可以直观地了解到在不同分辨率下,各个分辨率适配策略的表现。以960×640为设计分辨率,然后通过调整窗口的实际分辨率,选择不同的适配模式进行观察。在PC上调用Director的setFrameSize()方法可以自定义窗口的尺寸,但不要在移动设备上设置FrameSize。
首先是EXACT_FIT模式,当在不同的分辨率下运行时,界面的宽和高都会根据我们的设计分辨率进行缩放,例如,当设计分辨率是100×200,在200×300的分辨率下运行时,宽会放大2.0,高会放大1.5,当实际分辨率小于设计分辨率时,Cocos2d-x又会相应地缩小界面使其适配,如图5-1所示。
图5-1 EXACT_FIT模式
NO_BORDER模式下会根据实际分辨率进行等比缩放,不留黑边。首先按照EXACT_FIT模式的缩放规则计算出宽和高的缩放值,按照*高的缩放值进行等比缩放。当实际分辨率无法完整放下缩放后的界面时,会有一部分内容显示在屏幕外,如图5-1所示,当界面以NO_BORDER模式进行适配时,红色边框为界面的完整内容,红色边框左下角的红色原点为OpenGL窗口的原点坐标,如图5-2所示。
图5-2 NO_BORDER模式
SHOW_ALL模式下会根据实际分辨率进行等比缩放,完全显示界面的完整内容,与NO_BORDER模式相反,其会先按照EXACT_FIT模式的缩放规则计算出宽和高的缩放值,按照*低的缩放值进行等比缩放。由于是按照*小的分辨率进行缩放,所以左右和上下都有可能出现黑边,图5-3右侧图片中的红点处为OpenGL窗口的原点坐标,如图5-3所示。
FIXED_HEIGHT和FIXED_WIDTH模式比较类似,它们会将高度或宽度锁定,按照高度或宽度进行等比缩放,另外一个方向既可能超出,也有可能留下黑边。这两种模式会先按照EXACT_FIT模式的缩放规则计算出宽和高的缩放值,FIXED_HEIGHT取高度缩放值进行等比缩放,保证设计分辨率的高度刚好铺满设计分辨率,FIXED_WIDTH取宽度进行等比缩放,保证设计分辨率的宽度刚好铺满设计分辨率。
图5-3 SHOW_ALL模式
5.1.2 坐标编码
当我们的程序在不同的分辨率下运行时,setDesignResolutionSize()方法会对整个程序按照适配策略根据设计分辨率和实际分辨率进行缩放。在对坐标进行编码时,需要使用相对坐标编码,而根据窗口尺寸可以进行相对坐标的编码,如希望将一个节点放置在屏幕的正中间,就需要将其坐标的x和y分别设置为窗口尺寸的宽和高的1/2。相对左下角原点的坐标则可以直接使用坐标,设置相对位置可以使得程序在不同的分辨率下运行,我们的对象都能够显示在正确的位置上。
在使用相对坐标编码时,Director单例中有几个方法可以获取尺寸,下面了解一下这几个获取尺寸相关的方法。
* getWinSize,获取OpenGL窗口的单位尺寸。
* getWinSizeInPixels,获取OpenGL窗口的实际像素尺寸。
* getVisibleSize,获取可视窗口的尺寸。
* getVisibleOrigin,获取可视窗口左下角坐标的位置。
另外GLView对象还提供了以下两个接口来获取其他的尺寸。
* getFrameSize,获取设备或窗口的尺寸。
* getDesignResolutionSize,获取设置的设计分辨率。
如图5-4直观地演示了上面描述的各种尺寸,WinSize和WinSizeInPixels分别是当前整个OpenGL窗口的单位尺寸和像素尺寸。VisibleSize和VisibleOrigin可以共同构成当前窗口中实际可见部分内容的矩形范围,FrameSize为当前窗口或设备的真实尺寸。
图5-4 WinSize与VisibleSize
* WinSize分别为图5-4中左右两图的红色框范围,虽然看上去范围不同,但这是一个单位尺寸,所以值并没有变化,也就是原图尺寸960×640,一般等同于设计分辨率的尺寸,也是OpenGL窗口的单位尺寸。
* WinSizeInPixels也对应图5-4两图中的红色框范围,但这个尺寸为实际占用的像素尺寸,所以在不同分辨率下有不同的值(程序逻辑中使用的坐标是单位尺寸,而非像素尺寸)。
* VisibleSize表示可视内容的尺寸,在图5-4左图中为红色框范围,右图则为黄色框范围,也就是可以看到的有内容的显示区域尺寸。
* VisibleOrigin表示可视内容的左下角坐标,分别是左右图中左下角的红点的位置,左图中OpenGL窗口原点的坐标与红点重叠,而右图中OpenGL窗口的原点为红色框的左下角,VisibleOrigin的Y轴比原点高了64个像素。
* FrameSize为窗口或设备的实际尺寸,也就是图5-4中两个窗口的窗口大小1200×640。
Cocos2d-x推荐使用VisibleSize和VisibleOrigin进行相对位置的计算,就是因为根据它们来计算可以保证我们的对象能够处于可视范围中。
WinSize和(0,0)坐标构成了OpenGL窗口,VisibleSize和VisibleOrigin构成了可视窗口,可视窗口不会大于OpenGL窗口,因为OpenGL窗口以外的内容都是不可见的!但OpenGL窗口范围内的对象并不一定可见,如当屏幕窗口容不下OpenGL窗口时。可视窗口可以理解为OpenGL窗口和设备实际分辨率窗口相交的矩形区域。
5.1.3 OpenGL窗口与可视化窗口
绝大部分的游戏都可以使用FIXED_HEIGHT或FIXED_WIDTH模式来实现简单的分辨率适配,只需要在背景上将可能有黑边的内容进行填充即可。这两种模式与SHOW_ALL有些类似,就是都可能导致黑边或超出,但有一种本质区别,即它们的OpenGL窗口不同,这对于坐标编码是有巨大影响的!OpenGL窗口不同,说的是原点位置不同,WinSize、VisibleSize不同。
在图5-5中,使用FIXED_HEIGHT和SHOW_ALL模式都是同样的表现,左右都会有同样的黑边,但FIXED_HEIGHT模式下的OpenGL窗口和可视化窗口对应的是图5-5中的黄色矩形区域(包括左右的黑边),而SHOW_ALL模式下的OpenGL窗口和可视化窗口对应的是图5-5中的红色矩形区域(不包括黑边)。
图5-5 OpenGL窗口和可视化窗口
*直观的表现就是,在(0,0)的位置创建一个对象,FIXED_HEIGHT模式下会出现在黄色矩形区域的左下角,而SHOW_ALL模式下会出现在红色矩形区域的左下角。SHOW_ALL模式下的黑边部分是不会出现任何显示对象的,因为不在OpenGL窗口中。而FIXED_HEIGHT模式则可以正常显示,所以只要背景图片大一些,将左右的黑边区域遮住,即可简单地解决适配黑边的问题。正是由于这种实现方式,FIXED_HEIGHT和FIXED_WIDTH模式才可以在背景上对可能有黑边的内容进行填充来解决黑边的问题。
5.1.4 setDesignResolutionSize详解
在了解了适配策略和Cocos2d-x的各种尺寸之后,下面来进一步了解setDesign- ResolutionSize()方法,setDesignResolutionSize()方法中会简单判断传入的设计分辨率的宽度和高度,以及分辨率适配策略,将这些参数保存并调用updateDesignResolutionSize()方法更新分辨率。
void GLView::setDesignResolutionSize(float width, float height,
ResolutionPolicy resolutionPolicy)
{
CCASSERT(resolutionPolicy != ResolutionPolicy::UNKNOWN, “should set
resolutionPolicy”);
if (width == 0.0f || height == 0.0f)
{
return;
}
_designResolutionSize.setSize(width, height);
_resolutionPolicy = resolutionPolicy;
updateDesignResolutionSize();
}
在updateDesignResolutionSize()方法中,首先根据屏幕尺寸和设计分辨率计算出x和y方向的缩放值,然后根据分辨率适配模式选择*终的缩放值,计算完缩放值之后,再计算视口的大小。
void GLView::updateDesignResolutionSize()
{
if (_screenSize.width > 0 && _screenSize.height > 0
&& _designResolutionSize.width > 0 && _designResolutionSize.height
> 0)
{
_scaleX = (float)_screenSize.width / _designResolutionSize.width;
_scaleY = (float)_screenSize.height / _designResolutionSize.height;
//NO_BORDER模式下取*大的缩放值等比缩放
if (_resolutionPolicy == ResolutionPolicy::NO_BORDER)
{
_scaleX = _scaleY = MAX(_scaleX, _scaleY);
}
//SHOW_ALL模式下取*小的缩放值等比缩放
else if (_resolutionPolicy == ResolutionPolicy::SHOW_ALL)
{
_scaleX = _scaleY = MIN(_scaleX, _scaleY);
}
//FIXED_HEIGHT模式下取y轴缩放值等比缩放,并将设计分辨率的宽度调整为全屏的
宽度
else if ( _resolutionPolicy == ResolutionPolicy::FIXED_HEIGHT) {
_scaleX = _scaleY;
_designResolutionSize.width = ceilf(_screenSize.width/_scaleX);
}
//FIXED_WIDTH模式下取x轴缩放值等比缩放,并将设计分辨率的高度调整为全屏的
高度
else if ( _resolutionPolicy == ResolutionPolicy::FIXED_WIDTH) {
_scaleY = _scaleX;
_designResolutionSize.height = ceilf(_screenSize.height/_
scaleY);
}
//计算视口的尺寸,并设置视口的矩形区域
float viewPortW = _designResolutionSize.width * _scaleX;
float viewPortH = _designResolutionSize.height * _scaleY;
_viewPortRect.setRect((_screenSize.width – viewPortW) / 2,
(_screenSize.height – viewPortH) / 2, viewPortW, viewPortH);
//重置Director的成员变量来适应可视化矩形
auto director = Director::getInstance();
director->_winSizeInPoints = getDesignResolutionSize();
director->_isStatusLabelUpdated = true;
director->setGLDefaultValues();
}
}
5.2 分辨率适配经验
5.2.1 宽度或高度锁定
我们希望所有的机型都能够很完美地适配,不要拉伸!不要黑边!FIXED_HEIGHT或FIXED_WIDTH模式是比较容易做到的。
要做到上面的要求,需要选取一个范围,即要适配的分辨率比例的范围。我们都知道iPhone 5的比例非常长,应该没有什么机器比这个比例更长的了,所以一般笔者将iPhone 5的比例设置为要适配的极限比例,也就是说,如果有比iPhone 5更长的手机,笔者就基本放弃这个机型了。接下来选择一个*扁的比例,一般在平板电脑上的比例会更扁一些,纵观主流的分辨率,基本都在iPhone 5和iPad之间,所以笔者习惯将要适配的比例在iPhone 5到iPad之间(这里的是以横屏游戏为例,如果是竖屏游戏,只需要把宽和高对调一下即可)。也就是说,假设选择固定高度的FIXED_HEIGHT模式,那么就要选择一个*宽和*窄的宽度。
选择好比例之后,需要好好设计一下游戏内容,以方便不同分辨率的适配,主要包含游戏的背景、游戏的内容区域,以及UI等。
背景的设计是非常重要的一步,因为背景设计的好坏,直接决定了是否有黑边,以及游戏内容的布局。首先,背景图需要有多大?其次,游戏区域只能有多大?这些问题需要根据游戏的内容来设计。
如果是一个横屏的斗地主游戏,可以将游戏区域放在游戏的正中间,游戏内容可以根据游戏区域的原点为相对坐标计算,这时候两边各有一部分区域是可裁剪的。
如果是一个竖屏的雷电射击游戏,可以将游戏区域放在正下方,上方是可裁剪区域,敌人从上方出现,可以将上方的可裁剪区域也纳入游戏区域,敌机根据左上角为原点设置相对坐标。
如果是一个消除类游戏,如果是横屏的,一般把游戏区域放在正中间,左右两边裁剪;如果是竖屏的,一般也把游戏区域放在正中间,上下两边是可裁剪区域。
5.2.2 计算设计分辨率
使用FIXED_HEIGHT或FIXED_WIDTH模式结合一个比较大的背景,一般可以解决大部分游戏的分辨率适配问题,但如果游戏背景并不是锁定宽度或高度的,那么就需要选择其他的分辨率适配策略了。
下面介绍一个简单的适配示例,如图5-6所示。首先背景尺寸是1280×800,这个分辨率没有任何讲究,是美工随便给出的一个分辨率,是一个足够大的尺寸,宽度和高度都不进行锁定,而是根据实际设备的分辨率进行动态调整,这个分辨率尽管不怎么标准,但还是可以用来完成完美适配。
图5-6 分辨率480×320
游戏中有两部分UI,主界面的菜单面板是居中对齐,getWinSize得到的大小的一半即是居中的位置,面板设置锚点为(0.5,0.5),并设置居中的位置即可。第二部分UI是顶部的信息栏,信息栏的位置是靠上居中,信息栏设置锚点为(0.5,1.0),然后设置getWinSize的width×0.5f为x坐标,height为y坐标即可。
在这里选择的策略是SHOW_ALL,但是设计分辨率需要动态计算出来(一般的代码这里都会设置一个分辨率),因为要使用好1280×800的背景图,关键有以下几点:
* 不拉伸,不留黑边。
* 根据手机的分辨率调整可视区域(设置的标准分辨率)。
* 当目标分辨率比背景还要宽时,把目标分辨率等比缩小,直到分辨率内容全部在可视区域内。
* 当目标分辨率比背景还要高时,把目标分辨率等比缩小,直到分辨率内容全部在可视区域内。
* 当目标分辨率比背景小时,把目标分辨率等比放大,直到分辨率内容全部在可视区域内。
我们的背景分辨率是1280×800,720是笔者自己定义的一个值,因为笔者不希望整个背景太宽,所以进行了限制,然后根据实际的分辨率与预期分辨率计算出期望的高和宽(要么高变,要么宽变),代码如下。
float height = 800.0f;
float width = 1280.0f;
float ratio = sz.width / sz.height;
float maxratio = width / height;
float minratio = width / 720.0f;
if (ratio > maxratio)
{
//比*宽的还要宽
height = width / ratio;
}
else if(ratio < minratio)
{
//比*窄的还要窄
width = height * ratio;
……
评论
还没有评论。