昨天搭建好了cocos2d-x的开发环境,今天开始正式学习。
有必先了解一些基本概念(好像拍电影啊):
导演(CCDirector):顾名思义,就是一个游戏的总指挥,负责把控全场,所有场景切换工作都由导演来执行。
场景(CCScene):场景是视觉元素的容器,我们把层,精灵,菜单都放在这个容器里。
层(CCLayer):层的概念想必大家已经接触过很多了,比如横版过关游戏中,就有好多层,人物移动,后面的背景也跟着移动,但是前面的任务栏,图标栏,技能栏都没有移动,就是因为他们在不同的层上
精灵(CCSprite):精灵就是演员啦,你的角色,你控制的飞机坦克小伙伴都是通过精灵的形式展示出来的,恩,NPC也是精灵。精灵就是一连串的动画构成的一个角色。
动作(Action):动作是通过改变图像的属性来使图像呈现出动态变化,比如缩放,旋转,位移等,精灵通过一系列的动作让你觉得它是活得。
通常导演负责各个场景的切换,一个场景里可以有多个层,每个层里可以有多个精灵,精灵又可以有很多动作,他们都是一对多的关系,如下图:
下面我们先来创建一个导演,cocos2d-x已经为我们写好了一个导演的单例方法,导演是全局唯一的。
我们打开 AppDelegate.cpp,找到里面的applicationDidFinishLaunching方法
bool AppDelegate::applicationDidFinishLaunching() { // initialize director CCDirector* pDirector = CCDirector::sharedDirector(); CCEGLView* pEGLView = CCEGLView::sharedOpenGLView(); pDirector->setOpenGLView(pEGLView); // 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); // create a scene. it's an autorelease object CCScene *pScene = HelloWorld::scene(); // run pDirector->runWithScene(pScene); return true; }
我们可以看到CCDirector::sharedDirector()返回一个CCDirector实例的指针,下次用到导演的时候直接调用这个方法就可以了。
接下来说一说创建场景:
我们看到上面的代码块中有这么一句:
CCScene *pScene = HelloWorld::scene();
其中HelloWorld是我们自己生成的类的名字,那这个 scene() 方法是做什么用的呢?
我们打开MyHelloWorld.cpp文件,可以看到如下代码:
CCScene* MyHelloWorld::scene() { CCScene* ret = CCScene::create(); CCLayer* layer = MyHelloWorld::create(); ret->addChild(layer); return ret; }
这个方法的意思是在方法里生成了一个空的CCScene对象(注意在Cocos2d-x中,创建新对象的方法基本上都是Class::create(),记住哦),然后创建了一个自己类的实例,通过addChild(CCLayer Object)添加到刚才创建的CCScene对象ret中,最后把这个对象的指针返回给调用者,为什么要这么写呢,为什么是返回一个CCScene而不是返回一个CCLayer?我自己的理解是,因为CCScene是一个容器,本身没有任何的内容,所以如果是由CCLayer的对象(MyHelloWorld继承自CCLayer)来负责填充这个CCScene并且返回给调用者,对于调用者来说更加的方便,不用每次都要自己建一个空的场景。
下面就说到重要的层(CCLayer)了,创建方法如下:
打开MyHelloWorld.h,我们可以看到MyHelloWorld直接继承自CCLayer,代码如下
class MyHelloWorld : public cocos2d::CCLayer { public: virtual bool init(); static cocos2d::CCScene* scene(); void menuCloseCallback(CCObject* pSender); CREATE_FUNC(MyHelloWorld); };
有没有发现什么问题,没有???好吧,我们看到上面代码中调用了MyHelloWorld::create();这个方法,可是它没有定义呀,这是怎么回事呢?秘密就在
CREATE_FUNC(MyHelloWorld)
中,这其实是一个宏,创建了一个静态的create()方法,返回一个新的MyHelloWorld对象,具体可以参考CREATE_FUNC宏的定义,用到了模板方法哦。
其中
void menuCloseCallback(CCObject* pSender);
是关闭按钮的回调函数,负责当用户单击了关闭按钮之后关闭窗口。
现在就剩下一个最重要的
virtual bool init()
方法了,
我们看看它的实现,打开MyHelloWorld.cpp,可以看到如下代码,我把每行的意思写在注释里了
bool HelloWorld::init() { // 初始化父类 if ( !CCLayer::init() ) { return false; } // 得到当前窗口的大小 CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize(); // 坐标原点 CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin(); // 添加一个叉叉图像的菜单按钮, 当用户单击的时候就退出 CCMenuItemImage *pCloseItem = CCMenuItemImage::create( "CloseNormal.png", "CloseSelected.png", this, menu_selector(HelloWorld::menuCloseCallback)); pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 , origin.y + pCloseItem->getContentSize().height/2)); // 创建菜单对象,并把刚才的菜单按钮加进来 CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); pMenu->setPosition(CCPointZero); this->addChild(pMenu, 1); // 创建一个显示"Hello World"的标签 CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24); pLabel->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height - pLabel->getContentSize().height)); // 把标签添加到当前层中 this->addChild(pLabel, 1); // 创建以HelloWorld.png为样子的精灵 CCSprite* pSprite = CCSprite::create("HelloWorld.png"); pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y)); this->addChild(pSprite, 0); return true; }
创建精灵(CCSprite)的方法很简单,看上面的代码
CCSprite* pSprite = CCSprite::create("HelloWorld.png");
这样就创建了一个精灵,图片HelloWorld.png在Resources文件夹下。
CCSprite有好多功能,可以放大、缩小、拉伸、压缩、旋转、改变颜色等等,我们可以运行code里自带的SpriteTest项目来对CCSprite能干的事情有个大概了解。
至于动作(Action)嘛,自动生成的例子里面,没有带,那我们就来自己添加一个好了,在上面的代码
this->addChild(pSprite, 0)
这一行下面加入如下代码,
CCMoveTo* moveto = CCMoveTo::create(0.9f, ccp(400,150)); pSprite->runAction(moveto);
再运行一遍,看,是不是画面动起来了,一个简单的移动Action就完成了,是不是很简单啊。
好了,今天先到这里吧。
这个很有意思啊貌似 我顶!
大师来一起学吧