cocos2d-x 实战 Dots ( 一 ) – 搭建主界面

cocos2d-x 教程, Dots: A Game About Connecting 主界面

抄袭从游戏的第一个界面开始,如左图。

本文的代码已经提交 Github ,ccocos2d-x 的基础版本 fork 自其 2013.6.11 下午的版本。本项目直接做在 HelloCpp 的工程上,目前在 Windows 上开发,但我不会加系统 API ,保证跨平台性,当前分辨率设置为 320*480 ,以后适时再做到 iOS 上。

开始我完全不了解 cocos2d-x ,所以把 HelloCpp 和 TestCpp 工程跟了下,了解了它的运行流程,以及如何设置分辨率、组织场景、创建对象等等。

根据我看的这两个工程, cocos2d 的程序组织大致会是这样。

cocos2d-x 教程, 场景组织

由于 c++ 的 cocos2d-x 是从 objective-c 的 cocos2d 移植来的,所以很多类名、函数名都来自于 Cocoa ,比如 AppDelegate, applicationDidFinishLaunching 等。

CCApplication 是最外层的一个对象,需要是全局唯一的。我们要继承它( AppDelegate )并在 main 函数中手动创建,以后使用 CCApplication::sharedApplication 获取到,也算是一个 Singleton 的实现。cocos2d 中有很多类似的全局唯一对象,比如 CCDirector, CCEGLView 等。有了 App 对象后,调用其 run 函数,程序就会进入消息循环。

在进入消息循环之前,程序会进入到 CCApplication::applicationDidFinishLaunching 函数进行应用程序的初始化,所以在子类 AppDelegate 中,我们重载这个函数,初始化我们自己的程序。在这个函数中,我们需要做的事情首先是为 GLView 设置分辨率,然后组织游戏场景。

CCDirector 负责对场景的管理,同时只能有一个 CCScene 在跑,如果插入一个新的 Scene,原来的 Scene 就会被挂起。Scene 可以看作是游戏的多个流程模块,比如主界面、游戏界面、剧情界面等。TestCpp 工程就是通过 Scene 来组织多个 Demo 程序,点击主界面里的 Menu 来切换。

Scene 下面可以有多个 CCLayer ,Layer 被用来组织多个 CCSprite , Sprite 就是游戏里的那些基本的元素,比如一个图片,一个 Label 。

下面来组织我们的第一个场景,主界面。

我复制了 HelloWorldScene.h/cpp 建了一个新的类 MainMenuScene ,修改它的 init 函数创建我们的主界面场景,包含一个背景图,一个 Logo 和底部的 Menu 。

// on "init" you need to initialize your instance
bool MainMenuScene::init()
{
    //////////////////////////////
    // 1. super init first
    if ( !CCLayer::init() )
    {
        return false ;
    }
   
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();

    // add background
    CCSprite* pSprite = CCSprite::create( "background@2x.png");
                pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    // add the sprite as a child to this layer
    this->addChild(pSprite, 0);

    // add dots' logo
    CCSprite* pLogo = CCSprite::create( "dots_logo@2x.png");
    pLogo->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height + origin.y + pLogo->getContentSize().height));
     this->addChild(pLogo, 0);

    // logo's action
    CCPoint ptLogoFinal = ccp(visibleSize.width/2 + origin.x, visibleSize.height * 3 / 4 + origin.y);
    CCPoint ptLogoMiddle = ccp(visibleSize.width/2 + origin.x, visibleSize.height * 2 / 3 + origin.y);
    CCActionInterval*  action1 = CCMoveTo::create(0.5f, ptLogoMiddle);
    CCActionInterval*  action2 = CCMoveBy::create(0.2f, ccp(0, 50));
    CCActionInterval*  action3 = CCMoveBy::create(0.2f, ccp(0, -25));
    CCActionInterval*  action4 = CCMoveBy::create(0.2f, ccp(0, 12));
    CCActionInterval*  action5 = CCMoveBy::create(0.2f, ccp(0, -7));
     // run logo's action
    pLogo->runAction( CCSequence::create(action1, action2, action3, action4, action5, NULL));

     // dots menu
    m_pItemMenu = CCMenu::create();
    for (int i = 0; i < MENU_COUNT; ++i)
    {
                    
        CCLabelTTF* label = CCLabelTTF::create(g_aMenuNames[i].c_str(), "fonts/Josefin Sans Bold.ttf", 12);
        label->setColor(ccBLACK);
        aaMenuItemLabel* pMenuItem = new aaMenuItemLabel();
        pMenuItem->initWithLabel(label, this, menu_selector(MainMenuScene::menuCallback));
        pMenuItem->autorelease();

        m_pItemMenu->addChild(pMenuItem, i + 10000);
        pMenuItem->setPosition( ccp( 0, (- i * LINE_SPACE) ));
    }

    m_pItemMenu->setPosition(ccp(visibleSize.width/2 + origin.x, origin.y+50));
    this->addChild(m_pItemMenu, 0);

   
    return true ;
}

Action 部分是动画,留待下一篇专门来讲。背景和 Logo 就是一个图片 Sprite ,Menu 本身是一个 Layer,里面由多个菜单项组成。由于 CCMenuItemLabel 提供的点击动画(文字放大)不是我们想要的(Dots 的会变成青绿色),所以我做了一个 aaMenuItemLabel 继承于它,重新实现它的 selected 和 unselected 函数。

场景创建完后,把 AppDelegate::applicationDidFinishLaunching 里调用 HelloWorldScene 的地方改成 MainMenuScene 就能显示出主场景了。因为上面加了 Action ,所以你会看到 Dots 中 Logo 掉下来弹跳的样子。当然不如原版的动画好,我们后面再来想办法调。

初涉 cocos2d-x 我遇到的最大的麻烦其实是分辨率和坐标的问题。要把这个说清楚可是个大工程,我先偷个懒,后面再写。如果你也遇到这样的问题,推荐看看这篇文章《Cocos2d-x 屏幕适配新解》



发表评论?

1 条评论。

  1. cocos2d-x 实战 Dots – 序 | 山那畔别有人家 - pingback on 2013 年 6 月 11 日 在 22:15

发表评论

Trackbacks and Pingbacks: