Cocos2d-x中__Dictionary容器以及執行個體介紹,cocos2d執行個體
__Dictionary類在Cocos2d-x 2.x時代它就是CCDictionary類,它是模仿Objective-C中的NSDictionary類而設計的,通過引用計數管理記憶體。__Dictionary繼承於Ref類,因此它所能容納的是Ref及子類所建立的對象指標。
1、建立__Dictionary對象
建立__Dictionary對象有很多函數,下面是總結常用的函數:
static __Dictionary* create()。建立__ Dictionary。
static __Dictionary* createWithDictionary(__Dictionary* srcDict)。用一個已存在的__Dictionary來建立一個新的__Dictionary。
static __Dictionary* createWithContentsOfFile(const char *pFileName)。從屬性列表檔案建立__Dictionary。
2、添加元素
向__Dictionary對象中添加元素都必須是“鍵-值”對,“鍵”可以是字串(std::string)類型或整數(signed int)類型,而“值”必須是Ref和其子類的對象指標類型。下面是總結常用的函數:
void setObject(Ref* pObject, const std::string& key)。插入一個“鍵-值”對,其中pObject是“值”,key是“鍵”。如果是第一次調用,__Dictionary的“鍵”類型是字串型,之後就不能插入整型“鍵”。如果已存在該“鍵”,則舊“鍵-值”對會被釋放和移除,被新的替代。
void setObject(Ref* pObject, intptr_t key)。插入一個“鍵-值”對,其中pObject是“值”,key是“鍵”, intptr_t類型是signed int類型的別名,為整型。如果是第一次調用,__Dictionary的“鍵”類型是整型,之後就不能插入字串型“鍵”,如果已存在該“鍵”,則舊“鍵-值”對會被釋放和移除,被新的替代。
3、移除元素
下面是總結常用的移除__Dictionary容器中元素的函數:
void removeObjectForKey(const std::string& key)。通過指定鍵移除元素。
void removeObjectForKey(intptr_t key)。通過指定鍵移除元素。
void removeObjectsForKeys(__Array* pKeyArray)。通過一個__Array中鍵集合移除元素。
void removeObjectForElememt(DictElement* pElement)。通過指定元素來移除。
void removeAllObjects()。移除所有的元素。
4、尋找元素
我們還可以通過下面函數對__Dictionary容器中元素尋找:
Ref* objectForKey(const std::string& key)。返回指定字串類型“鍵”的“值”。
Ref* objectForKey(intptr_t key)。返回指定整型“鍵”的“值”。
const __String* valueForKey(const std::string& key)。返回指定字串類型“鍵”的“值”,傳回值是__String指標類型,這裡假定“值”是__String指標型,如果不是或者未找到,則返回空串。
const __String* valueForKey(intptr_t key)。返回指定整型“鍵”的“值”,傳回值是__String指標類型,這裡假定“值”是__String指標,如果不是或者未找到,則返回空串。
5、其它操作函數
此外還有很多操作__Dictionary對象函數,下面是總結常用的函數:
__Array* allKeys()。返回一個包含所有“鍵”的“值”的__Array容器。
unsigned int count()。返回元素個數。
bool writeToFile(const char *fullPath)。把__Dictionary寫到一個屬性列表檔案中,寫入的“值”要求是字串型。
6、遍曆__Dictionary容器
Cocos2d-x提供了兩個遍曆__Dictionary容器的宏:
CCDICT_FOREACH。遍曆__Dictionary容器。
執行個體:__Dictionary容器
下面我們通過一個執行個體介紹__Dictionary字典容器中的相關函數。所示情境,點擊右下角的Go按鈕,在情境中添加100個Ball精靈和100個icon精靈。
__Dictionary字典容器執行個體
為了學習__Dictionary類的使用,我們在程式中分別建立100個Ball精靈和100個icon精靈,並把它們分別添加到不同的__Dictionary容器中。
下面我們看看代碼部分,HelloWorldScene.h代碼如下:
#ifndef __HELLOWORLD_SCENE_H__#define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #define MAX_COUNT 100① class HelloWorld : public cocos2d::Layer{cocos2d::__Dictionary* dict1; ②cocos2d::__Dictionary* dict2; ③ public: ~HelloWorld();④ static cocos2d::Scene* createScene(); virtual bool init(); void menuCloseCallback(cocos2d::Ref* pSender); CREATE_FUNC(HelloWorld);}; #endif // __HELLOWORLD_SCENE_H__
上述代碼第①行代碼#define MAX_COUNT 100定義宏MAX_COUNT,MAX_COUNT定義了一次產生的精靈數。第②和③行代碼聲明__Dictionary*的成員變數dict1和dict2。第④行代碼是聲明解構函式,我們需要在解構函式中釋放成員變數dict1和dict2。
HelloWorldScene.cpp中的init函數代碼如下:
bool HelloWorld::init(){if ( !Layer::init() ){return false;} Size visibleSize = Director::getInstance()->getVisibleSize();Vec2 origin = Director::getInstance()->getVisibleOrigin(); auto goItem = MenuItemImage::create("go-down.png","go-up.png",CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); goItem->setPosition(Vec2(origin.x + visibleSize.width - goItem->getContentSize().width/2 ,origin.y + goItem->getContentSize().height/2)); auto menu = Menu::create(goItem, NULL);menu->setPosition(Vec2::ZERO);this->addChild(menu, 1); this->dict1 = __Dictionary::create();①this->dict1->retain();②this->dict2 = __Dictionary::create();this->dict2->retain(); for(int i = 0;i < MAX_COUNT; ++i){ ③ auto sprite1 = Sprite::create("Ball.png");④this->dict1->setObject(sprite1, i);⑤ auto sprite2 = Sprite::create("icon.png");⑥__String *key = __String::createWithFormat("key%d",i);⑦this->dict2->setObject(sprite2, key->getCString());⑧}return true;}
init是初始化情境的函數,我們在該函數中建立了200個精靈,並把它們分別放到__Dictionary*類型的dict1 和dict2成員變數中。其中第①行代碼是建立__Dictionary*類型的dict1成員變數,使用create函數。第②行代碼this->dict1->retain()非常重要,retain是保持dict1對象在一個遊戲迴圈事件後記憶體不會自動釋放,這涉及到Ref記憶體管理問題,我們將在第19章給大家詳細介紹。如果this->dict1->retain()語句,dict1對象會被釋放,在其它函數dict1容器物件就會出錯。
第③行代碼是迴圈建立精靈對象。第④行代碼是建立Ball精靈對象,第⑤行代碼this->dict1->setObject(sprite1, i)是使用迴圈變數i作為鍵,把Ball精靈對象添加到dict1容器物件中。第⑥行代碼是建立icon精靈對象。第⑦行代碼是根據迴圈變數i,建立字串,如:key0、key1等形式。第⑧行代碼把icon精靈對象添加到dict2容器物件中。
需要注意的是這些精靈對象還沒有被添加到情境中,因此,情境顯示的時候它們是不出現的。
HelloWorldScene.cpp中的menuCloseCallback函數代碼如下:
void HelloWorld::menuCloseCallback(Ref* pSender){ Size visibleSize = Director::getInstance()->getVisibleSize(); DictElement* pElement; ① log("Dict1 key-value count = %d",this->dict1->count());CCDICT_FOREACH(dict1, pElement) ②{int key = pElement->getIntKey(); ③log("Add Sprite %d", key); Sprite* sprite = (Sprite*)pElement->getObject();④ int x = CCRANDOM_0_1() * visibleSize.width;int y = CCRANDOM_0_1() * visibleSize.height; sprite->setPosition( Vec2(x, y) );this->removeChild(sprite);this->addChild(sprite);} log("Dict2 key-value count = %d",this->dict2->count());CCDICT_FOREACH(dict2, pElement) ⑤{const char *key = pElement->getStrKey(); ⑥log("Add Sprite %s", key); Sprite* sprite = (Sprite*)pElement->getObject(); int x = CCRANDOM_0_1() * visibleSize.width;int y = CCRANDOM_0_1() * visibleSize.height; sprite->setPosition( Vec2(x, y) );this->removeChild(sprite);this->addChild(sprite);} }
該函數是在玩家觸摸Go按鈕之後調用的函數,其中第①行代碼DictElement* pElement是__Dictionary元素(DictElement)指標,它將在迴圈遍曆中使用。DictElement類的主要函數如下:
const char* getStrKey ()。獲得元素的字串鍵。
intptr_t getIntKey ()。獲得元素的整型鍵。
Ref * getObject ()。獲得元素中的值。
第②行代碼CCDICT_FOREACH(dict1, pElement)是使用CCDICT_FOREACH宏對__Dictionary容器進行遍曆的,宏的第一個參數dict1是__Dictionary 對象指標,第二個元素pElement是前面聲明的__Dictionary元素(DictElement)指標。第③行代碼int key = pElement->getIntKey()獲得元素的整型鍵。第④行代碼Sprite* sprite = (Sprite*)pElement->getObject()獲得元素中的值。
第⑤行代碼CCDICT_FOREACH(dict2, pElement) )是遍曆dict2對象。與dict1不同的是dict2使用的鍵是字串類型,通過第⑥行代碼const char *key = pElement->getStrKey()可以獲得鍵。
HelloWorldScene.cpp中的解構函式代碼如下:
HelloWorld::~HelloWorld(){this->dict1->removeAllObjects();CC_SAFE_RELEASE_NULL(this->dict1); this->dict2->removeAllObjects();CC_SAFE_RELEASE_NULL(this->dict2);}
在解構函式中要釋放一些資源,首先要移除容器中的所有元素,然後再通過CC_SAFE_RELEASE_NULL宏將容器物件先釋放。
更多內容請關注國內第一本Cocos2d-x 3.2版本圖書《Cocos2d-x實戰:C++卷》本書交流討論網站:http://www.cocoagame.net
更多精彩視頻課程請關注智捷課堂Cocos課程:http://v.51work6.com
歡迎加入Cocos2d-x技術討論群:257760386歡迎關注智捷iOS課堂公用平台
cocos2d-x的3D情境中滑鼠拾取方法
一樣想知道解答..
[解決]
使用color picking object 的方法
[思路]
在按鈕下面貼一張純色的圖 (不要隱藏它) 把z 設定低一點. 把所需點擊的東西畫到一張畫布上, 然後用glReadPixels 讀取像素點.
// Draw into the RenderTexture
[_rtbeginWithClear:0g:0b:0a:0];
// Render both sprites: first one in RED and second one in GREEN
// [_redvisit];
// [_greenvisit];
// 這裡繪製所有想擷取點擊事件的純色圖片.
glColorMask(1,1,1,1);
// Get color values of intersection area
// 讀取一個像素
ccColor4B*buffer=(ccColor4B*)malloc(sizeof(ccColor4B)*numPixels);
glReadPixels(x,y,w,h,GL_RGBA,GL_UNSIGNED_BYTE,buffer);
[_rtend];
[完整代碼]
github.com/ascetic85/objectPick.git
勁樂團行?
我覺得挺好的!