进行分析下cocos的入口,简单的学习下ApplicationProtocol,Application,AppDelegate,GLContextAttrs,GLView这几个类。
游戏的入口是从AppDelegate开始的,但是,ApplDelegate继承自Application,Application继承自ApplicationProtocol。他们的关系如下:
ApplicationProtocol:
这是个协议类,只是声明了一些抽象接口。他们每个方法的作用在上图中都说清楚了,就不上代码了。
Application:
代码:
.h
class CC_DLL Application : public ApplicationProtocol
{
public:
/**
* @js ctor
*/
Application();
/**
* @js NA
* @lua NA
*/
virtual ~Application();
/**
@brief Run the message loop.
*/
/// 游戏的主循环都在这里来,包括逻辑,绘制,事件等
int run();
/**
@brief Get current applicaiton instance.
@return Current application instance pointer.
得到当前程序的实例
*/
static Application* getInstance();
/** @deprecated Use getInstance() instead */
/// 废弃掉了
CC_DEPRECATED_ATTRIBUTE static Application* sharedApplication();
/* override functions */
/// 设置动画间隔
virtual void setAnimationInterval(double interval);
/// 得到当前系统的语言
virtual LanguageType getCurrentLanguage();
/// 返回当前语言的ISO 639编码
/// ISO 639:
///ISO 639-1是国际标准化组织ISO 639语言编码标准的第一部分。它含有 136 个两字母的编码,用来标示世界上主要的语言。(百度的)
virtual const char * getCurrentLanguageCode();
/**
@brief Get target platform
*/
/// 当前平台的标签
virtual Platform getTargetPlatform();
/**
@brief Open url in default browser
@param String with url to open.
@return true if the resource located by the URL was successfully opened; otherwise false.
*/
/// 通过默认浏览器,打开网页
virtual bool openURL(const std::string &url);
/**
* Sets the Resource root path.
* @deprecated Please use FileUtils::getInstance()->setSearchPaths() instead.
*/
/// 设置资源的根目录
CC_DEPRECATED_ATTRIBUTE void setResourceRootPath(const std::string& rootResDir);
/**
* Gets the Resource root path.
* @deprecated Please use FileUtils::getInstance()->getSearchPaths() instead.
*/
/// 得到资源的根目录
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;/// 单例
};
.cpp
/**
@brief This function change the PVRFrame show/hide setting in register.
@param bEnable If true show the PVRFrame window, otherwise hide.
在注册表中写入PVRFrame的显示和隐藏设置
*/
static void PVRFrameEnableControlWindow(bool bEnable);
NS_CC_BEGIN
// sharedApplication pointer
Application * Application::sm_pSharedApplication = 0;
Application::Application()
: _instance(nullptr)
, _accelTable(nullptr)
{
_instance = GetModuleHandle(nullptr);
_animationInterval.QuadPart = 0;
CC_ASSERT(! sm_pSharedApplication);
sm_pSharedApplication = this;
}
Application::~Application()
{
CC_ASSERT(this == sm_pSharedApplication);
sm_pSharedApplication = nullptr;
}
int Application::run()
{
//设置PVRFrame不可用
PVRFrameEnableControlWindow(false);
// Main message loop:
LARGE_INTEGER nLast;
LARGE_INTEGER nNow;
QueryPerformanceCounter(&nLast);
//初始化OpenGL的背景属性
initGLContextAttrs();
// Initialize instance and cocos2d.
//初始化单例和cocos2d,方法中初始化了导演类和场景
if (!applicationDidFinishLaunching())
{
return 1;
}
auto director = Director::getInstance();//初始化后才能调用
auto glview = director->getOpenGLView();
// Retain glview to avoid glview being released in the while loop
//保持glview避免在while循环中glview被释放
glview->retain();
//如过窗口还没关闭,那么,执行这个循环
while(!glview->windowShouldClose())
{
//查询性能计数器
//QueryPerformanceCounter来查询定时器的计数值,如果硬件里有定时器,
//它就会启动这个定时器,并且不断获取定时器的值,这样的定时器精度,就跟硬件时钟的晶振一样精确的。
QueryPerformanceCounter(&nNow);
if (nNow.QuadPart - nLast.QuadPart > _animationInterval.QuadPart)
{
nLast.QuadPart = nNow.QuadPart - (nNow.QuadPart % _animationInterval.QuadPart);
//主循环,有对Director的销毁,重启和绘制操作
director->mainLoop();
//检测输入事件
glview->pollEvents();
}
else
{
Sleep(1);
}
}
// Director should still do a cleanup if the window was closed manually.
//导演需要执行一次清除,如果窗口手动关闭
//检测是否还有窗口,如果是直接关闭窗口,那么执行这个操作,如果是 director->end();那么不执行这个操作
if (glview->isOpenGLReady())
{
director->end();
director->mainLoop();
director = nullptr;
}
glview->release();
return 0;
}
void Application::setAnimationInterval(double interval)
{
LARGE_INTEGER nFreq;
QueryPerformanceFrequency(&nFreq);
_animationInterval.QuadPart = (LONGLONG)(interval * nFreq.QuadPart);
}
//////////////////////////////////////////////////////////////////////////
// static member function 静态函数(类函数)
//////////////////////////////////////////////////////////////////////////
Application* Application::getInstance()
{
CC_ASSERT(sm_pSharedApplication);
return sm_pSharedApplication;
}
// @deprecated Use getInstance() instead
Application* Application::sharedApplication()
{
return Application::getInstance();
}
LanguageType Application::getCurrentLanguage()
{
LanguageType ret = LanguageType::ENGLISH;
LCID localeID = GetUserDefaultLCID();
unsigned short primaryLanguageID = localeID & 0xFF;
/// 各种语言
switch (primaryLanguageID)
{
case LANG_CHINESE:
ret = LanguageType::CHINESE;
break;
case LANG_ENGLISH:
ret = LanguageType::ENGLISH;
break;
.............
break;
}
return ret;
}
const char * Application::getCurrentLanguageCode()
{
LANGID lid = GetUserDefaultUILanguage();
const LCID locale_id = MAKELCID(lid, SORT_DEFAULT);
static char code[3] = { 0 };
GetLocaleInfoA(locale_id, LOCALE_SISO639LANGNAME, code, sizeof(code));
code[2] = '\0';
return code;
}
Application::Platform Application::getTargetPlatform()
{
return Platform::OS_WINDOWS;
}
bool Application::openURL(const std::string &url)
{
WCHAR *temp = new WCHAR[url.size() + 1];
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, url.c_str(), url.size() + 1, temp, url.size() + 1);
HINSTANCE r = ShellExecuteW(NULL, L"open", temp, NULL, NULL, SW_SHOWNORMAL);
delete[] temp;
return (size_t)r>32;
}
void Application::setResourceRootPath(const std::string& rootResDir)
{
_resourceRootPath = rootResDir;
std::replace(_resourceRootPath.begin(), _resourceRootPath.end(), '\\', '/');
if (_resourceRootPath[_resourceRootPath.length() - 1] != '/')
{
_resourceRootPath += '/';
}
FileUtils* pFileUtils = FileUtils::getInstance();
std::vector<std::string> searchPaths = pFileUtils->getSearchPaths();
searchPaths.insert(searchPaths.begin(), _resourceRootPath);
pFileUtils->setSearchPaths(searchPaths);
}
const std::string& Application::getResourceRootPath(void)
{
return _resourceRootPath;
}
void Application::setStartupScriptFilename(const std::string& startupScriptFile)
{
_startupScriptFilename = startupScriptFile;
std::replace(_startupScriptFilename.begin(), _startupScriptFilename.end(), '\\', '/');
}
NS_CC_END
//////////////////////////////////////////////////////////////////////////
// Local function 局部函数
//////////////////////////////////////////////////////////////////////////
static void PVRFrameEnableControlWindow(bool bEnable)
{
HKEY hKey = 0;
// Open PVRFrame control key, if not exist create it.
// 打开PVRFrame的控制键,如果没有则创建它
if(ERROR_SUCCESS != RegCreateKeyExW(HKEY_CURRENT_USER,
L"Software\\Imagination Technologies\\PVRVFRame\\STARTUP\\",
0,
0,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
0,
&hKey,
nullptr))
{
return;
}
const WCHAR* wszValue = L"hide_gui";
const WCHAR* wszNewData = (bEnable) ? L"NO" : L"YES";
WCHAR wszOldData[256] = {0};
DWORD dwSize = sizeof(wszOldData);
LSTATUS status = RegQueryValueExW(hKey, wszValue, 0, nullptr, (LPBYTE)wszOldData, &dwSize);
if (ERROR_FILE_NOT_FOUND == status // the key not exist
|| (ERROR_SUCCESS == status // or the hide_gui value is exist
&& 0 != wcscmp(wszNewData, wszOldData))) // but new data and old data not equal
{
dwSize = sizeof(WCHAR) * (wcslen(wszNewData) + 1);
RegSetValueEx(hKey, wszValue, 0, REG_SZ, (const BYTE *)wszNewData, dwSize);
}
RegCloseKey(hKey);
}
GLView:
代码:
.h
/** There are some Resolution Policy for Adapt to the screen. */
//这里是一些关于屏幕适配的策略
enum class ResolutionPolicy
{
/** The entire application is visible in the specified area without trying to preserve the original aspect ratio.
* Distortion can occur, and the application may appear stretched or compressed.
*整个程序是可见的在规定区域,不尝试去保持原始的比例。
*将会有失真,程序(界面)或许会被拉伸或压缩
*/
EXACT_FIT,
/** The entire application fills the specified area, without distortion but possibly with some cropping,
* while maintaining the original aspect ratio of the application.
*整个程序将会填充规定区域,不会有失真但是可能会有一些裁切,当保持程序原始比例的时候。
*/
NO_BORDER,
/** The entire application is visible in the specified area without distortion while maintaining the original
* aspect ratio of the application. Borders can appear on two sides of the application.
*整个程序将会被显示没有失真当保持程序原有比例的时候。但是,黑边可能会在程序的左右两侧或上下两侧出现。
*/
SHOW_ALL,
/** The application takes the height of the design resolution size and modifies the width of the internal
* canvas so that it fits the aspect ratio of the device.
* No distortion will occur however you must make sure your application works on different
* aspect ratios.
*程序根据设计分辨率的高适应内部画布的宽,所以,他能适应设备的设置比例。
*
*/
FIXED_HEIGHT,
/** The application takes the width of the design resolution size and modifies the height of the internal
* canvas so that it fits the aspect ratio of the device.
* No distortion will occur however you must make sure your application works on different
* aspect ratios.
*/
FIXED_WIDTH,
UNKNOWN,
};
/** @struct GLContextAttrs
*
* There are six opengl Context Attrs.
*有OpenGL的6个背景属性
*/
struct GLContextAttrs
{
int redBits;
int greenBits;
int blueBits;
int alphaBits;
int depthBits;
int stencilBits;
};
NS_CC_BEGIN
/**
* @addtogroup core
* @{
*/
/**
* @brief By GLView you can operate the frame information of EGL view through some function.
*通过GLView你可以通过一些函数操作EGL试图的帧信息
*EGL详解:
*http://www.cnblogs.com/wanqieddy/archive/2011/11/24/2261457.html
*/
class CC_DLL GLView : public Ref
{
public:
/**
* @js ctor
*/
GLView();
/**
* @js NA
* @lua NA
*/
virtual ~GLView();
/** Force destroying EGL view, subclass must implement this method. */
//强制销毁EGL视图,子类必须实现这个接口
virtual void end() = 0;
/** Get whether opengl render system is ready, subclass must implement this method. */
//opengl 渲染系统是不是已经准备好,子类必须实现这个接口
virtual bool isOpenGLReady() = 0;
/** Exchanges the front and back buffers, subclass must implement this method. */
//交换前后缓冲区,子类必须实现这个接口
virtual void swapBuffers() = 0;
/** Open or close IME keyboard , subclass must implement this method.
*开启或者关闭IME键盘
*(IME:Input Method Editors中文名称输入法编辑器。它是一种程序,能使用户用 101
*键的标准键盘输入亚洲语言中数以千计的字符。IME 由将键击转换为拼音和表意字符的
*引擎和通常用于表意字的字典组成。当用户输入键击时,IME 引擎会尝试确定应将键击
*转换成哪个(哪些)字符。),
*子类必须实现这个接口.
* @param open Open or close IME keyboard.
*/
virtual void setIMEKeyboardState(bool open) = 0;
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
virtual void setIMEKeyboardState(bool open, std::string str) = 0;
#endif
/** When the window is closed, it will return false if the platforms is Ios or Android.
* If the platforms is windows or Mac,it will return true.
*在Ios和安卓平台当窗口被关闭的时候,这个方法将返回false,
*在Windows或者MAC平台,这个方法将返回true
* @return In ios and android it will return false,if in windows or Mac it will return true.
*/
virtual bool windowShouldClose() { return false; };
/** Static method and member so that we can modify it on all platforms before create OpenGL context.
*静态成员和方法,我们可以修改它在所有的平台上在生成OpenGL背景前
* @param glContextAttrs The OpenGL context attrs.
*/
static void setGLContextAttrs(GLContextAttrs& glContextAttrs);
/** Return the OpenGL context attrs.
*返回OpenGL背景属性
* @return Return the OpenGL context attrs.
*/
static GLContextAttrs getGLContextAttrs();
/** The OpenGL context attrs. */
//OpenGL背景属性
static GLContextAttrs _glContextAttrs;
/** @deprecated
* Polls input events. Subclass must implement methods if platform
* does not provide event callbacks.
*已经废弃,
*检查输入事件,子类必须实现这个接口如果平台不支持事件回调
*/
CC_DEPRECATED_ATTRIBUTE virtual void pollInputEvents();
/** Polls the events. */
//检查事件
//检查输入事件,子类必须实现这个接口如果平台不支持事件回调
virtual void pollEvents();
/**
* Get the frame size of EGL view.
* In general, it returns the screen size since the EGL view is a fullscreen view.
*得到EGL视图的框架尺寸。
*通常来说,如果EGL试图是全屏视图,将返回屏幕的尺寸
* @return The frame size of EGL view.
*/
virtual const Size& getFrameSize() const;
/**
* Set the frame size of EGL view.
*设置EGL试图的框架尺寸
* @param width The width of the fram size.
* @param height The height of the fram size.
*/
virtual void setFrameSize(float width, float height);
/** Set zoom factor for frame. This methods are for
* debugging big resolution (e.g.new ipad) app on desktop.
* 设置框架的缩放系数。这个方法是为了调试大分辨率的桌面程序
* @param zoomFactor The zoom factor for frame.
*/
virtual void setFrameZoomFactor(float zoomFactor) {}
/** Get zoom factor for frame. This methods are for
* debugging big resolution (e.g.new ipad) app on desktop.
*得到框架的缩放系数。这个方法是为了调试大分辨率的桌面程序
* @return The zoom factor for frame.
*/
virtual float getFrameZoomFactor() const { return 1.0; }
/**
* Hide or Show the mouse cursor if there is one.
*显示或隐藏鼠标的光标,如果有鼠标的话。
* @param isVisible Hide or Show the mouse cursor if there is one.
*/
virtual void setCursorVisible(bool isVisible) {}
/** Get retina factor.
*得到视网膜屏的系数
* @return The retina factor.
*/
virtual int getRetinaFactor() const { return 1; }
/** Only works on ios platform. Set Content Scale of the Factor. */
//只在IOS平台有效,设置内容的缩放系数
virtual bool setContentScaleFactor(float scaleFactor) { return false; }
/** Only works on ios platform. Get Content Scale of the Factor. */
/// 得到内容的缩放系数,只在IOS平台有效
virtual float getContentScaleFactor() const { return 1.0; }
/** Returns whether or not the view is in Retina Display mode.
*判断当前的视图是不是视网膜显示模式
* @return Returns whether or not the view is in Retina Display mode.
*/
virtual bool isRetinaDisplay() const { return false; }
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
virtual void* getEAGLView() const { return nullptr; }
#endif /* (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) */
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
virtual Size getRenerTargetSize() const = 0;
virtual const Mat4& getOrientationMatrix() const = 0;
virtual const Mat4& getReverseOrientationMatrix() const = 0;
#endif
/**
* Get the visible area size of opengl viewport.
*得到OpenGL视窗的可视区域
* @return The visible area size of opengl viewport.
*/
virtual Size getVisibleSize() const;
/**
* Get the visible origin point of opengl viewport.
*得到OpenGL视窗的可视原点
* @return The visible origin point of opengl viewport.
*/
virtual Vec2 getVisibleOrigin() const;
/**
* Get the visible rectangle of opengl viewport.
*得到OpenGL视窗的可视矩形
* @return The visible rectangle of opengl viewport.
*/
virtual Rect getVisibleRect() const;
/**
* Set the design resolution size.
* @param width Design resolution width.
* @param height Design resolution height.
* @param resolutionPolicy The resolution policy desired, you may choose:
* [1] EXACT_FIT Fill screen by stretch-to-fit: if the design resolution ratio of width to height is different from the screen resolution ratio, your game view will be stretched.
* [2] NO_BORDER Full screen without black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two areas of your game view will be cut.
* [3] SHOW_ALL Full screen with black border: if the design resolution ratio of width to height is different from the screen resolution ratio, two black borders will be shown.
*设置设计分辨率的尺寸和分辨率策略
*/
virtual void setDesignResolutionSize(float width, float height, ResolutionPolicy resolutionPolicy);
/** Get design resolution size.
* Default resolution size is the same as 'getFrameSize'.
*返回设计分辨率,默认的尺寸与getFrameSize的结果一样
* @return The design resolution size.
*/
virtual const Size& getDesignResolutionSize() const;
/**
* Set opengl view port rectangle with points.
*通过点设置OpenGL视窗的矩形
* @param x Set the points of x.
* @param y Set the points of y.
* @param w Set the width of the view port
* @param h Set the Height of the view port.
*/
virtual void setViewPortInPoints(float x , float y , float w , float h);
/**
* Set Scissor rectangle with points.
*通过点设置裁切矩形
* @param x Set the points of x.
* @param y Set the points of y.
* @param w Set the width of the view port
* @param h Set the Height of the view port.
*/
virtual void setScissorInPoints(float x , float y , float w , float h);
/**
* Get whether GL_SCISSOR_TEST is enable.
*裁切是否可用
* @return Whether GL_SCISSOR_TEST is enable.
*/
virtual bool isScissorEnabled();
/**
* Get the current scissor rectangle.
*返回当前裁切矩形
* @return The current scissor rectangle.
*/
virtual Rect getScissorRect() const;
/** Set the view name.
*设置视图的名字
* @param viewname A string will be set to the view as name.
*/
virtual void setViewName(const std::string& viewname);
/** Get the view name.
*返回视图的名字
* @return The view name.
*/
const std::string& getViewName() const;
/** Touch events are handled by default; if you want to customize your handlers, please override this function.
*点击事件被自动管理,如果你想定制自己的管理器,请重载这个方法
* @param num The number of touch.
* @param ids The identity of the touch.
* @param xs The points of x.
* @param ys The points of y.
*/
virtual void handleTouchesBegin(int num, intptr_t ids[], float xs[], float ys[]);
/** Touch events are handled by default; if you want to customize your handlers, please override this function.
*
* @param num The number of touch.
* @param ids The identity of the touch.
* @param xs The points of x.
* @param ys The points of y.
*/
virtual void handleTouchesMove(int num, intptr_t ids[], float xs[], float ys[]);
/** Touch events are handled by default; if you want to customize your handlers, please override this function.
*
* @param num The number of touch.
* @param ids The identity of the touch.
* @param xs The points of x.
* @param ys The points of y.
*/
virtual void handleTouchesEnd(int num, intptr_t ids[], float xs[], float ys[]);
/** Touch events are handled by default; if you want to customize your handlers, please override this function.
*
* @param num The number of touch.
* @param ids The identity of the touch.
* @param xs The points of x.
* @param ys The points of y.
*/
virtual void handleTouchesCancel(int num, intptr_t ids[], float xs[], float ys[]);
/**
* Get the opengl view port rectangle.
*得到OpenGL视窗的矩形
* @return Return the opengl view port rectangle.
*/
const Rect& getViewPortRect() const;
/**
* Get list of all active touches.
*得到所有激活的点击事件
* @return A list of all active touches.
*/
std::vector<Touch*> getAllTouches() const;
/**
* Get scale factor of the horizontal direction.
*得到水平方向的缩放系数
* @return Scale factor of the horizontal direction.
*/
float getScaleX() const;
/**
* Get scale factor of the vertical direction.
*得到竖直方向的缩放系数
* @return Scale factor of the vertical direction.
*/
float getScaleY() const;
/** Returns the current Resolution policy.
*返回当前的屏幕适应策略
* @return The current Resolution policy.
*/
ResolutionPolicy getResolutionPolicy() const { return _resolutionPolicy; }
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
virtual HWND getWin32Window() = 0;
#endif /* (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32) */
#if (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
virtual id getCocoaWindow() = 0;
#endif /* (CC_TARGET_PLATFORM == CC_PLATFORM_MAC) */
protected:
void updateDesignResolutionSize();
void handleTouchesOfEndOrCancel(EventTouch::EventCode eventCode, int num, intptr_t ids[], float xs[], float ys[]);
// real screen size
//屏幕的真实尺寸
Size _screenSize;
// resolution size, it is the size appropriate for the app resources.
//设计分辨率尺寸
Size _designResolutionSize;
// the view port size
//视窗尺寸
Rect _viewPortRect;
// the view name
//视窗名字
std::string _viewName;
float _scaleX;
float _scaleY;
ResolutionPolicy _resolutionPolicy;
};