Cocos2d-x 2.0 TestCpp框架源码分析

长平狐 发布于 2013/03/19 18:39
阅读 319
收藏 0

[Cocos2d-x相关教程来源于红孩儿的游戏编程之路CSDN博客地址:http://blog.csdn.net/honghaier]

红孩儿Cocos2d-X学习园地QQ群:249941957 加群写:Cocos2d-x

本章为我的Cocos2d-x教程一书初稿。望各位看官多提建议!


    Cocos2d-x2.0 TestCpp框架源码分析       


             [本版教程使用的Cocos2d-x版本为cocos2d-2.0-x-2.0.2]


         好的引擎,会提供一系列完整的功能示例,Cocos2d-x之所以能得到很多人的喜爱,其重要的原因是它提供了丰富而易学的示例。在cocos2d-2.0-x-2.0.2中这些示例被放在一个名叫TestCpp的工程中,为了更好的学习Cocos2d-x的功能示例,我们今天来学习一下这个工程的框架结构。


         在VS的解决方案里展开TestCpp工程,其下有43个示例目录,除此之前还有几个文件:

 

AppDelegate.h/cpp : 程序控制类AppDelegate 。

controller.h/cpp:示例场景管理类TestController,用于显示所有示例的菜单。

testBasic.h/cpp:示例场景基类TestScene,用于返回到主界面场景。

testResource.h:文件资源名称字符串定义头文件

tests.h:示例总头文件

main.h/cpp:主函数及头文件

 

          所有的示例都是写在单独的由TestScene派生场景类中,在这些场景中加入一些由CCLayer派生的示例对象来实现相应功能的展示。

 

          与HelloWorld一样,我们需要在main.cpp中创建AppDelegate实例,并设置窗口大小,启动游戏程序。

#include "main.h"
#include "AppDelegate.h"
#include "CCEGLView.h"
USING_NS_CC;
//WIN32程序主函数
int APIENTRY _tWinMain(HINSTANCE hInstance,
                       HINSTANCE hPrevInstance,
                       LPTSTR    lpCmdLine,
                       int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
	//实例化一个Cocos2d-x程序对象
    AppDelegate app;
	//创建OpenGL视窗并设置窗口大小
    CCEGLView* eglView = CCEGLView::sharedOpenGLView();
    eglView->setFrameSize(480, 320);
	//运行程序对象
    return CCApplication::sharedApplication()->run();
}

 

    在AppDelegate.cpp中的boolAppDelegate::applicationDid。FinishLaunching()函数中创建场景并运行场景

bool AppDelegate::applicationDidFinishLaunching()
{
    // 取得当前显示设备指针并设置其OpenGL视窗
    CCDirector *pDirector = CCDirector::sharedDirector();
    pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());
	//取得当前运行硬件平台
    TargetPlatform target = getTargetPlatform();
    //如果是IPAD
    if (target == kTargetIpad)
    {
		//如果能启动高清屏,使用高精度资源,否则使用一般精度资源
        if (pDirector->enableRetinaDisplay(true))
        {
            CCFileUtils::sharedFileUtils()->setResourceDirectory("ipadhd");
        }
        else 
        {
            CCFileUtils::sharedFileUtils()->setResourceDirectory("ipad");
        }
    }
	//如果是Iphone
    else if (target == kTargetIphone)
    {
		//如果能启动高清屏,使用高精度资源
        if (pDirector->enableRetinaDisplay(true))
        {
            CCFileUtils::sharedFileUtils()->setResourceDirectory("hd");
        }
    }

    // 设置FPS信息显示
    pDirector->setDisplayStats(true);

    //设置帧间隔时间
    pDirector->setAnimationInterval(1.0 / 60);
	//在这里创建一个场景
    CCScene * pScene = CCScene::create();
	//实例化一个TestController,它是一个CCLayer。
    CCLayer * pLayer = new TestController();
	//设置由内存管理器来进行自动回收,不必手动DELETE
    pLayer->autorelease();
	//将它放置到场景中
    pScene->addChild(pLayer);
	//运行这个新创建的场景。
    pDirector->runWithScene(pScene);

    return true;
}

 

    下面我们来看一下testBase.h/cpp,这里面有一个所有示例都要用到的场景基类TestScene。

#ifndef _TEST_BASIC_H_
#define _TEST_BASIC_H_
//Cocos2d头文件
#include "cocos2d.h"
//使用Cocos2d命名空间
USING_NS_CC;
using namespace std;

class TestScene : public CCScene
{
public: 
	//构造
    TestScene(bool bPortrait = false);
	//场景被加载时的回调函数
    virtual void onEnter();
	//自定义的虚函数,用于运行场景。
    virtual void runThisTest() = 0;
    //返回主界面的菜单按钮响应回调函数。
    virtual void MainMenuCallback(CCObject* pSender);
};

#endif

cpp文件:


#include "testBasic.h"
#include "controller.h"
//构造函数
TestScene::TestScene(bool bPortrait)
{
    
    CCScene::init();
}
//场景被加载时的回调函数
void TestScene::onEnter()
{
    CCScene::onEnter();

   	  //#if (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
//    CCLabelBMFont* label = CCLabelBMFont::create("MainMenu",  "fonts/arial16.fnt");
//#else
	//创建一个文字标签,显示“MainMenu”字符串
    CCLabelTTF* label = CCLabelTTF::create("MainMenu", "Arial", 20);
//#endif
	//增加一个菜单标签,设定其被按下时的回调函数,用于返回到主界面
    CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(TestScene::MainMenuCallback));
	//将菜单标签加入创建的菜单中,并设置相应位置。
    CCMenu* pMenu =CCMenu::create(pMenuItem, NULL);
    CCSize s = CCDirector::sharedDirector()->getWinSize();
    pMenu->setPosition( CCPointZero );
    pMenuItem->setPosition( CCPointMake( s.width - 50, 25) );
	//将菜单放入场景中。
    addChild(pMenu, 1);
}
//菜单标签被按下时的响应函数
void TestScene::MainMenuCallback(CCObject* pSender)
{
	//新创建一个场景。
    CCScene* pScene = CCScene::create();
	//新创建一个TestController对象
    CCLayer* pLayer = new TestController();
    pLayer->autorelease();
	//将它放入新创建的场景中并运行。
    pScene->addChild(pLayer);
    CCDirector::sharedDirector()->replaceScene(pScene);
}

 

         在TestScene中,提供了一个可以被点击的标签MainMenu,从字面意思就知道点击它可以返回主菜单界面,这个主菜单在哪呢?就是TestController。

#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;
	//主菜单
    CCMenu* m_pItemMenu;
};

#endif
进入Cpp看一下:
#include "controller.h"
#include "testResource.h"
#include "tests.h"
//菜单项的行间距 ,设40点
#define LINE_SPACE          40
//创建一个当前触点位置变量,初始化为左下角位置。
static CCPoint s_tCurPos = CCPointZero;
//创建指定的示例场景
static TestScene* CreateTestScene(int nIdx)
{
	//先清空一下显示设备使用的数据
    CCDirector::sharedDirector()->purgeCachedData();

	//定义TestScene指针用于接收创建的示例场景
    TestScene* pScene = NULL;
	//跟据参数来创建相应的TestScene派生类对象。
    switch (nIdx)
    {
    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://旋转CCLayer
        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://CCLayer功能展示
        pScene = new LayerTestScene(); break;
    case TEST_SCENE://CCScene功能展示
        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_CHIPMUNKACCELTOUCH://ChipMunk物理引擎与多点触屏
#if (CC_TARGET_PLATFORM != CC_PLATFORM_MARMALADE)
        pScene = new ChipmunkAccelTouchTestScene(); break;
#else
#ifdef MARMALADEUSECHIPMUNK
#if    (MARMALADEUSECHIPMUNK == 1)
        pScene = new ChipmunkAccelTouchTestScene(); 
#endif
        break;
#endif
#endif
    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;
    case TEST_BOX2D://Box2D物理引擎展示
        pScene = new Box2DTestScene(); break;
    case TEST_BOX2DBED: //Box2D物理引擎展示[物体的固定与连接]
        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://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://BUG示例
        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://使用Shader的渲染演示
        pScene = new ShaderTestScene();
        break;
    case TEST_MUTITOUCH://多点触屏
        pScene = new MutiTouchTestScene();
        break;
    default:
        break;
    }
	//返回创建的场景
    return pScene;
}
//构造函数
TestController::TestController()
: m_tBeginPos(CCPointZero)
{
    // 加入一个关闭菜单按钮
    CCMenuItemImage *pCloseItem = CCMenuItemImage::create(s_pPathClose, s_pPathClose, this, menu_selector(TestController::closeCallback) );
	//创建一个菜单放置关闭按钮
    CCMenu* pMenu =CCMenu::create(pCloseItem, NULL);
    CCSize s = CCDirector::sharedDirector()->getWinSize();
	//设置这个菜单位置
    pMenu->setPosition( CCPointZero );
    pCloseItem->setPosition(CCPointMake( s.width - 30, s.height - 30));

    //新建一个测试项菜单,将所有代表测试场景的菜单标签项加入菜单
    m_pItemMenu = CCMenu::create();
	//
    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
        CCLabelTTF* label = CCLabelTTF::create(g_aTestNames[i].c_str(), "Arial", 24);
// #endif        
        CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(TestController::menuCallback));
		//将代表测试场景的菜单标签加入菜单中,以i+10000的值做为Z值。
        m_pItemMenu->addChild(pMenuItem, i + 10000);
		//设置代表测试场景的菜单标签在测试项菜单层的位置
        pMenuItem->setPosition( CCPointMake( s.width / 2, (s.height - (i + 1) * LINE_SPACE) ));
    }
	//设置测试项菜单的大小
    m_pItemMenu->setContentSize(CCSizeMake(s.width, (TESTS_COUNT + 1) * (LINE_SPACE)));
	//设置测试项菜单的位置
    m_pItemMenu->setPosition(s_tCurPos);
	//将测试项菜单放入当前CCLayer
    addChild(m_pItemMenu);
	//设置开启触屏事件响应
    setTouchEnabled(true);
	//将关闭按钮项菜单放入当前CCLayer
    addChild(pMenu, 1);

}

TestController::~TestController()
{
}
//点击菜单项的事件响应函数
void TestController::menuCallback(CCObject * pSender)
{
    // 取得菜单项
    CCMenuItem* pMenuItem = (CCMenuItem *)(pSender);
	//取得Z值,减10000算出是第几个菜单项
    int nIdx = pMenuItem->getZOrder() - 10000;

    //创建相应的场景
    TestScene* pScene = CreateTestScene(nIdx);
    if (pScene)
    {
		//运行当前测试场景
        pScene->runThisTest();
		//runThisTest中会对其引用计数加1变为2,这里做一次引用计数减1操作,以保证后面再释放场景时可以正常的释放。
        pScene->release();
    }
}
//点击关闭按钮时的响应处理
void TestController::closeCallback(CCObject * pSender)
{
	//退出程序
    CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}
//触点按下时的响应处理
void TestController::ccTouchesBegan(CCSet *pTouches, CCEvent *pEvent)
{
	//获取第一个触点位置
    CCSetIterator it = pTouches->begin();
    CCTouch* touch = (CCTouch*)(*it);
	//将位置保存到变量m_tBeginPos中。
    m_tBeginPos = touch->getLocation();    
}
//触点
void TestController::ccTouchesMoved(CCSet *pTouches, CCEvent *pEvent)
{
	//获取第一个触点位置
    CCSetIterator it = pTouches->begin();
    CCTouch* touch = (CCTouch*)(*it);
	//取得这个位置与上一帧移动的Y值之差,即在纵方向的偏移。
    CCPoint touchLocation = touch->getLocation();    
    float nMoveY = touchLocation.y - m_tBeginPos.y;
	//计算菜单在纵方向上也移动相应值后的新位置。
    CCPoint curPos  = m_pItemMenu->getPosition();
    CCPoint nextPos = ccp(curPos.x, curPos.y + nMoveY);
	//这里对新位置的有效范围做个限定
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    if (nextPos.y < 0.0f)
    {
        m_pItemMenu->setPosition(CCPointZero);
        return;
    }

    if (nextPos.y > ((TESTS_COUNT + 1)* LINE_SPACE - winSize.height))
    {
        m_pItemMenu->setPosition(ccp(0, ((TESTS_COUNT + 1)* LINE_SPACE - winSize.height)));
        return;
    }
	//更新菜单到新位置
    m_pItemMenu->setPosition(nextPos);
	//记录当前位置为旧位置。
    m_tBeginPos = touchLocation;
    s_tCurPos   = nextPos;
}

 

         总结:示例框架展示了一个菜单,每个菜单项代表了一个示例工程,菜单项的Z值是递增排列的。点击菜单项响应TestController::menuCallback函数,此函数通过减去Z值基数可以取得菜单项的索引,并通过CreateTestScene(nIdx);来创建出相应的示例场景。本示例框架还演示了如何在纵方向上拖动一个菜单。


      


原文链接:http://blog.csdn.net/honghaier/article/details/8130947
加载中
返回顶部
顶部