Cocos2d-x开发知识点总结

2015年03月22日 16:25 0 点赞 0 评论 更新于 2025-11-21 18:10

以下是我总结的Cocos2d-x开发中的一些重要知识点,与大家分享。

1. CCMoveTo动作位置异常问题

当CCMoveTo动作运行多次时,目标位置可能会出现诡异变化,例如变成目标位置的几倍。解决办法是在每次执行CCMoveTo之前,确保停止之前的动作。

2. 父类函数调用问题

2.1 onEnter()函数

onEnter()函数中,必须调用父类的onEnter()函数,否则动画等效果可能会失效。

2.2 init()函数

init()函数中,要对父类进行初始化。

3. addChild()函数的zOrder参数

addChild(CCNode* child, int zOrder)函数中的zOrder参数用于控制显示顺序,zOrder的值越大,显示的位置越靠前。

4. 常用命名空间宏

Cocos2d-x提供了两个常用的命名空间宏:

#define USING_NS_CC using namespace cocos2d
#define USING_NS_CC_EXT using namespace cocos2d::extension

5. 日志输出函数

Cocos2d-x提供的日志输出函数为CCLOG

6. CC_BREAK_IF宏

CC_BREAK_IF宏的定义如下:

#define CC_BREAK_IF(cond) if(cond) break

7. do…while(0)或do…while(false)语句的特殊作用

7.1 提高代码健壮性

在代码执行过程中,可通过CC_BREAK_IF提前退出函数,不执行循环体中后面的部分代码,转而直接执行循环体外后面的代码。当然,使用goto语句也能实现这一目的。示例代码如下:

some code…
do{
CC_BREAK_IF( 如果出错,跳出while循环);
//…另一些语句,如果跳出循环后,这些语句将不会执行,从而执行循环体外后面的代码
} while(0);
some code…

7.2 用于宏定义

宏定义采用#define MARCRO(para) do{macro content}while(0)的格式,原因如下:

  • 避免空的宏定义产生warning:例如#define fun() do{}while(0);
  • 存在独立的block:可用来进行变量定义,实现复杂逻辑。
  • 保证宏作为一个整体实现:如果宏出现在判断语句之后,用do{}while(0)包起来可以保证宏作为一个整体来执行。例如:
    #define fun()  \
    fun1(); \
    fun2();
    if( cond == true)
    fun();
    

    在上述情况中使用该宏,会导致fun1()fun2()不会被同时执行,不符合预期目的。

  • 避免语法错误:使用单独的{}包括宏也能实现预期目的,但使用do{}while(0)语句包起来,能成为一个独立的语法单元,避免与上下文混淆。而且绝大多数编译器都能识别do{}while(0)这种无用的循环并进行优化,不会导致程序性能降低。当然,养成在每个判断语句后加上{}的习惯也能解决该问题,但在设计library时,不能指望使用者有这种代码规范习惯,因此要提高程序的健壮性,避免编译出错。

8. C++中单例的实现

以下是一个C++单例的实现示例:

class DataManager
{
private:
DataManager(); //构造函数定义为私有,防止外部调用
~DataManager();
public:
static DataManager* instance();
static void destroyInstance();
};

DataManager::DataManager()
{
}

DataManager::~DataManager()
{
}

static DataManager* gDataManager = NULL;

DataManager* DataManager::instance() {
if(!gDataManager) {
gDataManager = new DataManager();
}
return gDataManager;
}

void DataManager::destroyInstance()
{
if(gDataManager) {
delete gDataManager;
gDataManager = NULL;
}
}

9. Cocos2d-x的内存管理机制

Cocos2d-x的内存管理机制基本跟Objective-C语言一样,采用引用计数的内存管理机制。Cocos2d-x一般采用autorelease()即自动释放的对象,Cocos2d-x将会在每一帧结束后释放一次内存池,并在下一帧开始前创建一个新的回收池,回收池维护着一个自动释放操作的对象列表。如果一帧内生成了大量autorelease对象,会导致性能下降。因此,在生成autorelease对象密集的区域(通常是循环中)的前后,最好手动创建并释放一个回收池;如果循环数过大,可以将每次循环都创建并释放一次回收池。

9.1 示例代码

// 情况一
CCArray* strArray = CCArray::createWithCapacity(0);
CCPoolManager::sharedPoolManager()->push(); // 压入一个自动回收池到回收池栈的顶端,autorelease对象仅会添加到顶端的池中
for(int i = 0; i < 1000; i ++) {
CCString* str = CCString::createWithFormat("%d",i);
strArray->addObject(str);
}
CCPoolManager::sharedPoolManager()->pop();  // 顶层的回收池释放,内部所有对象被释放一次,此后出现的autorelease对象则添加到下一个池中

// 情况二
CCArray* strArray = CCArray::createWithCapacity(0);
for(int i = 0; i < 100000000; i ++) {
CCPoolManager::sharedPoolManager()->push();
CCString* str = CCString::createWithFormat("%d",i);
strArray->addObject(str);
CCPoolManager::sharedPoolManager()->pop();
}

一般函数的返回值都用autorelease对象。

10. set方法赋值的内存管理

跟Objective-C的属性对象赋值一样,Cocos2d-x的set方法赋值也要注意内存的管理。示例代码如下:

void AClass::setObject(CCObject* pObj)
{
if(this->object != pObj) {
this->object->release();
pObj->retain();
this->object = pObj;
}
}

11. 内存管理的宏

Cocos2d-x提供了一些内存管理的宏:

  • CC_SAFE_DELETE(p):delete一个C++对象p,如果pNULL则不操作。
  • CC_SAFE_DELETE_ARRAY(p):delete[]一个C++数组p
  • CC_SAFE_FREE(p)
  • CC_SAFE_RELEASE(p)
  • CC_SAFE_RELEASE_NULL(p)
  • CC_SAFE_RETAIN(p)

12. 容器类

Cocos2d-x提供了一套类似Objective-C语言的容器类,如CCArrayCCDictionary,用法基本跟Objective-C的NSMutableArrayNSMutableDictionary一样。还提供了CCARRAY_FOREACH(__array__, __object__)函数方便遍历CCArray

13. 游戏组件

13.1 导演、场景、层、精灵、纹理

导演是控制游戏流程的主要组件,游戏流程控制通过在场景间的切换实现。通常,场景包含层,层包含精灵,场景与层是其他游戏元素的容器。层处理触摸事件、加速度计事件、键盘输入事件,而精灵是展示给玩家的图形,纹理是图片。

13.2 节点和渲染树

一切可以显示的游戏元素都是渲染树的节点。

13.3 动作

动作作用于游戏元素,规定了游戏元素运动的方式。帧动画是作用于精灵的一种特殊动作。

14. 坐标系

Cocos2d-x中存在两种坐标系:

  • 绘图坐标系:与OpenGL采用的坐标系相同,以左下角为原点,向右为x轴正向,向上为y轴正向。
  • 纹理坐标系:以左上角为坐标原点,向右为x轴正向,向下为y轴正向,只有从纹理中截取部分矩形时才使用这个坐标系。

15. 锚点

锚点AnchorPoint用于设置一个描点,取值为0到1之间的实数,表示锚点相对于节点长宽的位置。锚点(0,0)表示锚点在节点左下角,(1,1)表示锚点在节点右上角。

16. 定时器事件

  • CCNodeupdate()方法:每帧都会调用。
  • CCNodeschedule()方法。

17. 节点生命周期方法

  • onEnter():当此节点所在场景即将呈现时,会调用此方法。
  • onEnterTransitionDidFinish():当此节点所在场景的入场动作结束后,会调用此方法。如果所在场景没有入场动作,则此方法会紧接着onEnter()后被调用。
  • onExit():当此节点所在场景即将退出时调用。
  • onExitTransitionDidStart():当此节点所在的出场动作结束后会调用此方法。如果所在场景没有出场动作,则此方法会紧接着onExit()后被调用。

18. 特殊的CCLayer

  • CCLayerColor:带背景色的层。
  • CCLayerGradient:能设置两种渐变色的层。
  • CCMenu:游戏菜单,分为菜单项和菜单本身,CCMenuItem是一个菜单项,相当于一个按钮。

作者信息

feifeila

feifeila

共发布了 3994 篇文章