轉自:http://blog.sina.com.cn/s/blog_4522f0b80102vgdw.html
Cocos2dx3.0,會遇到對象的值與對象的存儲問題,即與ValueVectorVector(Map)。
在Cocos2dx 2.0版本,我們要存儲一個int型數據,應該放到哪裏?沒錯,放到CCArray中,如下:
int i=10;
CCArray _array=CCArray::create();//創建一個CCArray數組
_array->addObject(CCInteger::create(i));//將int型數據放入數組中
如果要存儲一個CCObject對象,又是用什麼存呢?是的,又是CCArray:
CCSprite*sp=CCSprite::create("star.png");//創建一個精靈
...
_array->addObject(sp);//將精靈放入到數組中
在Cocos2dx3.0版本,
我們都知道該版本的CCArray已經被甩了(實際上用__Array也還是可以替用一下),那麼要存儲一個Ref(3.0後CCObject改名爲Ref)對象應該如何操作?機智的我馬上想到了CCArray的替代者:Vector,示例代碼如下:
autosp=Sprite::create("star.png");
...
Vector sp_vec;//創建一個Sprite*類型的容器
sp_vec.pushBack(sp);//將精靈放入到容器中
如果對Vector的操作不是很熟悉,可以看之前的博客:http://blog.csdn.net/star530/article/details/19170853
接下來問題來了,如果要存儲一個數據類型,如int型數據,那麼用Vector
可以實現嗎?答案是否定的,在Vector的官方說明文檔裏有這麼一句話:
cocos2d::Vector 中的T必須是一個指向cocos2d::Ref
子類對象的指針。不能是其他數據類型或者原生類型,因爲我們已經將 Cocos2d-x
的內存管理模型集成到cocos2d::Vector 中。
有句話叫什麼來着:上帝爲你關上了一扇門,一定會爲你打開一扇窗...此處不留爺,自有留爺處...
既然Vector容不下數據類型的元素,那麼肯定有可以替代它的東西存在。沒錯,ValueVector登上了歷史舞臺。
第一次看到ValueVector時我就愣住了,這貨又是什麼碗糕?幾秒後我反應過來,這貨肯定是Value與Vector的私生子,我實在太特麼機智了,這麼抽象的命名都能讓我快速想到答案,心中不禁暗自得意。先到CCValue.h
頭文件中看下它的聲明:
-
typedefstd::vectorValueVector;
可以看出,ValueVector
實際上就是一個存放Value類型元素的std::vector容器,這裏和我之前的猜測有些出入。下面將幾個int型數據存儲到ValueVector中。
int a=10;
int b=20;
ValueVector val_vec;
val_vec.push_back(Value(a));
val_vec.push_back(Value(b));
上面代碼就是創建兩個int型的變量,然後放入ValueVector中,其中要注意的是:因爲ValueVector中只能存放Value類型的元素,所以int型的a、b變量必須轉換成Value類型後才能放入到ValueVector中。
關於Value
的一些用法,可以看之前的博客:http://blog.csdn.net/star530/article/details/21651751
說到ValueVector
,那就順便提下它的一些簡單操作:
1、讀取Plist
(xml)配置文件。如下:
-
ValueVectorstar_val=FileUtils::getInstance()->getValueVectorFromFile("star.plist");
不過用ValueVector讀取的plist文件只侷限於是該plist的格式的以array數組類型開頭的,例如下面這種:
name
star
isCool
yes
如果是以dict
字典類型開頭的文件,則要換用ValueMap,這是下一篇的內容,先跳過。
2、往ValueVector
中插入一個元素。上面有提到過,ValueVector實際上就是一個存放Value類型的vector順序容器,所以它的插入元素方式可以直接使用vector順序容器的操作。示例如下:
int
a=10;
std::stringb="starissocool";
ValueVector star_val;
star_val.push_back(Value(a));
star_val.push_back(Value(b));//
放入ValueVector
前都要先將類型轉成Value類型
-
提取ValueVector中的元素。這裏我接上面的例子來用:
int
a1=star_val.at(0).asInt();
std::stringb1=star_val.at(1).asString();
CCLOG("a1=%d,b1=%s",a1,b1);
上面的代碼比較容易理解,就是提取star_val
中放在0和1位置上的元素,然後分別轉成int型和string型。asInt()與asString()是Value用來實現類型轉換的函數。4、刪除ValueVector中的元素。容器中比較常用的刪除元素方式有三種:1)刪除容器中最後一個元素,
star_val.pop_back();//
直接刪除容器中最後一個元素
2)用erase刪除容器中的某一個元素?爲什麼我要在前面加個問號呢?假設我要刪除star_val中的 元素a,代碼如下:
autostar_iter=std::find(star_val.begin(),star_val.end(),a);
star_val.erase(star_iter);
上面兩行代碼信息量還是比較大的,首先我們要知道erase 刪除的是由一個迭代器指向的單個元素,而不是直接這樣: star_val.erase(a);
這種操作是錯誤的。因爲刪除一個元素要用到迭代器,用到迭代器,就要用到find
函數,用到find函數,就要用到==運算符。但是cocos2d-x 3.0沒用重載這個==運算符,所以這個方法行不通。
3)既然無法刪除指定的元素,那我破罐子破摔,將全部元素都刪除總可以吧?答案是肯定的:
star_val.clear();
好了,ValueVector
的用法說到這裏,最後做下總結和補充:
1、Vector
只能用來存放Ref類型的元素,不能存放數據類型的元素;
2、ValueVector
只能用來存放Value類型的元素,因爲Value說到底就是數據類型,所以也可以認爲ValueVector只能用來存放數據類型,千萬別將Ref類型的元素放進入,否則會很刺激。3、ValueVector中可以放ValueVector,前提是將ValueVector轉成Value類型;而Vector中不能存放Vector類型的元素,如下:
ValueVector
star_val;
ValueVector
star_val2;
star_val.push_back(Value(star_val2));//正確
Vector> star_vec;//錯誤!
OK,就寫到這裏吧。