小鱼习惯直接从代码实例来学习一套成型的引擎库。

运行cpp-empty-test

一个典型的HelloWorld程序翻看代码结构

看到了 main.h与main.cpp文件就从这里开始

#ifndef __MAIN_H__
#define __MAIN_H__ #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files:
#include <windows.h>
#include <tchar.h> // C RunTime Header Files
#include "CCStdC.h" #endif // __MAIN_H__

从这个头文件中没有得到什么有价值的信息,包含了一些库文件,还有一个就是引入了 CCStdC.h 这个文件,从命名上来看应该是Cocos2d-x的标准库头文件,打开来看了几眼,都是一些常用的宏定义,还有就是平台定义,先忽略掉这些信息,继续向下看。

main.cpp

#include "main.h"
#include "../Classes/AppDelegate.h" USING_NS_CC; int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine); // create the application instance
AppDelegate app;
return Application::getInstance()->run();
}

  打开了main.cpp文件我立刻石化了,竟然就有这么几行代码,看来cocos2d-x封装的很牛X啊

这个helloWorld的核心代码就一句 Application::getInstance()->run();

刨根问底我们去了解一下 Application类, 从在这里的调用上来看,整个cocox2d-x都封装在了Application这个类里面每一个应用程序都有唯一的一个Application对象,这种调用明显采用了单例的设计模式,我们跟一下代码,追踪线索。

打开Application.h文件发现

class CC_DLL Application : public ApplicationProtocol

  Applilcation类继承了 ApplicationProtocol类, 继续看 ApplicationProtocol.h

CCApplicationProtocol.h

#ifndef __CC_APPLICATION_PROTOCOL_H__
#define __CC_APPLICATION_PROTOCOL_H__ #include "CCPlatformMacros.h" NS_CC_BEGIN class CC_DLL ApplicationProtocol
{
public: // Since WINDOWS and ANDROID are defined as macros, we could not just use these keywords in enumeration(Platform).
// Therefore, 'OS_' prefix is added to avoid conflicts with the definitions of system macros.
enum class Platform<span style="white-space:pre"> </span>// 平台种类的一个枚举
{
OS_WINDOWS,
OS_LINUX,
OS_MAC,
OS_ANDROID,
OS_IPHONE,
OS_IPAD,
OS_BLACKBERRY,
OS_NACL,
OS_EMSCRIPTEN,
OS_TIZEN,
OS_WINRT,
OS_WP8
};
virtual ~ApplicationProtocol() {} virtual bool applicationDidFinishLaunching() = ;// 程序启动后的一个回调,应该在这里可以放置一些初始化的操作 virtual void applicationDidEnterBackground() = ;// 程序进入后台时的回调函数,pc中的最小化,手机中的程序转入后台的这个时机调用。 virtual void applicationWillEnterForeground() = ;// 程序又重回前台时的回调 virtual void setAnimationInterval(double interval) = ;// 设置动画两帧之间的时间间隔,也就是常说的帧速度之类的参数 virtual LanguageType getCurrentLanguage() = ;// 应该是和语种相关的,用来做多语言版本时得到当前语言类型参数 可以打开LanguageType看看 virtual const char * getCurrentLanguageCode() = ;// 得到当前语言的编码,返回的是一个字符串,可能是 utf8 gb2312(这里是推测) virtual Platform getTargetPlatform() = ;// 得到当前平台类型 也就是上面定义的枚举,
}; // end of platform group
/// @} NS_CC_END #endif // __CC_APPLICATION_PROTOCOL_H__

这里我把这个文件精简了一下去掉了注释

可以看到ApplicationProtocol是一个抽象类,提供了很多抽象方法,有一个平台类型的定义

enum class Platform

通过这个枚举里面的定义可以了解cocos2d-x所支持的平台各类,还是很全面的,很多小鱼都没用到过。

从纯虚函数的名称上我可以大致猜到这些函数的作用,以注释的形式写到上面代码的后面。

这个类并不复杂,都是定义了一些接口,可以推断,不同平台下的App都要分别继承这个接口来实现不同的处理。

下面我回到 Application 类 一点一点的看,确定Application这个类继承了ApplicationProtocol类

并且在这个头文件上面我看到了这样的一个宏定义

#if CC_TARGET_PLATFORM == CC_PLATFORM_WIN32

明显这个Application类是为了 Windows平台准备的

下面列出部分代码来分析

NS_CC_BEGIN

class Rect;

class CC_DLL Application : public ApplicationProtocol
{
public:
Application(); virtual ~Application(); int run(); static Application* getInstance(); CC_DEPRECATED_ATTRIBUTE static Application* sharedApplication(); virtual void setAnimationInterval(double interval);
virtual LanguageType getCurrentLanguage(); virtual const char * getCurrentLanguageCode(); virtual Platform getTargetPlatform(); /**
* Sets the Resource root path.
* @deprecated Please use FileUtils::getInstance()->setSearchPaths() instead.
*/
CC_DEPRECATED_ATTRIBUTE void setResourceRootPath(const std::string& rootResDir); CC_DEPRECATED_ATTRIBUTE const std::string& getResourceRootPath(void); void setStartupScriptFilename(const std::string& startupScriptFile); const std::string& getStartupScriptFilename(void)
{
return _startupScriptFilename;
} protected:
HINSTANCE _instance;
HACCEL _accelTable;
LARGE_INTEGER _animationInterval;
std::string _resourceRootPath;
std::string _startupScriptFilename; static Application * sm_pSharedApplication;
}; NS_CC_END

实现父类的几个虚函数我们就不讨论了。

static Application* getInstance(); 

App是个单例,这是得到app对象的静态方法,不用多说。

int run();

游戏启动及游戏循环肯定在这里了。

我们稍后再进入到run里面看个究竟,先把Application看完整

CC_DEPRECATED_ATTRIBUTE void setResourceRootPath(const std::string& rootResDir);

这个函数肯定是设置资源文件的路径地址的。

 void setStartupScriptFilename(const std::string& startupScriptFile);

设置启动脚本,这个肯定是设置启动Lua或者js脚本的地方

Application类小鱼总结一下,这个类也是一个抽象类,因为有些父类的虚函数并没有实现,是针对win32平台下的,如果 想在自己的平台使用应该仿照定义自己的Application类,主要负责启动Cocos2d-x 开发人员应该继承 Application类来定制自己的应用程序。值得学习的是这块Application的封装应用了抽象工厂的设计模式,来满足不同平台的整合

这个HelloWorld示例程序中私人订制的App类为AppDelegate类,我们打开看一下,实现了三个抽象方法.

    virtual bool applicationDidFinishLaunching();

    virtual void applicationDidEnterBackground();

    virtual void applicationWillEnterForeground();

后两个函数主要是在程序前后台运行的时候进行了暂停和恢复暂停的操作,

第一个函数 applicationdidFinishLaunching 进行了一系列初始化。稍后我们再分析它。

至此我们大致分析了Application这个类,看了源码,了解了这个类的作用,那么具体是怎么驱动的呢,我们回过头来看 Application:run()这个函数,这也是helloworld里调用 的唯一一个方法。程序从这个run开始运行。我将分析写入到代码间,这样能方便大家阅读。

int Application::run()
{
PVRFrameEnableControlWindow(false); //跟进函数看到了一些注册表的操作,操作了窗口信息的变量。先过,可以了解到如果自己有些平台性质的全局数据交互可以扩展这里面的代码。 // Main message loop:
LARGE_INTEGER nFreq;
LARGE_INTEGER nLast;
LARGE_INTEGER nNow; QueryPerformanceFrequency(&nFreq);// windows平台得到硬件时钟的频率
QueryPerformanceCounter(&nLast);//记录上一次计时的时间 // Initialize instance and cocos2d.
if (!applicationDidFinishLaunching())//调用上面提到过的私人定制的初始化过程。这也是虚函数的一个应用
{
return ;
} auto director = Director::getInstance();//得到Director类的单例对象,Director类是干什么的先不管,从字面上理解是导演的意思,肯定是一个很重要的类
auto glview = director->getOpenGLView();//可以看出 Director类里封装了关于OPENGL的操作,这里是得到opengl对象 // Retain glview to avoid glview being released in the while loop
glview->retain();//从上面的注释可以了解到在这里为了防止glview这个opengl对象在下面的循环中被释放,增加了一次引用。 while(!glview->windowShouldClose())// 游戏主循环
{
QueryPerformanceCounter(&nNow);
if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)// 计算是否达到设置的游戏帧频的时间
{
nLast.QuadPart = nNow.QuadPart; director->mainLoop();
glview->pollEvents();
}
else
{
Sleep();
}
} // Director should still do a cleanup if the window was closed manually.
if (glview->isOpenGLReady())//释放opengl
{
director->end();
director->mainLoop();
director = nullptr;
}
glview->release();
return true;
}

这里面Director这个类出镜率很高,之后我们单独分析这个类。

下面我们分析一下私人定制的applicationDidFinishLaunching函数在程序启动中都干了些什么。

bool AppDelegate::applicationDidFinishLaunching() {
// initialize director
auto director = Director::getInstance();//获取director对象,具体Director类是什么玩意,下文分析,目前可以知道这是个大管家
auto glview = director->getOpenGLView();//获取opengl渲染对象,注意这里的 auto用法,这是c++11的新特性,大家可以去百度,就是根据后面的初始化来自动识别变量类型,真是方便啊。
if(!glview) {
glview = GLView::create("Cpp Empty Test");
director->setOpenGLView(glview);
}//如果获取opengl失败那么重新创建一个opengl对象。 director->setOpenGLView(glview);// 将opengl对象绑定到大管家,大导演身上。 // Set the design resolution
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
// a bug in DirectX 11 level9-x on the device prevents ResolutionPolicy::NO_BORDER from working correctly
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::SHOW_ALL);
#else
glview->setDesignResolutionSize(designResolutionSize.width, designResolutionSize.height, ResolutionPolicy::NO_BORDER);
#endif
//这段代码是判断平台来设置此app的长宽及边框模式。还有一些预定义在AppMacros.h里面定义的,可以翻看一下。
Size frameSize = glview->getFrameSize();
vector<string> searchPath;
// In this demo, we select resource according to the frame's height.
// If the resource size is different from design resolution size, you need to set contentScaleFactor.
// We use the ratio of resource's height to the height of design resolution,
// this can make sure that the resource's height could fit for the height of design resolution.
// if the frame's height is larger than the height of medium resource size, select large resource.
if (frameSize.height > mediumResource.size.height){ searchPath.push_back(largeResource.directory);
director->setContentScaleFactor(MIN(largeResource.size.height/designResolutionSize.height, largeResource.size.width/designResolutionSize.width));}
// if the frame's height is larger than the height of small resource size, select medium resource.
else if (frameSize.height > smallResource.size.height)
{
searchPath.push_back(mediumResource.directory);
director->setContentScaleFactor(MIN(mediumResource.size.height/designResolutionSize.height, mediumResource.size.width/designResolutionSize.width));
}
// if the frame's height is smaller than the height of medium resource size, select small resource.
else
{
searchPath.push_back(smallResource.directory);
director->setContentScaleFactor(MIN(smallResource.size.height/designResolutionSize.height, smallResource.size.width/designResolutionSize.width));
} // set searching path
FileUtils::getInstance()->setSearchPaths(searchPath);
// 上面的那几段代码是针对不同分辨率读取不同的资源,并且计算了缩放比例,设置了资源路径。
// turn on display FPS 设置帧速率的显示
director->setDisplayStats(true);
// set FPS. the default value is 1.0/60 if you don't call this
director->setAnimationInterval(1.0 / );
//这里设置了帧速率,回想上面我们看Application::run代码里面while循环就是依据这块设置的速率来实现的。
// create a scene. it's an autorelease object
auto scene = HelloWorld::scene();//这里又出现了一个新的类 HelloWorld 这是什么玩意?后面再说。肯定是定义了一个场景。
// run
director->runWithScene(scene);//最后一行代码是让大总管,大导演,run这个HelloWorld场景。
return true;
}
总结:到这里我们通过HelloWorld及跟踪代码,了解了cocos2d-x的启动流程每个平台都要有一个Application类继承自ApplicationProtocol来驱动整个程序。
每个项目都要有一个自己的App类继承自相应平台的Application调用Application::run方法来实现程序的启动。
在run里面可以定制自己的启动初始化 用Application::applicationDidFinishLaunching来实现 还涉及到了几个重要的类   Director, HelloWorld里面的Layer,Scene这几个类.
下章我们来继续刨根问底从 Director  Layer  Scene这几个类开始小鱼看代码喜欢一层一层的看,也就是广度优先,而不是一个类看到底的方式。 备注:此系列文章为小鱼自己学习cocos2d-x源码的一个过程,并非教程,有些内容在前面可能在前面章节说的不准确(因小鱼也不知道),但后面涉及到后肯定会给出明确的解释。

  

Cocos2d-X3.0 刨根问底(二)----- 从HelloWorld开始的更多相关文章

  1. Cocos2D v2.0至v3.x简洁转换指南(二)

    触摸处理 我们在稍后将完成Cocos2d 3.0中触摸处理的完整教程.而现在最重要的是知道如何去启用触摸处理在你的CCNode中: self.userInteractionEnabled = TRUE ...

  2. 如何在Cocos2D 1.0 中掩饰一个精灵(六)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 掩饰一个精灵:实现代码 打开HelloWorldLayer.m并 ...

  3. 如何在Cocos2D 1.0 中掩饰一个精灵(一)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 原帖来自Ray Wunderlich写的精彩的文章 How To ...

  4. Cocos2D v2.0至v3.x简洁转换指南(三)

    Cocos2D 3.3中的注意事项 如果你在使用Cocos2D 3.3+(是SpriteBuilder 1.3+的一部分)你将不得不替分别的换所有存在的UITouch和UITouchEvent为CCT ...

  5. 如何将各种低版本的discuz版本升级到discuz x3.0

    最近在做discuz改版的项目,遇到了很多问题,相信很多拥有discuz论坛的版主,站长和程序猿在升级或改版discuz的过程中遇到过和我一样的问题,所以我开了一个discuz专栏,为大家讲解一下di ...

  6. cocos2d 2.0和UIKit混合编程, Push CCDirector的时候出现黑屏的天坑

    症状 使用cocos2d 2.0和UIKit混合编程, 有一块用cocos2d编写的小程序, 将CCDirector push到一个UINavigationController里面. 虽然事先在后台初 ...

  7. 探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs

    原文:探索ASP.Net Core 3.0系列二:聊聊ASP.Net Core 3.0 中的Startup.cs 前言:.NET Core 3.0 SDK包含比以前版本更多的现成模板. 在本文中,我将 ...

  8. 如何在Cocos2D 1.0 中掩饰一个精灵(二)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请告诉我,如果觉得不错请多多支持点赞.谢谢! hopy ;) 让我们开始吧 打开Xcode,从New Project中选择co ...

  9. cocos2d-x3.0创建第一个jsb游戏

    第一步: 最新的cocos2d-x.下载地址https://github.com/cocos2d/cocos2d-x github上最新的引擎,值得注意的是官网上发布的引擎是稳定版.选择哪种就看个人喜 ...

随机推荐

  1. 2014 Super Training #9 E Destroy --树的直径+树形DP

    原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其 ...

  2. 《The Django Book》实战--第二章--动态网页基础

    这章演示了一些最基本的Django开发动态网页的实例,由于版本不一样,我用的是Django 1.,6.3,有些地方按书上的做是不行的,所以又改了一些,写出来让大家参考. 这是一个用python写的一个 ...

  3. java 15-1 Collection集合的概述以及小功能介绍

     集合的由来:  我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储.  而要想存储多个对象,就不能是一个基本的变量,而应 ...

  4. Open Sans字体兼容问题解决办法[font-face]

    参考:http://www.tantengvip.com/2014/11/open-sans/ 1.font-face使用方法 font-face是CSS3中的一个模块,主要是把自定义的Web字体嵌入 ...

  5. sql 索引 填充因子(转)

    和索引重建最相关的是填充因子.当创建一个新索引,或重建一个存在的索引时,你可以指定一个填充因子,它是在索引创建时索引里的数据页被填充的数量.填充因子设置为100意味着每个索引页100%填满,50%意味 ...

  6. Silverlight 利用DataGrid行加载事件动态控制行列显示

    datagrid的绑定很好用,但有时候我们往往需要根据model内容来动态控制行或者列,该怎么办呢? 这时候,我们就需要用到行加载事件:在加载每一行数据的时候,根据数据的内容来控制相应的表格显示. 比 ...

  7. 思科产品选型pdf

    以前做工程时候想起了设备选型时候用过的一份文档. 有个小伙伴今天问起思科设备选型,恰好google到了这份文档 https://www.cisco.com/web/CN/products/pdf/04 ...

  8. ThinkPHP项目CMS内容管理系统开发视频教程【20课】(3.02GB)

    ThinkPHP背景介绍:     ThinkPHP是一个免费开源的,快速.简单的面向对象的轻量级PHP开发框架,遵循Apache2开源协议发布,是为了敏捷WEB应用开发和简化企业级应用开发而诞生的. ...

  9. 对于JAVA课程的期望

    对于JAVA课程的期望 我对于JAVA这门课程最初的了解可能来自于学长学姐的描述,或者是选课指南上简单的课程名称,那个时候的JAVA,对我来说遥远而又陌生,显得那么高大上,但是一转眼自己马上就要结束大 ...

  10. windows命令行

    [drive:] Change the current driver, without changing its current directory cd [drive:] [path] Just c ...