转【玩转cocos2d-x之二十五】数据结构CCArray
前端之家收集整理的这篇文章主要介绍了
转【玩转cocos2d-x之二十五】数据结构CCArray,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
原创作品,转载请标明:http://www.jb51.cc/article/p-bsovodom-ep.html
CCArray是从cocos2d中移植过来的,类似于Apple的NSMutableArray,但是比NSMutableArray更为的好用。要注意的是虽然CCArray和CCDictionary可以管理cocos2d-x中绝大多数的类,但是仍然无法替代STL库,STL库更为强有力。
1.API
先看一下CCArray可以帮我们做什么。
1.1.创建
-
- staticCCArray*create();
-
- staticCCArray*create(CCObject*pObject,…);
-
- staticCCArray*createWithObject(CCObject*pObject);
-
- staticCCArray*createWithCapacity(unsignedintcapacity);
-
- staticCCArray*createWithArray(CCArray*otherArray);
- voidaddObject(CCObject*object);
-
- voidaddObjectsFromArray(CCArray*otherArray);
-
- voidinsertObject(CCObject*object,unsignedintindex);
- voidremoveLastObject(boolbReleaSEObj=true);
-
- voidremoveObject(CCObject*object,boolbReleaSEObj=true);
-
- voidremoveObjectAtIndex(unsignedintindex,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px">
- voidremoveObjectsInArray(CCArray*otherArray);
-
- voidremoveAllObjects();
-
- voidfastRemoveObject(CCObject*object);
-
- voidfastRemoveObjectAtIndex(unsignedintindex);
1.4.操作元素
- unsignedintcount()const;
-
- unsignedintcapacity()const;
-
- unsignedintindexOfObject(CCObject*object)const;
-
- CCObject*objectAtIndex(unsignedintindex);
-
- CCObject*lastObject();
-
- CCObject*randomObject();
-
- boolcontainsObject(CCObject*object)const;
-
- boolisEqualToArray(CCArray*pOtherArray);
1.5.操作array内容
- voidexchangeObject(CCObject*object1,CCObject*object2);
-
- voidexchangeObjectAtIndex(unsignedintindex1,unsignedintindex2);
-
- voidreplaceObjectAtIndex(unsignedintuIndex,CCObject*pObject,boolbReleaSEObject=true);
-
- voidreverSEObjects();
-
- voidreduceMemoryFootprint();
2.remove和fastremove
从1.3可以看出删除有两种方式,普通删除和快速删除,它们有什么区别呢?
2.1.普通删除
- voidccArrayRemoveObjectAtIndex(ccArray*arr,unsignedintindex,boolbReleaSEObj)
- {
- CCAssert(arr&&arr->num>0&&index<arr->num,"Invalidindex.Outofbounds");
-
- if(bReleaSEObj)
- CC_SAFE_RELEASE(arr->arr[index]);
- }
-
- arr->num--;
-
- unsignedintremaining=arr->num-index;
- if(remaining>0)
-
- memmove((void*)&arr->arr[index],(void*)&arr->arr[index+1],remaining*sizeof(CCObject*));
- }
- }
- voidccArrayFastRemoveObjectAtIndex(ccArray*arr,unsignedintindex)
-
- CC_SAFE_RELEASE(arr->arr[index]);
-
- unsignedintlast=--arr->num;
-
- arr->arr[index]=arr->arr[last];
- }
2.3.总结
如果有array={0,1,2,3,4,5},如果要删除3,使用普通删除得到的结果{0,5},使用快速删除得到的结果是{0,5,4}。可以看出快速删除的效率比普通删除效率高,就差在移动元素的时间复杂度上。
3.内存分配
3.1.容量和个数
CCArray中容量和个数并不是同一个概念。个数<=容量。从添加元素的源码中可以看到在添加之前会先进行空间分配,所以它是一个动态分配内存的过程。如下
voidccArrayEnsureExtraCapacity(ccArray*arr,unsignedintextra)
- {
- while(arr->max<arr->num+extra)
- ccArrayDoubleCapacity(arr);
- }
所以,每次CCArray在插入数据时检测到空间不足会增加一倍空间,再进行检测,直到空间满足分配为止。
3.2.判等
判断2个CCArray是否相等使用isEqualToArray(),判断相等的条件是CCArray中的每个元素相等即可,与CCArray的容量无关。
4.效率
比起NSMutableArray,CCArray效率能高出10%左右,原因有三:
(1)它使用的是C接口,所以它不有Objective-C消息开销。
(2)它假定你知道你在做什么,所以它不花时间在安全检查上(如边界溢出,空间需求等)。
(3)在比较上使用了指针而不是isEqual。
除了CCArray,我们还看到了ccCArray,CCArray基本上都是调用了ccCArray的函数,为什么要分为2种?
仔细看一下CCArray是继承于CCObject,所以CCArray是用于处理cocos2d-x对象的,内存管理上也有cocos2d-x的autorelease等诸多特性。而ccCArray可以直接操作标准的C数据结构和类型。
5.CCARRAY_FOREACH和CCARRAY_FOREACH_REVERSE
宏定义,用于正向遍历和反向遍历CCArray元素
@H_667_1301@#defineCCARRAY_FOREACH(__array__,__object__)\
- if((__array__)&&(__array__)->data->num>0)\
- for(CCObject**__arr__=(__array__)->data->arr,**__end__=(__array__)->data->arr+(__array__)->data->num-1;\
- __arr__<=__end__&&(((__object__)=*__arr__)!=NULL);\
- __arr__++)
-
- @H_667_1301@#defineCCARRAY_FOREACH_REVERSE(__array__,108); list-style:decimal-leading-zero outside; color:inherit; line-height:18px"> for(CCObject**__arr__=(__array__)->data->arr+(__array__)->data->num-1,**__end__=(__array__)->data->arr;\
- __arr__>=__end__&&(((__object__)=*__arr__)!=NULL);\
- __arr__--)
6.示例
CCArray的使用示例在http://www.jb51.cc/article/p-wfbmoohn-ep.html此文中有比较典型的应用,这里就不再详述。
7.注意
一般来说,CCArray不会被add到其他类,所以它的引用计数是1,而且被设置为自动释放。所以创建CCArray对象时要记得调用retain,而且在析构的时候也要调用release来释放内存。真心想吐槽。。。
============
http://blog.csdn.net/kenkao/article/details/10375683
1.声明初始化变量
|
cocos2d
::
CCArray
*
pArray
;
pArray
=
CCArray
::
createWithCapacity
(
100
)
;
pArray
->
retain
(
)
;
//如果保留成员变量的话,因为标记了autorelease
|
2.添加元素到数组
|
CCSprite
*
pRet
=
CCSprite
::
create
(
"test.png"
)
;
pArray
->
addObject
(
pRet
)
;
//将pRet添加到数组0位置,此处会调用一次pRet的retain
|
3.删除元素
|
pArray
->
removeObject
(
pRet
)
;
//第二参数为是否调用release,默认为true
pArray
->
removeObjectAtIndex
(
0
)
;
//删除o位置上的元素
|
4.遍历
1).使用ccarray中的宏进行遍历
1
2
3
4
5
6
7
8
9
10
11
12
13
|
CCObject
*
pObj
;
//正向
CCARRAY_FOREACH
(
s_pBulletArray
,
pObj
)
{
CMapNode
*
pNode
=
(
CMapNode
*
)
pObj
;
//...
}
//逆向
CCARRAY_FOREACH_REVERSE
(
s_pBulletArray
,
pObj
)
{
CMapNode
*
pNode
=
(
CMapNode
*
)
pObj
;
//...
}
|
2).for循环遍历
|
for
(
unsigned
int
i
=
0
;
i
<
s_pBulletArray
->
count
(
)
;
++
i
)
{
CCNode
*
pObj
=
(
CCNode
*
)
s_pBulletArray
->
objectAtIndex
(
i
)
;
}
|
二.注意事项
1.创建一个CCArray后如果不是立刻使用的话一定要调用retain,增加引用计数,不然会被自动释放!
2.删除CCArray中的元素时最好默认内部调用一次release,不然可能会内存泄露!
3.遍历时删除元素
|
for
(
int
i
=
arr
->
count
(
)
-
1
;
i
>=
0
;
--
i
)
{
CMonster
*
pObj
=
(
CMonster
*
)
arr
->
objectAtIndex
(
i
)
;
bool
isCollide
=
false
;
isCollide
=
rect
.
intersectsRect
(
pObj
->
getCollideRect
(
)
)
;
if
(
isCollide
)
{
arr
->
removeObject
(
pObj
)
;
}
}
|
三.什么时候会用到CCArray?
1.每一个CCNode的children本质就是一个CCArray,这样我们就可以通过getChildren()获得array,进行操作!
2.对于CCSequence如果只有到运行时才能知道有个少个动作时,我们就可以声明一个CCArray然后将动作addObject(),最后通过一个array来创建CCSequence,例如下面这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
|
//所有的路径节点
CCArray
*
array
=
CCArray
::
createWithCapacity
(
20
)
;
float
dt
=
1
/
(
m_pProperty
->
fMoveSpeed
)
;
CCPoint
point
(
-
1
,
-
1
)
;
for
(
UINT
i
=
0
;
i
<
CGlobal
::
getGameMap
(
)
->
m_PathNode
.
size
(
)
-
1
;
++
i
)
{
array
->
addObject
(
CCMoveTo
::
create
(
dt
,
point
)
)
;
}
//移动完毕的回调
array
->
addObject
(
CCCallFunc
::
create
(
this
,
callfunc_selector
(
CMonster
::
onArrive
)
)
)
;
CCSequence
*
pAct
=
CCSequence
::
create
(
array
)
;
|
3.对于一个CCSprite,我们肯定需要把它addChild到parent上,这样他才能显示出来,这样的话parent上就会有好多child,但是我们要遍历只是其中的一部分(例:场景的地图上有好多种花,我们都会把它们添加到同一个parent上,这时候策划说其中的一种花会被怪物踩死?纳尼….,这个时候我们就需要唉将能被踩死的花加入到parent上时同时加入到一个CCArray中去….),这样我们用的时候遍历这个数组就可以了,而不是遍历这个children!
4.多谢@子龙山人 大大的添加,CCArray还可以内存预分配,比如预先生成一堆子弹,然后加到CCArray中,再从这个CCArray中去重用子弹。这样可以提高游戏效率。消失的子弹只需要设置为Invisible就可以了。这个在做射击类游戏中会大量使用的!
5.还有其他用法?发评论告诉我!