精通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開發過程中碰到問題的程序員,以及希望學習一些實用技術,從而豐富自身經驗的程序員。對于大中專院校的學生和社會培訓班的學員,本書也是一本不可多得的學習教程。《精通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開發過程中碰到問題的程序員,以及希望學習一些實用技術,從而豐富自身經驗的程序員。對于大中專院校的學生和社會培訓班的學員,本書也是一本不可多得的學習教程。
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等交流方式,為讀者答疑解惑。
王永寶,自高一起就自學編程,至今已經10年有余。酷愛游戲開發。熟練掌握C/C 、Lua和C#等編程語言。擅長網絡編程、高并發服務端架構設計、客戶端框架設計和OpenGL等技術。2010年參加了廣東省專業杯軟件設計大賽,在31所院校的86支隊伍的激烈競爭中,憑借一個月內使用三門語言開發的塔防游戲而獲得一等獎。同年進入深圳市飯后科技有限公司,陸續擔任C 服務端主程、Unity3D主程和Cocos2d-x主程,并作為技術負責人負責了多款游戲的開發。業余時間潛心研究游戲開發,編寫了多款游戲作品。
第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 A
第5章 分辨率適配
當在不同的分辨率下運行程序時,就會碰到分辨率適配的問題,如出現黑邊、界面的一部分顯示在屏幕外,我們希望程序在不同的分辨率下運行都能有良好的表現。在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;
……
本書作者擁有豐富的一線研發經驗,對Cocos引擎也有著深入而獨到的理解。整個寫作期間,他對這本書傾注了大量的心血,精心打磨,多次對不滿意的地方推翻重寫。這份執著和熱忱加精益求精的態度令人感動。這本書內容新穎,緊跟技術趨勢,注重實際應用,講述而深入,對游戲開發人員而言是一本不可多得的專業好書,認真閱讀一定大有裨益。
——Cocos2d-x創始人 王哲
用于進階,一本很不錯的書
活動時買的,很劃算
cool……
不錯不錯不錯
很滿意的一次購物
好用的工具書!!!