Cocos2d-x TestApp分析

        Cocos2d-x引擎自带的解决方案中的TestApp绝对是新手学习的好材料,下面就来分析一下TestApp的结构。我的引擎版本是cocos2d-x-2.2。



        

打开解决方案cocos2d-win32.vc2010.sln,查看TestApp-》Classes:


testResource:存放资源路径的头文件

tests:添加头文件和主界面菜单的文字

VisibleRect:取得屏幕的各个边界点


1、main:win32程序的入口

    // 创建一个应用实例
    AppDelegate app;	
    CCEGLView* eglView = CCEGLView::sharedOpenGLView();
    eglView->setViewName("TestCpp");
    eglView->setFrameSize(960, 640);
    return CCApplication::sharedApplication()->run();	// 运行程序

2、AppDelegate:

bool AppDelegate::applicationDidFinishLaunching()	// 入口
{
	// As an example, load config file
	// XXX: This should be loaded before the Director is initialized,
	// XXX: but at this point, the director is already initialized
	CCConfiguration::sharedConfiguration()->loadConfigFile("configs/config-example.plist");

    // initialize director
    CCDirector *pDirector = CCDirector::sharedDirector();
    pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

    CCSize screenSize = CCEGLView::sharedOpenGLView()->getFrameSize();

    CCSize designSize = CCSizeMake(480, 320);

    CCFileUtils* pFileUtils = CCFileUtils::sharedFileUtils();
    std::vector<std::string> searchPaths;
    
	if (screenSize.height > 320)
    {
		// 如果屏幕高度大于320,则设置资源搜索路径
        CCSize resourceSize = CCSizeMake(960, 640);
        searchPaths.push_back("hd");
		searchPaths.push_back("hd/scenetest");
        pDirector->setContentScaleFactor(resourceSize.height/designSize.height);
    }
	else
	{
		searchPaths.push_back("scenetest");
	}
	pFileUtils->setSearchPaths(searchPaths);

 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
    CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionShowAll);
#else
	CCEGLView::sharedOpenGLView()->setDesignResolutionSize(designSize.width, designSize.height, kResolutionNoBorder);
#endif

	// 将布景添加到场景中并执行
    CCScene * pScene = CCScene::create();
    CCLayer * pLayer = new TestController();
    pLayer->autorelease();

    pScene->addChild(pLayer);
    pDirector->runWithScene(pScene);

    return true;
}


3、TestController是controller的类,继承CCLayer,也就是我们运行程序时的主界面,先看构造函数:

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));

    // 循环tests.h头文件的g_aTestNames名字数组,添加文字菜单
    m_pItemMenu = CCMenu::create();
    for (int i = 0; i < TESTS_COUNT; ++i)
    {
        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);
    addChild(m_pItemMenu);

    setTouchEnabled(true);

    addChild(pMenu, 1);

}

运行了程序后我们知道:每点击一个文字菜单项都会跳转到不同的场景,下面来看看菜单回调函数menuCallback:

void TestController::menuCallback(CCObject * pSender)
{
    // 通过这两句代码来识别点击的文字菜单项
    CCMenuItem* pMenuItem = (CCMenuItem *)(pSender);
    int nIdx = pMenuItem->getZOrder() - 10000;

    // 新建一个场景并运行
    TestScene* pScene = CreateTestScene(nIdx);
    if (pScene)
    {
        pScene->runThisTest();
        pScene->release();
    }
}


我们调用CreateTestScene()函数,获得一个创建好的场景,然后调用runThisTest()来切换场景,看看CreateTestScene()是何方神圣:

static TestScene* CreateTestScene(int nIdx)
{
    CCDirector::sharedDirector()->purgeCachedData();

    TestScene* pScene = NULL;

    switch (nIdx)
    {
	// 下面的这些类,存放在Classes下的那些文件夹中,比如ActionTestScene存放在Classes\ActionTest中,
	// ActionTest的头文件已经在tests.h中导入了
    case TEST_ACTIONS:
        pScene = new ActionsTestScene(); break;
    case TEST_TRANSITIONS:
        pScene = new TransitionsTestScene(); break;
     case TEST_PROGRESS_ACTIONS:
         pScene = new ProgressActionsTestScene(); break;
    case TEST_EFFECTS:
        pScene = new EffectTestScene(); break;
    case TEST_CLICK_AND_MOVE:
        pScene = new ClickAndMoveTestScene(); break;
    case TEST_ROTATE_WORLD:
        pScene = new RotateWorldTestScene(); break;
    case TEST_PARTICLE:
        pScene = new ParticleTestScene(); break;
    case TEST_EASE_ACTIONS:
        pScene = new ActionsEaseTestScene(); break;
    case TEST_MOTION_STREAK:
        pScene = new MotionStreakTestScene(); break;
    case TEST_DRAW_PRIMITIVES:
        pScene = new DrawPrimitivesTestScene(); break;
    case TEST_COCOSNODE:
        pScene = new CocosNodeTestScene(); break;
    case TEST_TOUCHES:
        pScene = new PongScene(); break;
    case TEST_MENU:
        pScene = new MenuTestScene(); break;
    case TEST_ACTION_MANAGER:
        pScene = new ActionManagerTestScene(); break;
    case TEST_LAYER:
        pScene = new LayerTestScene(); break;
    case TEST_SCENE:
        pScene = new SceneTestScene(); break;
    case TEST_PARALLAX:
        pScene = new ParallaxTestScene(); break;
    case TEST_TILE_MAP:
        pScene = new TileMapTestScene(); break;
    case TEST_INTERVAL:
        pScene = new IntervalTestScene(); break;
    case TEST_LABEL:
        pScene = new AtlasTestScene(); break;
    case TEST_TEXT_INPUT:
        pScene = new TextInputTestScene(); break;
    case TEST_SPRITE:
        pScene = new SpriteTestScene(); break;
    case TEST_SCHEDULER:
        pScene = new SchedulerTestScene(); break;
    case TEST_RENDERTEXTURE:
        pScene = new RenderTextureScene(); break;
    case TEST_TEXTURE2D:
        pScene = new TextureTestScene(); break;
#if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE)
    case TEST_CHIPMUNK:
        pScene = new ChipmunkAccelTouchTestScene(); break;
#endif
    case TEST_BOX2D:
        pScene = new Box2DTestScene(); break;
    case TEST_BOX2DBED:
        pScene = new Box2dTestBedScene(); break;
    case TEST_EFFECT_ADVANCE:
        pScene = new EffectAdvanceScene(); break;
    case TEST_ACCELEROMRTER:
        pScene = new AccelerometerTestScene(); break;
#if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)
    case TEST_KEYPAD:
        pScene = new KeypadTestScene(); break;
#endif
    case TEST_COCOSDENSHION:
        pScene = new CocosDenshionTestScene(); break;
    case TEST_PERFORMANCE:
        pScene = new PerformanceTestScene(); break;
    case TEST_ZWOPTEX:
        pScene = new ZwoptexTestScene(); break;
// bada don't support libcurl
#if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA && CC_TARGET_PLATFORM != CC_PLATFORM_NACL && CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE && CC_TARGET_PLATFORM != CC_PLATFORM_EMSCRIPTEN)
    case TEST_CURL:
	#if (CC_TARGET_PLATFORM != CC_PLATFORM_WINRT) && (CC_TARGET_PLATFORM != CC_PLATFORM_WP8)
        pScene = new CurlTestScene(); break;
    #else
	    CCMessageBox("CurlTest not yet implemented.","Alert"); break;
    #endif
#endif
    case TEST_USERDEFAULT:
        pScene = new UserDefaultTestScene(); break;
    case TEST_BUGS:
        pScene = new BugsTestScene(); break;
    case TEST_FONTS:
        pScene = new FontTestScene(); break;
    case TEST_CURRENT_LANGUAGE:
        pScene = new CurrentLanguageTestScene(); break;
#if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE)
    case TEST_TEXTURECACHE: pScene = new TextureCacheTestScene(); break;
#endif
    case TEST_EXTENSIONS:
        pScene = new ExtensionsTestScene();
        break;
    case TEST_SHADER:
#if (CC_TARGET_PLATFORM != CC_PLATFORM_WP8)
       pScene = new ShaderTestScene();
#else
		CCMessageBox("ShaderTest not yet implemented.","Alert");
#endif          
    break;

    case TEST_MUTITOUCH:
        pScene = new MutiTouchTestScene();
        break;
#if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE)
    case TEST_CLIPPINGNODE:
        pScene = new ClippingNodeTestScene();
        break;
#endif
    case TEST_FILEUTILS:
        pScene = new FileUtilsTestScene();
        break;
    case TEST_SPINE:
        pScene = new SpineTestScene();
        break;
    case TEST_TEXTUREPACKER_ENCRYPTION:
        pScene = new TextureAtlasEncryptionTestScene();
        break;
    case TEST_DATAVISTOR:
        pScene = new DataVisitorTestScene();
        break;
	case TEST_CONFIGURATION:
		pScene = new ConfigurationTestScene();
		break;
	default:
        break;
    }

    return pScene;
}

4、举一个具体的例子,比如CreateTestScene(1),执行pScene = new ActionTestScene(),并返回,此时执行pScene->runThisTest()。去ActionTest.cpp中的runThisTest():

class ActionsTestScene : public TestScene
{
public:
    virtual void runThisTest();
};


5、可以发现,ActionTestScene是继承TestScene的,而TestScene存放在testBasic.cpp中,继续查看testBasic.cpp中的TestScene:

void TestScene::onEnter()
{
    CCScene::onEnter();

	// 添加返回主场景(controller)的文字菜单
    CCLabelTTF* label = CCLabelTTF::create("MainMenu", "Arial", 20);
    CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(TestScene::MainMenuCallback));

    CCMenu* pMenu =CCMenu::create(pMenuItem, NULL);

    pMenu->setPosition( CCPointZero );
    pMenuItem->setPosition( ccp( VisibleRect::right().x - 50, VisibleRect::bottom().y + 25) );

    addChild(pMenu, 1);
}

void TestScene::MainMenuCallback(CCObject* pSender)
{
	// 可以发现这里的代码跟AppDelegate启动主场景的代码是一样的
    CCScene* pScene = CCScene::create();
    CCLayer* pLayer = new TestController();
    pLayer->autorelease();

    pScene->addChild(pLayer);
    CCDirector::sharedDirector()->replaceScene(pScene);
}

6、回到ActionTestScene中查看runThisTest():

void ActionsTestScene::runThisTest()
{
    sceneIdx = -1;
    addChild(nextAction());

    CCDirector::sharedDirector()->replaceScene(this);
}

nextAction()又是什么,nextAction()、backAction()、restartAction()对应的是程序下面的三个按钮:下一个、上一个、重启:

static CCLayer* nextAction()
{
    sceneIdx++;
    sceneIdx = sceneIdx % MAX_LAYER;
    
    CCLayer* pLayer = (createFunctions[sceneIdx])();
    pLayer->init();
    pLayer->autorelease();
    
    return pLayer;
}

static CCLayer* backAction()
{
    sceneIdx--;
    int total = MAX_LAYER;
    if( sceneIdx < 0 )
        sceneIdx += total;
    
    CCLayer* pLayer = (createFunctions[sceneIdx])();
    pLayer->init();
    pLayer->autorelease();
    
    return pLayer;
}

static CCLayer* restartAction()
{
    CCLayer* pLayer = (createFunctions[sceneIdx])();
    pLayer->init();
    pLayer->autorelease();
    
    return pLayer;
}

布景是怎么创建的呢,查看createFunctions[]数组:

TESTLAYER_CREATE_FUNC(ActionManual);
TESTLAYER_CREATE_FUNC(ActionMove);
TESTLAYER_CREATE_FUNC(ActionRotate);
TESTLAYER_CREATE_FUNC(ActionScale);
TESTLAYER_CREATE_FUNC(ActionSkew);
TESTLAYER_CREATE_FUNC(ActionRotationalSkew);
TESTLAYER_CREATE_FUNC(ActionRotationalSkewVSStandardSkew);
TESTLAYER_CREATE_FUNC(ActionSkewRotateScale);
TESTLAYER_CREATE_FUNC(ActionJump);
TESTLAYER_CREATE_FUNC(ActionCardinalSpline);
TESTLAYER_CREATE_FUNC(ActionCatmullRom);
TESTLAYER_CREATE_FUNC(ActionBezier);
TESTLAYER_CREATE_FUNC(ActionBlink);
TESTLAYER_CREATE_FUNC(ActionFade);
TESTLAYER_CREATE_FUNC(ActionTint);
TESTLAYER_CREATE_FUNC(ActionAnimate);
TESTLAYER_CREATE_FUNC(ActionSequence);
TESTLAYER_CREATE_FUNC(ActionSequence2);
TESTLAYER_CREATE_FUNC(ActionSpawn);
TESTLAYER_CREATE_FUNC(ActionReverse);
TESTLAYER_CREATE_FUNC(ActionDelayTime);
TESTLAYER_CREATE_FUNC(ActionRepeat);
TESTLAYER_CREATE_FUNC(ActionRepeatForever);
TESTLAYER_CREATE_FUNC(ActionRotateToRepeat);
TESTLAYER_CREATE_FUNC(ActionRotateJerk);
TESTLAYER_CREATE_FUNC(ActionCallFunc);
TESTLAYER_CREATE_FUNC(ActionCallFuncND);
TESTLAYER_CREATE_FUNC(ActionReverseSequence);
TESTLAYER_CREATE_FUNC(ActionReverseSequence2);
TESTLAYER_CREATE_FUNC(ActionRemoveSelf);
TESTLAYER_CREATE_FUNC(ActionOrbit);
TESTLAYER_CREATE_FUNC(ActionFollow);
TESTLAYER_CREATE_FUNC(ActionTargeted);
TESTLAYER_CREATE_FUNC(ActionMoveStacked);
TESTLAYER_CREATE_FUNC(ActionMoveJumpStacked);
TESTLAYER_CREATE_FUNC(ActionMoveBezierStacked);
TESTLAYER_CREATE_FUNC(ActionCardinalSplineStacked);
TESTLAYER_CREATE_FUNC(ActionCatmullRomStacked);
TESTLAYER_CREATE_FUNC(PauseResumeActions);
TESTLAYER_CREATE_FUNC(Issue1305);
TESTLAYER_CREATE_FUNC(Issue1305_2);
TESTLAYER_CREATE_FUNC(Issue1288);
TESTLAYER_CREATE_FUNC(Issue1288_2);
TESTLAYER_CREATE_FUNC(Issue1327);
TESTLAYER_CREATE_FUNC(Issue1398);


static NEWTESTFUNC createFunctions[] = {
    CF(ActionManual),
    CF(ActionMove),
    CF(ActionRotate),
    CF(ActionScale),
    CF(ActionSkew),
    CF(ActionRotationalSkew),
    CF(ActionRotationalSkewVSStandardSkew),
    CF(ActionSkewRotateScale),
    CF(ActionJump),
    CF(ActionCardinalSpline),
    CF(ActionCatmullRom),
    CF(ActionBezier),
    CF(ActionBlink),
    CF(ActionFade),
    CF(ActionTint),
    CF(ActionAnimate),
    CF(ActionSequence),
    CF(ActionSequence2),
    CF(ActionRemoveSelf),
    CF(ActionSpawn),
    CF(ActionReverse),
    CF(ActionDelayTime),
    CF(ActionRepeat),
    CF(ActionRepeatForever),
    CF(ActionRotateToRepeat),
    CF(ActionRotateJerk),
    CF(ActionCallFunc),
    CF(ActionCallFuncND),
    CF(ActionReverseSequence),
    CF(ActionReverseSequence2),
    CF(ActionOrbit),
    CF(ActionFollow),
    CF(ActionTargeted),
    CF(ActionMoveStacked),
    CF(ActionMoveJumpStacked),
    CF(ActionMoveBezierStacked),
    CF(ActionCardinalSplineStacked),
    CF(ActionCatmullRomStacked),
    CF(PauseResumeActions),
    CF(Issue1305),
    CF(Issue1305_2),
    CF(Issue1288),
    CF(Issue1288_2),
    CF(Issue1327),
    CF(Issue1398)
};


7、NEWTESTFUNC是一个返回CCLayer* 的函数指针类型,TESTLAYER_CREATE_FUNC和CF都是宏,这些存放在testBasic.h中:

typedef CCLayer* (*NEWTESTFUNC)();
#define TESTLAYER_CREATE_FUNC(className) \
static CCLayer* create##className() \
{ return new className(); }

#define CF(className) create##className

8、回到第六步,假设打开第一个界面:

(createFunctions[0])()  -->  (CF(ActionManual))()  -->  createActionManual()

TESTLAYER_CREATE_FUNC(ActionManual)  --> createActionManual() -->  return new ActionManual()

综上,这里主要是将各个布景的实例添加到createFunctions数组中,通过nextAction(),backAction(),restartAction()来控制场景的切换。


        其他实例也是大同小异的,语言组织得不好,不知道大家看懂了没,有问题或者意见的随便提,谢谢支持。









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值