介绍
Cocos2d-x是一个开源的移动2D游戏框架,MIT许可证下发布的。Cocos2d-x支持跨平台,目前版本号为v4.x。
Cocos2d-x官网(https://www.cocos.com/)
github链接(
https://github.com/cocos2d/cocos2d-x)
创建项目
首先创建一个HelloWorld项目,在源码下载下来后,打开源码目录下的
tools/cocos2d-console/bin/,里面有cocos的控制台程序,我们使用它来创建项目。
创建项目的命令参数为new,之后跟上工程名,使用的语言,以及工程目录。
这样在我的Workspace/cocos2d下就创建好了一个HelloWorld工程。
进入我们的工程,可以看到以下目录结构:
其中,proj开头的是不同平台的入口文件,cocos2d文件夹是引擎源码,Classes是我们自己的类,Resources是游戏资源文件。
创建一个build文件夹,进入执行:
cmake ..
由于我的系统是linux,所以生成了makefile文件,执行:
make
就会开始编译,编译完成后,build/bin/目录下就会有可执行文件,运行:
程序入口
首先程序是如何启动的呢?
我们打开自己对应平台的文件夹,我这里是linux,所以打开proj.linux,会发现下面有个main.cpp:
我们打开这个文件:
里面有一个main函数,可以确定这是我们程序的入口,里面定义了一个AppDelegate的对象,之后返回了Application:getInstance()->run(),我们先看一下AppDelegate这个类,它的位置在我们工程Classes目录下:
这是AppDelegate.h的代码:
#ifndef _APP_DELEGATE_H_
#define _APP_DELEGATE_H_
#include "cocos2d.h"
/**
@brief The cocos2d Application.
Private inheritance here hides part of interface from Director.
*/
class AppDelegate : private cocos2d::Application
{
public:
AppDelegate();
virtual ~AppDelegate();
virtual void initGLContextAttrs();
/**
@brief Implement Director and Scene init code here.
@return true Initialize success, app continue.
@return false Initialize failed, app terminate.
*/
virtual bool applicationDidFinishLaunching();
/**
@brief Called when the application moves to the background
@param the pointer of the application
*/
virtual void applicationDidEnterBackground();
/**
@brief Called when the application reenters the foreground
@param the pointer of the application
*/
virtual void applicationWillEnterForeground();
};
#endif // _APP_DELEGATE_H_
可以看到它继承自Application,那么我们去寻找一下Application类。
首先我们得找到cocos2d.h,引擎头文件目录在cmake里,所以代码里可以只写文件名,到时候构建的时候,会自动寻找头文件所在位置,我们的cocos2d.h在cocos2d/cocos目录下。
打开cocos2d.h:
可以看到宏会根据平台不同,导入不同的头文件,我这里是linux,所以打开
platform/linux/CCApplication-linux.h:
#pragma once
#include "platform/CCCommon.h"
#include "platform/CCApplicationProtocol.h"
#include
NS_CC_BEGIN
class Rect;
class Application : public ApplicationProtocol
{
public:
/**
* @js ctor
*/
Application();
/**
* @js NA
* @lua NA
*/
virtual ~Application();
/**
@brief Callback by Director for limit FPS.
@param interval The time, which expressed in second in second, between current frame and next.
*/
virtual void setAnimationInterval(float interval) override;
/**
@brief Run the message loop.
*/
int run();
/**
@brief Get current application instance.
@return Current application instance pointer.
*/
static Application* getInstance();
/** @deprecated Use getInstance() instead */
CC_DEPRECATED_ATTRIBUTE static Application* sharedApplication();
/* override functions */
virtual LanguageType getCurrentLanguage() override;
/**
@brief Get current language iso 639-1 code
@return Current language iso 639-1 code
*/
virtual const char * getCurrentLanguageCode() override;
/**
@brief Get application version
*/
virtual std::string getVersion() override;
/**
@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) override;
/**
* 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();
/**
@brief Get target platform
*/
virtual Platform getTargetPlatform() override;
protected:
long _animationInterval; //micro second
std::string _resourceRootPath;
static Application * sm_pSharedApplication;
};
NS_CC_END
Application继承的类只是一个接口,我们这里就看Application就可以了。
我们看一下构造函数的定义:
// sharedApplication pointer
Application * Application::sm_pSharedApplication = nullptr;
Application::Application()
: _animationInterval(1.0f/60.0f*1000.0f)
{
CC_ASSERT(! sm_pSharedApplication);
sm_pSharedApplication = this;
}
首先是初始化一个static Application的指针为nullptr,接着在构造函数里,把这个指针初始化为this,也就是这个类的对象,所以这个指针是个全局单例对象,而在我们的程序里,这个指针其实就是我们main.cpp里的app对象。接着看一下getInstance函数:
//////////////////////////////////////////////////////////////////////////
// static member function
//////////////////////////////////////////////////////////////////////////
Application* Application::getInstance()
{
CC_ASSERT(sm_pSharedApplication);
return sm_pSharedApplication;
}
这是个静态函数,这个函数返回我们的全局对象。所以main里面的run函数,实际上是Application的run:
int Application::run()
{
initGLContextAttrs();
// Initialize instance and cocos2d.
if (! applicationDidFinishLaunching())
{
return 0;
}
long lastTime = 0L;
long curTime = 0L;
auto director = Director::getInstance();
auto glview = director->getOpenGLView();
// Retain glview to avoid glview being released in the while loop
glview->retain();
while (!glview->windowShouldClose())
{
lastTime = getCurrentMillSecond();
director->mainLoop();
glview->pollEvents();
curTime = getCurrentMillSecond();
if (curTime - lastTime < _animationInterval)
{
usleep((_animationInterval - curTime + lastTime)*1000);
}
}
/* Only work on Desktop
* Director::mainLoop is really one frame logic
* when we want to close the window, we should call Director::end();
* then call Director::mainLoop to do release of internal resources
*/
if (glview->isOpenGLReady())
{
director->end();
director->mainLoop();
director = nullptr;
}
glview->release();
return EXIT_SUCCESS;
}
值得注意的是Application里面的虚函数,实际上run里面调用的是由AppDelegate实现的。
里面的循环逻辑实际上主要是director->mainLoop(),下结教程我们会讲解director的mainLoop。