这篇文章主要是介绍主程序的框架,他理所有的实例程序,提供相应的控制。我们都知道C++的程序都是从main函数开始启动,咱们先来看一下main.cpp
#include "main.h"
#include "AppDelegate.h"
#include "CCEGLView.h"
USING_NS_CC;
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
//这个地方呢具体意义我是不太懂,功能是创建一个AppDelegate的一个实例并让他跑起来的
AppDelegate app;
CCEGLView* eglView = CCEGLView::sharedOpenGLView();
//设置窗口的标题
eglView->setViewName("TestCpp");
//设置窗口的大小
eglView->setFrameSize(960, 640);
return CCApplication::sharedApplication()->run();
}
代码不多,他是启动CCApplication,而AppDelegate是CCApplication,所以说他启动的是AppDelegate。总结一句话就是启动AppDelegate。
AppDelegate从函数applicationDidFinishLaunching开始执行。
bool AppDelegate::applicationDidFinishLaunching()
{
// 实例化导演类并设置一些参数
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize();
// CCSize designSize = CCSizeMake(2880, 1920);
CCSize designSize = CCSizeMake(720, 480);
CCFileUtils* pFileUtils = CCFileUtils::sharedFileUtils();
if (screenSize.height > 320)
{
CCSize resourceSize = CCSizeMake(1440, 960);
std::vector<std::string> searchPaths;
searchPaths.push_back("hd");
pFileUtils->setSearchPaths(searchPaths);
pDirector->setContentScaleFactor(resourceSize.height/designSize.height);
}
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionNoBorder);
// turn on display FPS
pDirector->setDisplayStats(true);
// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60);
//实例化一个CCScene(场景)
CCScene * pScene = CCScene::create();
//实例化一个CCLayer(层)
CCLayer * pLayer = new TestController();
//设置自动释放(和JAVA里的回收机制是一样的,一个对象不用了,他会自动释放内存)
pLayer->autorelease();
//将层添加到场景里
pScene->addChild(pLayer);
//最后是开始场景(就像演京剧时候似的,两边帘子退向两边,演出开始)
pDirector->runWithScene(pScene);
return true;
}
这个函数总的来说就是实例化一个层和一个场景,把层添加到场景里,然后开始场景。
就这么开始了?!!里面那些东西呢?左下角那些数字,中间的选项,右上角的关闭按钮搁那添加的?
我们前面已经说了,实例化一个层然后把这个层添加到场景里然后开始场景。这里实例化的场景是CCScene,这是引擎提供的类,他并没有被谁继承就被实例化话了,所以说这个场景里什么也没有。这个场景就想一个黑板啥也没有。我们看到实例化层的时候,他是new了一个TestController,这个时候我们就可以断定TestController这个类继承了CCLayer并且在这个类里添加了上面那些我们需要的东西。
在Controller.h里我们可以看到TestController是继承CCLayer的。我们来看一下Controller.cpp里的东西
static TestScene* CreateTestScene(int nIdx)
{
CCDirector::sharedDirector()->purgeCachedData();
TestScene* pScene = NULL;
switch (nIdx)
{
case TEST_ACTIONS:
pScene = new ActionsTestScene(); break;
case TEST_TRANSITIONS:
pScene = new TransitionsTestScene(); break;
case TEST_PROGRESS_ACTIONS:
//省略部分代码
default:
break;
}
return pScene;
}
首先是一个静态函数CreateTestScene,他接收一个int类型的参数,返回一个TestScene。可以想到我们可以用这个函数来获得场景的,就是我们点击中间的菜单,跳转到相应的界面时,这个函数会创建我们要去的那个场景的。传入一个int值,他会返回相应的场景。
接下来是TestController的构造函数
TestController::TestController()
: m_tBeginPos(CCPointZero)
{
// 添加关闭菜单,就是右上角那个
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(s_pPathClose, s_pPathClose, this, menu_selector(TestController::closeCallback) );
CCMenu* pMenu =CCMenu::create(pCloseItem, NULL);
pMenu->setPosition( CCPointZero );
pCloseItem->setPosition(ccp( VisibleRect::right().x - 30, VisibleRect::top().y - 30));
// 添加中间小实例的菜单
m_pItemMenu = CCMenu::create();
for (int i = 0; i < TESTS_COUNT; ++i)
{
//g_aTestNames可以看作是一个字符串数组,里面是菜单里要显示的文字
CCLabelTTF* label = CCLabelTTF::create(g_aTestNames[i].c_str(), "Arial", 24);
CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(TestController::menuCallback));
m_pItemMenu->addChild(pMenuItem, i + 10000);
pMenuItem->setPosition( ccp( VisibleRect::center().x, (VisibleRect::top().y - (i + 1) * LINE_SPACE) ));
}
m_pItemMenu->setContentSize(CCSizeMake(VisibleRect::getVisibleRect().size.width, (TESTS_COUNT + 1) * (LINE_SPACE)));
m_pItemMenu->setPosition(s_tCurPos);
//添加实例菜单到Layer
addChild(m_pItemMenu);
setTouchEnabled(true);
//添加关闭按钮到Layer
addChild(pMenu, 1);
}
在这个构造函数里,我们创建了实例菜单和关闭按钮并把他们加到了Layer上。
但是当我们点击其中一个菜单项的时候,他会做什么呢?我们看到在创建每一个子菜单时,我们都设置了回调函数
CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(TestController::menuCallback));
menuCallBack就是回调函数,但菜单被点击时,这个函数就会执行。
下面我们来看一下这个回调函数。
void TestController::menuCallback(CCObject * pSender)
{
// 获取被点击的子菜单项,
CCMenuItem* pMenuItem = (CCMenuItem *)(pSender);
//获取子菜单项的Zorder值,这个值就是在Z轴上的一个值,通过设置他可以影响遮挡关系
//这里呢,子菜单之间是没有遮挡关系的,这个值其实就是用来获取这个子菜单对应场景的index值
int nIdx = pMenuItem->getZOrder() - 10000;
// 通过静态方法CreateTestScene获得相应的场景并开始场景
TestScene* pScene = CreateTestScene(nIdx);
if (pScene)
{
pScene->runThisTest();
pScene->release();
}
}
同理我们可理解关闭按钮的回调函数closeCallback。
ccTouchesBegan和ccTouchesMoved实现了上下拖动实例菜单,这里我们不在讲述。