cocos2d-x 笔记(四) TestCpp源码分析:control

来源:互联网 发布:windows程序设计c 编辑:程序博客网 时间:2024/05/29 18:33

Orca原创,转贴请标明链接Orca的移动开发轨迹。

目前整个学习笔记的版本是cocos2d-x 2.1.0beta3。

从这篇开始分析TestCpp的源码。这里借鉴了红孩儿的游戏编程之路的讲解方法,对此致谢。有点撞车,不过以下还是全部由我自己分析的内容。好了,开始吧。

这里看看整个TestCpp的控制流程,也就是说从control开始。

先看Appdelegate.cpp里面与HelloCpp不同的地方

// 创建TestController对象。    CCLayer * pLayer = new TestController();    pLayer->autorelease();// // 改成这样可以吗?// CCLayer *pLayer = TestController::create();    pScene->addChild(pLayer);    pDirector->runWithScene(pScene);

我们现在创建新的layer都是使用create(),为什么这里不用这种方法?抱着这种疑问,我们可以去看看CCLayer的create()方法:

CCLayer *CCLayer::create(){    CCLayer *pRet = new CCLayer();    if (pRet && pRet->init())    {        pRet->autorelease();        return pRet;    }    else    {        CC_SAFE_DELETE(pRet);        return NULL;    }}
这里不再深入解释,总之,一般的情况下,layer的构造方式是使用init()方法,把所有的都写在里面。而接下来我们就可以看到,这个controller的构造方式并非如此,所以不能使用这种方式来进行处理。

言归正传,可见TestCpp里面就是新建了一个TestController的Layer,用这个layer来控制整个testcpp。

好了,这样我们就去看看TestController。

先看头文件TestController.h

#ifndef _CONTROLLER_H_#define _CONTROLLER_H_#include "cocos2d.h"USING_NS_CC;class TestController : public CCLayer{public:// 构造函数    TestController();// 析构函数    ~TestController();// 菜单的返回方法    void menuCallback(CCObject * pSender);// 关闭的返回方法    void closeCallback(CCObject * pSender);// 重写触摸开始的方法    virtual void ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent);// 重写触摸移动的方法    virtual void ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent);private:// 开始位置    CCPoint m_tBeginPos;// Menu层    CCMenu* m_pItemMenu;};#endif

其实也没什么好说的,看一下源文件TestController.cpp吧

#include "controller.h"// tests资源管理#include "testResource.h"// tests管理#include "tests.h"// 定义每一行标题的高度#define LINE_SPACE          40// 光标位置static CCPoint s_tCurPos = CCPointZero;/************************************************************************//*  创建每一个测试场景                                                                     *//************************************************************************/static TestScene* CreateTestScene(int nIdx){// 释放所有缓存    CCDirector::sharedDirector()->purgeCachedData();// 创建指向场景的指针。TestScene是在testbasic.h里面声明的    TestScene* pScene = NULL;// 根据参数不同创建不同的场景    switch (nIdx)    {// 枚举常量TEST_XXX是在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;#if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE)// bada don't support libcurl#if (CC_TARGET_PLATFORM != CC_PLATFORM_BADA)    case TEST_CURL:        pScene = new CurlTestScene(); 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:        pScene = new ShaderTestScene();        break;    case TEST_MUTITOUCH:        pScene = new MutiTouchTestScene();        break;#if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE)    case TEST_CLIPPINGNODE:        pScene = new ClippingNodeTestScene();        break;#endif    default:        break;    }// 返回创建的场景    return pScene;}// 构造函数TestController::TestController(): m_tBeginPos(CCPointZero){    // add close menu// 增加关闭menu的MenuItemImage    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(s_pPathClose, s_pPathClose, this, menu_selector(TestController::closeCallback) );// 创建menu    CCMenu* pMenu =CCMenu::create(pCloseItem, NULL);// 设置menu层的位置在左下角    pMenu->setPosition( CCPointZero );// 设置按钮的位置在右上角。这里的VisibleRect是由包含在tests.h里面的testbasic.h里面的VisibleRect.h来进行声明的,表示的是各个角落    pCloseItem->setPosition(ccp( VisibleRect::right().x - 30, VisibleRect::top().y - 30));    // add menu items for tests// 创建测试菜单    m_pItemMenu = CCMenu::create();// TESTS_COUNT是在testbasic.h里面声明的    for (int i = 0; i < TESTS_COUNT; ++i)    {// #if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)//         CCLabelBMFont* label = CCLabelBMFont::create(g_aTestNames[i].c_str(),  "fonts/arial16.fnt");// #else// 创建label,g_aTestNames是在tests.h里面。c_str()是封装的用于转换String类为C风格字符串字面值的方法        CCLabelTTF* label = CCLabelTTF::create(g_aTestNames[i].c_str(), "Arial", 24);// #endif        // 通过Label创建MenuItem        CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(TestController::menuCallback));// 在测试菜单中加入这个MenuItem         m_pItemMenu->addChild(pMenuItem, i + 10000);// 设置这个MenuItem的位置        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中添加关闭menu    addChild(pMenu, 1);}TestController::~TestController(){}void TestController::menuCallback(CCObject * pSender){    // get the userdata, it's the index of the menu item clicked// 获取用户所点击的MenuItem的指针    CCMenuItem* pMenuItem = (CCMenuItem *)(pSender);// 根据定义时的zOrder获取MenuItem的id    int nIdx = pMenuItem->getZOrder() - 10000;    // create the test scene and run it// 根据id创建对应的场景    TestScene* pScene = CreateTestScene(nIdx);// 如果创建没有问题    if (pScene)    {// 运行TestScene各派生类重写的虚函数runThisTest()        pScene->runThisTest();        // 释放场景pScene->release();    }}void TestController::closeCallback(CCObject * pSender){// 关闭director    CCDirector::sharedDirector()->end();#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)    exit(0);#endif}void TestController::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent){//  获得当前CCTouch对象的指针    CCSetIterator it = pTouches->begin();// 类型转换    CCTouch* touch = (CCTouch*)(*it);// 设置初始位置为第一个CCTouch的位置    m_tBeginPos = touch->getLocation();    }void TestController::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent){// 获得当前CCTouch对象的指针    CCSetIterator it = pTouches->begin();// 类型转换    CCTouch* touch = (CCTouch*)(*it);// 获得当前的位置    CCPoint touchLocation = touch->getLocation();    // 获得移动了多少    float nMoveY = touchLocation.y - m_tBeginPos.y;// 获取整个Menu的位置    CCPoint curPos  = m_pItemMenu->getPosition();// 根据Y轴的移动量设置Menu的下一个位置    CCPoint nextPos = ccp(curPos.x, curPos.y + nMoveY);// 如果下一个位置的Y坐标低于最低值,则移动到最上面。    if (nextPos.y < 0.0f)    {        m_pItemMenu->setPosition(CCPointZero);        return;    }// 如果下一个位置的Y坐标高于最高值,则移动到最下面。    if (nextPos.y > ((TESTS_COUNT + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height))    {        m_pItemMenu->setPosition(ccp(0, ((TESTS_COUNT + 1)* LINE_SPACE - VisibleRect::getVisibleRect().size.height)));        return;    }// 不是以上两种情况则移动到下一个位置    m_pItemMenu->setPosition(nextPos);// 用于计算的初始位置移动到当前位置    m_tBeginPos = touchLocation;// 光标位置移动到下一个位置    s_tCurPos   = nextPos;}


看完以后可以回答一下我们刚才的疑问。因为这里直接使用构造函数创建,而不是在init()里面构建的,所以无法使用create,而是必须new以后再autorelease()。

好,接下来我们看看tests.h和testResource.h。

testResource.h里面全部都是资源的名字,没什么可说的。tests.h里面则是包含所有的头文件以及全局用的枚举值,也没什么好说的。

然后VisibleRect.h和VisibleRect.cpp主要是用来计算屏幕各参考点的位置的,基本没什么好说的。

接下来我们看一下在所有的测试例子中都引用了的testBasic.h及其源文件testBasic.cpp。

首先是testBasic.h:

#ifndef _TEST_BASIC_H_#define _TEST_BASIC_H_#include "cocos2d.h"#include "VisibleRect.h"USING_NS_CC;using namespace std;/************************************************************************//*  TestScene类,所有的Test例子的场景都由这个类派生                                                                     *//************************************************************************/class TestScene : public CCScene{public: // 构造函数    TestScene(bool bPortrait = false);// 重写进入scene时的onEnter()    virtual void onEnter();// 纯虚函数runThisTest,说明本类不会被实例化。    virtual void runThisTest() = 0;    // The CallBack for back to the main menu scene// 返回主菜单的CallBack函数    virtual void MainMenuCallback(CCObject* pSender);};// 定义了一个指向无参数,返回值为CCLayer的函数指针NEWTESTFUNCtypedef CCLayer* (*NEWTESTFUNC)();// 定义了这样一个创建方法的宏#define TESTLAYER_CREATE_FUNC(className) \static CCLayer* create##className() \{ return new className(); }// 定义了创建宏#define CF(className) create##className#endif

这里稍微有点不是很容易理解的就是这里的两个宏定义吧,这些大致会是在一些派生类中方便调用的。接下来看下testBasic.cpp好了。



#include "testBasic.h"#include "controller.h"TestScene::TestScene(bool bPortrait){    // 直接调用CCScene基类的init方法    CCScene::init();}void TestScene::onEnter(){// 先调用基类的onEnter方法    CCScene::onEnter();    //add the menu item for back to main menu//#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)//    CCLabelBMFont* label = CCLabelBMFont::create("MainMenu",  "fonts/arial16.fnt");//#else// 创建返回主页面的label文字    CCLabelTTF* label = CCLabelTTF::create("MainMenu", "Arial", 20);//#endif// 以“MainMenu”文字作为MenuItem,它的callback参数就是MaiMenuCallback    CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(TestScene::MainMenuCallback));// 创建MainMenu这个Item的Menu    CCMenu* pMenu =CCMenu::create(pMenuItem, NULL);// MenuItem放到左下角    pMenu->setPosition( CCPointZero );// MenuItem放到右中间的位置    pMenuItem->setPosition( ccp( VisibleRect::right().x - 50, VisibleRect::bottom().y + 25) );// 把这个menu加入本scene    addChild(pMenu, 1);}void TestScene::MainMenuCallback(CCObject* pSender){// 创建一个scene    CCScene* pScene = CCScene::create();// scene中创建testController,并加入自动回收    CCLayer* pLayer = new TestController();    pLayer->autorelease();// pLayer加入scene    pScene->addChild(pLayer);// 替换掉当前Scene    CCDirector::sharedDirector()->replaceScene(pScene);}

整个控制代码基本就看完了。看完这些代码,其实已经可以完成一个完整的SceneManager了。如果有看我博客的朋友,可以自己试一下,很简单的。

下一篇开始正式进入各个测试类的内容当中

原创粉丝点击