Cocos2d-x 的“HelloWorld” 深入分析(windows上的CCApplication的运作)(上)

        不能免俗,一切都从“HelloWorld!”开始.打开HelloWorld工程,里面有两个文件目录Classes和win32。

Classes下有HelloWorldScene.h/cpp ,AppDelegate.h/cpp.

win32下有main.h/cpp

       首先看一下win32目录下的main.h,其中定义了使用win32平台进行编译的宏和一些Windows编程头文件。

[cpp]  view plain copy
  1. [Cocos2d-x相关教程来源于红孩儿的游戏编程之路 CSDN博客地址:http://blog.csdn.net/honghaier]   
  2. #ifndef __MAIN_H__  
  3.   
  4. #define __MAIN_H__  
  5.   
  6. //定义使用WIN32平台进行编译的宏  
  7.   
  8. #define WIN32_LEAN_AND_MEAN              
  9.   
  10. // 所用到的Windows编程所用头文件  
  11.   
  12. #include <windows.h>  
  13.   
  14. #include <tchar.h>  
  15.   
  16. // Cocos的C语言头文件  
  17.   
  18. #include "CCStdC.h"  
  19.   
  20. #endif// __MAIN_H__  

再打开main.cpp.

[cpp]  view plain copy
  1. //加入main.h头文件  
  2.   
  3. #include "main.h"  
  4.   
  5. //加入使用的AppDelegate类头文件  
  6.   
  7. #include "../Classes/AppDelegate.h"  
  8.   
  9. //WinMain主函数  
  10.   
  11. int APIENTRY _tWinMain(HINSTANCE hInstance,  
  12.   
  13.    HINSTANCE hPrevInstance,  
  14.   
  15.    LPTSTR    lpCmdLine,  
  16.   
  17.    int       nCmdShow)  
  18.   
  19. {  
  20.   
  21. //UNREFERENCED_PARAMETER用于在VC编译器下告知编译器,不必检测改变量是否使用的警告。  
  22.   
  23. UNREFERENCED_PARAMETER(hPrevInstance);  
  24.   
  25. UNREFERENCED_PARAMETER(lpCmdLine);  
  26.   
  27.     // 创建一个Cocos2d-x程序实例  
  28.   
  29. AppDelegate app;  
  30.   
  31.     // 运行程序实例  
  32.   
  33.     return cocos2d::CCApplication::sharedApplication().run();  
  34.   
  35. }  


 

         代码看着就这么几行,好像非常简单。那是因为Cocos2d-x把很多WINDOWS窗口程序的代码都封装到了内部。这也使得它更加简单易学。但我们也应该明白这里面是怎么一回事。

             

        咱们转到AppDelegate.h,可以看到AppDelegate类是一个私有继承Cocos2d命名空间中的CCApplication类。它的成员函数均是重载了CCApplication类的成员函数。顾名思义,CCApplication代表了程序类。我们打开它的声明文件看一下:

[cpp]  view plain copy
  1. #ifndef __CC_APPLICATION_WIN32_H__  
  2.   
  3. #define __CC_APPLICATION_WIN32_H__  
  4.   
  5. //Windows头文件  
  6.   
  7. #include <Windows.h>   
  8.   
  9. //Cocos2d-x公共头文件,声明了一些公共函数以及语言类型枚举ccLanguageType  
  10.   
  11. #include "CCCommon.h"  
  12.   
  13. //使用cocos2d的命名空间来包括后面的代码  
  14.   
  15. NS_CC_BEGIN;  
  16.   
  17. //声明一下CCRect类,在CCApplication中会用到CCRect类指针  
  18.   
  19. class CCRect;  
  20.   
  21. class CC_DLL CCApplication  
  22.   
  23. {  
  24.   
  25. public:  
  26.   
  27. //构造  
  28.   
  29. CCApplication();  
  30.   
  31. //析构  
  32.   
  33.     virtual ~CCApplication();  
  34.   
  35.     //初始化  
  36.   
  37.     virtual bool initInstance() = 0;  
  38.   
  39. //程序启动后调用的函数,在这里创建设备与场景  
  40.   
  41.     virtual bool applicationDidFinishLaunching() = 0;  
  42.   
  43. //当程序转入后台,如电话打入时调用  
  44.   
  45.     virtual void applicationDidEnterBackground() = 0;  
  46.   
  47. //当程序转入前台,再次恢复时调用  
  48.   
  49.     virtual void applicationWillEnterForeground() = 0;  
  50.   
  51. //在“设备”设置FPS时调用的函数,设置帧间隔时间  
  52.   
  53. void setAnimationInterval(double interval);  
  54.   
  55. //声明一个枚举,列出当前设备的摆放方向  
  56.   
  57.     typedef enum  
  58.   
  59.     {  
  60.   
  61.         /// 垂直方向, home 键在下面  
  62.   
  63.         kOrientationPortrait = 0,  
  64.   
  65.         /// 垂直方向, home 键在上面  
  66.   
  67.         kOrientationPortraitUpsideDown = 1,  
  68.   
  69.         /// 水平方向,home键在右边  
  70.   
  71.         kOrientationLandscapeLeft = 2,  
  72.   
  73.         /// 水平方向,home健在左边  
  74.   
  75.         kOrientationLandscapeRight = 3,  
  76.   
  77.     } Orientation;  
  78.   
  79.       
  80.   
  81. //在“设备”改变了摆放方向后调用的函数,设置设备摆放方向  
  82.   
  83.     Orientation setOrientation(Orientation orientation);  
  84.   
  85. //取得窗口的状态栏所在的矩形位置  
  86.   
  87.     void    statusBarFrame(CCRect * rect);  
  88.   
  89.     //运行程序  
  90.   
  91.     int run();  
  92.   
  93. //取得当前的程序实例,这种用法可参考C++模式设计中的“单件”模式  
  94.   
  95.     static CCApplication& sharedApplication();  
  96.   
  97. //取得当前的语言类型  
  98.   
  99.     static ccLanguageType getCurrentLanguage();  
  100.   
  101. protected:  
  102.   
  103. //程序实例句柄  
  104.   
  105. HINSTANCE           m_hInstance;  
  106.   
  107. //加速键句柄  
  108.   
  109. HACCEL              m_hAccelTable;  
  110.   
  111. //声明为帧间隔,实际上是每两帧之间的频率次数  
  112.   
  113.     LARGE_INTEGER       m_nAnimationInterval;  
  114.   
  115. //单件的程序实例指针  
  116.   
  117.     static CCApplication * sm_pSharedApplication;  
  118.   
  119. };  
  120.   
  121. NS_CC_END;  
  122.   
  123. #endif// __CC_APPLICATION_WIN32_H__  

          通过对于CCApplication_win32.h的代码分析,我们可以清楚CCApplication的功能是对于程序的控制。

我们转到CCApplication类的cpp文件CCApplication_win32.cpp再来分析一下。

         读前小提示:  CCDirector代表显示设备管理器。也是一个单件类。通过其静态函数CCDirector::sharedDirector()来访问唯一的显示设备。

         重点关注函数:CCApplication(),run()。

[cpp]  view plain copy
  1. #include "CCApplication.h"  
  2. //设备头文件  
  3. #include "CCDirector.h"  
  4. //在注册表中写入对于PVRFrame的显示和隐藏的设置  
  5. static void PVRFrameEnableControlWindow(bool bEnable);  
  6. //使用cocos2d的命名空间来包括后面的代码  
  7. NS_CC_BEGIN;  
  8. // CCApplication的静态成员指针变量, 单件对象指针  
  9. CCApplication * CCApplication::sm_pSharedApplication = 0;  
  10. //构造函数  
  11. CCApplication::CCApplication()  
  12. : m_hInstance(NULL)  
  13. , m_hAccelTable(NULL)  
  14. {  
  15. //获取当前程序句柄  
  16. m_hInstance= GetModuleHandle(NULL);  
  17. //初始化m_nAnimationInterval  
  18. m_nAnimationInterval.QuadPart = 0;  
  19. //断言程序中只有一个sm_pSharedApplication。确保当前类只有一个实例对象  
  20. CC_ASSERT(! sm_pSharedApplication);  
  21. //设置单件对象指针指向当前类对象实例  
  22.     sm_pSharedApplication = this;  
  23. }  
  24. //析构  
  25. CCApplication::~CCApplication()  
  26. {  
  27. //断言程序只有一个sm_pSharedApplication就是指向当前类的实例对象  
  28.     CC_ASSERT(this == sm_pSharedApplication);  
  29.     sm_pSharedApplication = NULL;  
  30. }  
  31. //程序运行  
  32. int CCApplication::run()  
  33. {  
  34.     //设置注册表PVRFrame隐藏  
  35.     PVRFrameEnableControlWindow(false);  
  36.     //主消息循环  
  37.     MSG msg;  
  38.     LARGE_INTEGER nFreq;  
  39.     LARGE_INTEGER nLast;  
  40.     LARGE_INTEGER nNow;  
  41. //WINDOWS高精度定时器的用法,先获取频率  
  42. QueryPerformanceFrequency(&nFreq);  
  43. //获取当前的计数值,即频率x当前时间  
  44.     QueryPerformanceCounter(&nLast);  
  45. //initInstance函数为虚函数,由派生类AppDelegate进行了重载。此段代码在调用AppDelegate重载的initInstance函数之后调用applicationDidFinishLaunching函数完成一些初始化处理。  
  46. //注:AppDelegate重载initInstance函数做了什么我们暂且只先认为它如平时我们WINDOWS基本框架程序一样创建了一个Windows窗口。【伏笔1后面会有讲解】。  
  47.     if (! initInstance() || ! applicationDidFinishLaunching())  
  48.     {  
  49.         return 0;  
  50.     }  
  51. //取得当前使用的OPENGL窗口管理实例对象  
  52. CCEGLView& mainWnd = CCEGLView::sharedOpenGLView();  
  53. //将窗口居中显示  
  54.     mainWnd.centerWindow();  
  55.     ShowWindow(mainWnd.getHWnd(), SW_SHOW);  
  56. //非常熟悉!进入WINDOWS消息循环  
  57.     while (1)  
  58. {  
  59.    //如果没有获取到WINDOWS消息  
  60.         if (! PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))  
  61.         {  
  62.             // 取得当前的计数值,即频率x当前时间  
  63.             QueryPerformanceCounter(&nNow);  
  64.             //m_nAnimationInterval.QuadPart的值 为setAnimationInterval函数进行设置的固定值。此处是为了判断时间流逝了多久,是否应该更新显示设备  
  65.             if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart)  
  66.             {  
  67.   //如果时间流逝达到了设定的FPS时间差,则更新计数值。  
  68.                 nLast.QuadPart = nNow.QuadPart;  
  69.   //这里是设备渲染场景的函数,【伏笔2后面会有讲解】   
  70.                 CCDirector::sharedDirector()->mainLoop();  
  71.             }  
  72.             else  
  73.             {  
  74.   //sleep0秒的意义是让CPU做下时间片切换,防止死循环而使系统其它程序得不到响应。  
  75.                 Sleep(0);  
  76.             }  
  77.             continue;  
  78.         }  
  79.    //有消息获取到  
  80.         if (WM_QUIT == msg.message)  
  81.         {  
  82.    // 如果获取的消息是退出则退出循环。  
  83.             break;  
  84.         }  
  85.         // 如果没有定义加速键或者处理完加速键信息  
  86.         if (! m_hAccelTable || ! TranslateAccelerator(msg.hwnd, m_hAccelTable, &msg))  
  87.         {  
  88.    //处理Windows消息  
  89.             TranslateMessage(&msg);  
  90.             DispatchMessage(&msg);  
  91.         }  
  92.     }  
  93.     return (int) msg.wParam;  
  94. }  
  95.    
  96. //外部调用的设置帧间隔时间  
  97. void CCApplication::setAnimationInterval(double interval)  
  98. {  
  99.     //获取高精度定时器的频率  
  100.     LARGE_INTEGER nFreq;  
  101. QueryPerformanceFrequency(&nFreq);  
  102. //计算出频率X帧间隔时差的值存入m_nAnimationInterval用做比较值  
  103.     m_nAnimationInterval.QuadPart = (LONGLONG)(interval * nFreq.QuadPart);  
  104. }  
  105. //摆放方向变化时外部自动调用的设置摆放方向  
  106. CCApplication::Orientation CCApplication::setOrientation(Orientation orientation)  
  107. {  
  108.     //切换OPENGL视窗的宽高  
  109.     CCEGLView * pView = CCDirector::sharedDirector()->getOpenGLView();  
  110.     if (pView)  
  111.     {  
  112.         return (Orientation)pView->setDeviceOrientation(orientation);  
  113.     }  
  114.     return (Orientation)CCDirector::sharedDirector()->getDeviceOrientation();  
  115. }  
  116. //获取状态栏的位置矩形  
  117. void CCApplication::statusBarFrame(CCRect * rect)  
  118. {  
  119.     if (rect)  
  120.     {  
  121.         // WINDOWS系统没有状态栏,所以返回的矩形各位置都是0  
  122.         *rect = CCRectMake(0, 0, 0, 0);  
  123.     }  
  124. }  
  125. //  
  126. // 静态成员函数,获取单件指针  
  127. //  
  128. CCApplication& CCApplication::sharedApplication()  
  129. {  
  130.     CC_ASSERT(sm_pSharedApplication);  
  131.     return *sm_pSharedApplication;  
  132. }  
  133. //静态成员函数,获取当前系统的语言类型  
  134. ccLanguageType CCApplication::getCurrentLanguage()  
  135. {  
  136. //默认为英语  
  137.     ccLanguageType ret = kLanguageEnglish;  
  138. //  
  139. LCID localeID = GetUserDefaultLCID();  
  140. unsigned short primaryLanguageID = localeID & 0xFF;  
  141. switch (primaryLanguageID)  
  142. {  
  143. case LANG_CHINESE://中文  
  144. ret = kLanguageChinese;  
  145. break;  
  146. case LANG_FRENCH://法文  
  147. ret = kLanguageFrench;  
  148. break;  
  149. case LANG_ITALIAN://意文  
  150. ret = kLanguageItalian;  
  151. break;  
  152. case LANG_GERMAN://德文  
  153. ret = kLanguageGerman;  
  154. break;  
  155. case LANG_SPANISH://西班牙文  
  156. ret = kLanguageSpanish;  
  157. break;  
  158. case LANG_RUSSIAN://俄文  
  159. ret = kLanguageRussian;  
  160. break;  
  161. }  
  162.     return ret;  
  163. }  
  164. NS_CC_END;  
  165. //  
  166. //在注册表中写入对于PVRFrame的显示和隐藏的设置  
  167. //  
  168. static void PVRFrameEnableControlWindow(bool bEnable)  
  169. {  
  170.     HKEY hKey = 0;  
  171.     // 打开注册表的 PVRFrame 项  
  172.     if(ERROR_SUCCESS != RegCreateKeyExW(HKEY_CURRENT_USER,  
  173.         L"Software\\Imagination Technologies\\PVRVFRame\\STARTUP\\",  
  174.         0,  
  175.         0,  
  176.         REG_OPTION_NON_VOLATILE,  
  177.         KEY_ALL_ACCESS,  
  178.         0,  
  179.         &hKey,  
  180.         NULL))  
  181.     {  
  182.         return;  
  183.     }  
  184.      
  185.     const wchar_t * wszValue = L"hide_gui";  
  186.     const wchar_t * wszNewData = (bEnable) ? L"NO" : L"YES";  
  187.     wchar_t wszOldData[256] = {0};  
  188. DWORD   dwSize = sizeof(wszOldData);  
  189. //读取相应的键值  
  190. LONGstatus = RegQueryValueExW(hKey, wszValue, 0, NULL, (LPBYTE)wszOldData, &dwSize);  
  191. //如果键值不存在,或者键值存在但与当前值不同,重设键值  
  192.     if (ERROR_FILE_NOT_FOUND == status                
  193.         || (ERROR_SUCCESS == status                   
  194.         && 0 != wcscmp(wszNewData, wszOldData)))      
  195. {  
  196.         dwSize = sizeof(wchar_t) * (wcslen(wszNewData) + 1);  
  197.         RegSetValueEx(hKey, wszValue, 0, REG_SZ, (const BYTE *)wszNewData, dwSize);  
  198.     }  
  199. //关闭注册表  
  200.     RegCloseKey(hKey);  
  201. }  

          代码看完之后,我们来做一下CCApplication类的总结:

          在CCApplication的构造函数中可以看到这里定义了一个静态指针sm_pShareApplication;它在CCApplication实例化时指定为实例化单件对象的指针。在sharedApplication函数中返回实例化的单件对象引用。重点函数是run函数。在run函数开始调用了initInstance函数进行程序的初始化,调用返回为true后再调用applicationDidFinishLaunching函数完成一些逻辑的初始化工作,完成初始化后会进入WINDOWS消息循环,并通过高精度定时器进行FPS判断什么时候调用CCDirector::sharedDirector()->mainLoop()。直待收到窗口关闭的消息退出消息循环并返回。

好了,我们理解了CCApplication之后,我们再来看一下它的派生类AppDelegate,了解一下它都重载了哪些函数。

读前小提示:  CCEGLView代表OpenGL显示窗口。封装了使用OpengGL做为显示底层API的一个基本的WINDOWS窗体的创建与控制。

读前小提示:  CCDirector类中有一个函数enableRetinaDisplay函数。这个函数主要是影响到IOS平台上支持高清显示的设备如iphone4,iphone4s等。如果设置enableRetinaDisplay(false), 则在iphone4平台上运行的结果是游戏的图片分辨率降低为原来的一半,因为宽高都被拉伸了一倍。如果设置enableRetinaDisplay(true), 则在iphone4平台上运行的结果是游戏的图片分辨率正常,但是放置的位置的水平方向和垂直方向都拉伸了两倍。要记住在cocos2d里面设置精灵坐标时,使用的是点,而不是像素,在普通的iphone上,一个点就等于一个像素,而在高清显示设备中,默认一个点等于二个像素。在IOS SDK 4.0及以后的SDK中支持不同的分辨率。并提供了相应的函数对逻辑点与像素的对应比例值做设置。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值