作者:慧科集团华东校区-朱家聪老师,转载请注明出处及本链接。
导演,场景,层,精灵,菜单
在Cocos2d-x中,有很多的概念,这些概念很多都来源于动画,动漫和电影等行业,如导演,场景和层等概念,当然也有传统的游戏概念。
导演
场景
层
节点
精灵
菜单
动作
效果
粒子运动
地图
物理引擎
首先要来学习的是最主要的几个概念,导演,场景,层,精灵,菜单。前四个概念之间的关系如下图所示:

导演
导演类 Director(v3.0之前是 CCDirector)是用于管理场景的对象,采用了单例设计模式,在一个游戏程序中只有一个导演对象。由于是单例模式,能够保存当前程序中的很多配置信息,并保证这些信息的一致性。获取当前程序的导演对象的代码如下:
auto director = Director::getInstance();
导演对象的职责如下:
- 访问和改变场景
- 访问Cocos2d-x的配置信息
- 暂停,继续和停止游戏
- 转换坐标
场景
场景类Scene(v3.0之前是CCScene)是构成游戏的界面,场景大致可以分为以下几类:
- 展示类场景:播放视频或简单的在图像上输出文字,如游戏的开始界面,帮助界面,胜利提示界面等。
- 选项类场景:包括主菜单,设置菜单等。
- 游戏场景:游戏的主要内容。
导演类管理着不同场景之间的转换,而场景则是层Layer的承载者。
层
层是Cocos2d-x中的一个重点,我们所有的游戏内容都要放在层上进行实现。类似于PhotoShop中的图层的概念,每一个游戏场景都是有一个个的图层构成的。与场景不同,层通常包含的是直接在屏幕上呈现的内容,并且可以接受用户的输入事件,包括触摸,加速度计和键盘输入等。我们需要在层中加入精灵,文本标签或者其他游戏元素,并设置游戏元素的属性,比如位置,方向和大小;设置游戏元素的动作等。
auto layer = LayerColor::create(Color4B(0, 128, 128, 255));
layer->setContentSize(Size(120, 80));
layer->setPosition(Point(50, 50));
this->addChild(layer, 10);
auto layer1 = LayerColor::create(Color4B(128, 0, 128, 255));
layer1->setContentSize(Size(120, 80));
layer1->setPosition(Point(100, 80));
this->addChild(layer1, 20);
auto layer2 = LayerColor::create(Color4B(128, 128, 0, 255));
layer2->setContentSize(Size(120, 80));
layer2->setPosition(Point(150, 110));
this->addChild(layer2, 30);
/*
LayerColor是Layer的一个派生类,用于创建带有背景颜色的层对象
Color4B(r,g,b,a)用于创建一个颜色数据
*/

position:节点的位置,Vec2(float xx, float yy);
一个节点一般被看作是一个标准的矩形区域。对于一个区域的定位,只有一个position值是远远不够的。所以每一个节点都还有一个锚点的概念。这个锚点是节点内部一个虚拟的点,在定位节点时可以理解为将锚点位置对准父节点坐标系中position点所在的位置。而锚点在当前节点中的相对位置则以相对比例来表示。例如(0,0)点在左下角,(1,1)点在右上角,(0,1)点在左上角,(1,0)点在右下角。
anchorPoint:节点的锚点位置,Vec2(float xx, float yy);
游戏的循环和调度
Cocos2d-x调度器为游戏提供定时事件和定时调用服务。所有Node对象都可以调度和取消调度事件,使用调度器有几个好处:
- 每当Node不再可见或已从场景中移除时,调度器会停止。
- Cocos2d-x暂停时,调度器也会停止。当Cocos2d-x重新开始时,调度器也会自动继续启动。
- Cocos2d-x封装了一个供各种不同平台使用的调度器,使用此调度器你不用关心和跟踪你所设定的定时对象的销毁和停止,以及崩溃的风险。
默认调度器
在节点运行过程中,可以随时开启默认调度器。默认调度器能够自动的调用节点对象的update函数,该方法会在每帧绘制之前都会被调用一次。因为游戏能够被用户做观察到的最短时间间隔为1帧,所以在update函数中就能过执行大多数的游戏运行逻辑。使用scheduleUpdate()
函数可以开启默认调度器,或者使用unscheduleUpdate()
来关闭默认调度器。
class HelloWorld : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
// 定义update函数,用于循环调用
virtual void update(float dt);
};
// 实现update函数
void HelloWorld::update(float dt){
cout<<"update:"<<dt<<endl;
}
//在当前场景的init函数中开启update函数的调用
bool HelloWorld::init()
{
if ( !Scene::init() )
{
return false;
}
//开启update的调用
this->scheduleUpdate();
return true;
}
程序运行结果:

执行上述代码后系统会不停的去调用update函数,这个函数一般都用于执行一些时时刻刻需要做的事。比如说一些射击类游戏中,子弹的碰撞计算与胜负的判定。
自定义调度器
对于一些执行频率不需要这么高的操作,使用默认调度器就不太合适了。这里我们还可以创建一个自定义的调度器。
class HelloWorld : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
//定义自定义的调度函数
virtual void updateCustom(float dt);
};
void HelloWorld::updateCustom(float dt){
cout<<"update:"<<dt<<endl;
}
然后同样也需要开启这个自定义的调度器。使用schedule函数可以开启自定义的调度器,这里可以根据自己的需求来填写参数。
this->schedule(schedule_selector(HelloWorld::updateCustom), 1.0f, kRepeatForever, 0);
//取消某一个调度器的执行
//this->unschedule(schedule_selector(HelloWorld::updateCustom));
//取消所有调度器的执行
//this->unscheduleAllCallbacks();
//schedule函数的定义:
void Node::schedule(SEL_SCHEDULE selector);
void Node::schedule(SEL_SCHEDULE selector, float interval);
void Node::schedule(SEL_SCHEDULE selector, float interval, unsigned int repeat, float delay);
参数:
SEL_SCHEDULE selector:所要调用的函数,使用schedule_selector()宏定义来声明一个函数
interval:调度的时间间隔,单位是秒
repeat:重复调度的次数,kRepeatForever表示一直调用直到手动取消
delay: 延迟调用的时间
单次调度器
顾名思义就是值调用一次的调度器。
class HelloWorld : public cocos2d::Scene
{
public:
static cocos2d::Scene* createScene();
virtual bool init();
// a selector callback
void menuCloseCallback(cocos2d::Ref* pSender);
// implement the "static create()" method manually
CREATE_FUNC(HelloWorld);
// 单次调度函数
void updateOnce(float dt);
};
bool HelloWorld::init()
{
scheduleOnce(schedule_selector(HelloWorld::updateOnce), 0.1f);
return true;
}
void HelloWorld::updateOnce(float dt)
{
log("Once");
}
网友评论