__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代码如下:

  1. #ifndef __HELLOWORLD_SCENE_H__
  2. #define __HELLOWORLD_SCENE_H__
  3. #include "cocos2d.h"
  4. #define MAX_COUNT 100   ①
  5. class HelloWorld : public cocos2d::Layer
  6. {
  7. cocos2d::__Dictionary* dict1;   ②
  8. cocos2d::__Dictionary* dict2;   ③
  9. public:
  10. ~HelloWorld();  ④
  11. static cocos2d::Scene* createScene();
  12. virtual bool init();
  13. void menuCloseCallback(cocos2d::Ref* pSender);
  14. CREATE_FUNC(HelloWorld);
  15. };
  16. #endif // __HELLOWORLD_SCENE_H__

上述代码第①行代码#define MAX_COUNT 100定义宏MAX_COUNT,MAX_COUNT定义了一次生成的精灵数。第②和③行代码声明__Dictionary*的成员变量dict1和dict2。第④行代码是声明析构函数,我们需要在析构函数中释放成员变量dict1和dict2。

HelloWorldScene.cpp中的init函数代码如下:

  1. bool HelloWorld::init()
  2. {
  3. if ( !Layer::init() )
  4. {
  5. return false;
  6. }
  7. Size visibleSize = Director::getInstance()->getVisibleSize();
  8. Vec2 origin = Director::getInstance()->getVisibleOrigin();
  9. auto goItem = MenuItemImage::create(
  10. "go-down.png",
  11. "go-up.png",
  12. CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
  13. goItem->setPosition(Vec2(origin.x + visibleSize.width - goItem->getContentSize().width/2 ,
  14. origin.y + goItem->getContentSize().height/2));
  15. auto menu = Menu::create(goItem, NULL);
  16. menu->setPosition(Vec2::ZERO);
  17. this->addChild(menu, 1);
  18. this->dict1  = __Dictionary::create();   ①
  19. this->dict1->retain();    ②
  20. this->dict2  = __Dictionary::create();
  21. this->dict2->retain();
  22. for(int i = 0;i < MAX_COUNT; ++i){   ③
  23. auto sprite1 = Sprite::create("Ball.png");  ④
  24. this->dict1->setObject(sprite1, i);   ⑤
  25. auto sprite2 = Sprite::create("icon.png");  ⑥
  26. __String *key = __String::createWithFormat("key%d",i);  ⑦
  27. this->dict2->setObject(sprite2, key->getCString());    ⑧
  28. }
  29. return true;
  30. }

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函数代码如下:

  1. void HelloWorld::menuCloseCallback(Ref* pSender)
  2. {
  3. Size visibleSize = Director::getInstance()->getVisibleSize();
  4. DictElement* pElement;  ①
  5. log("Dict1 key-value count = %d",this->dict1->count());
  6. CCDICT_FOREACH(dict1, pElement)     ②
  7. {
  8. int key = pElement->getIntKey();     ③
  9. log("Add Sprite %d", key);
  10. Sprite* sprite = (Sprite*)pElement->getObject(); ④
  11. int x = CCRANDOM_0_1() * visibleSize.width;
  12. int y = CCRANDOM_0_1() * visibleSize.height;
  13. sprite->setPosition( Vec2(x, y) );
  14. this->removeChild(sprite);
  15. this->addChild(sprite);
  16. }
  17. log("Dict2 key-value count = %d",this->dict2->count());
  18. CCDICT_FOREACH(dict2, pElement)     ⑤
  19. {
  20. const char *key = pElement->getStrKey();     ⑥
  21. log("Add Sprite %s", key);
  22. Sprite* sprite = (Sprite*)pElement->getObject();
  23. int x = CCRANDOM_0_1() * visibleSize.width;
  24. int y = CCRANDOM_0_1() * visibleSize.height;
  25. sprite->setPosition( Vec2(x, y) );
  26. this->removeChild(sprite);
  27. this->addChild(sprite);
  28. }
  29. }

该函数是在玩家触摸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中的析构函数代码如下:

  1. HelloWorld::~HelloWorld()
  2. {
  3. this->dict1->removeAllObjects();
  4. CC_SAFE_RELEASE_NULL(this->dict1);
  5. this->dict2->removeAllObjects();
  6. CC_SAFE_RELEASE_NULL(this->dict2);
  7. }

在析构函数中要释放一些资源,首先要移除容器中的所有元素,然后再通过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中__Dictionary容器以及实例介绍的更多相关文章

  1. Cocos2d-x中__Array容器以及实例介绍

    __Array类在Cocos2d-x 2.x时代它就是CCArray类.它是模仿Objective-C中的NSArray类而设计的,通过引用计数管理内存.__Array继承于Ref类,因此它所能容纳的 ...

  2. Cocos2d-x中Vector<T>容器以及实例介绍

    Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容纳的是Ref及子类所创建的对象指针,其中的T是模板,表示能够放入到容器中的类型,在Cocos2d-x 3.x中T ...

  3. Cocos2d-x中Vector&lt;T&gt;容器以及实例介绍

    Vector<T> 是Cocos2d-x 3.x推出的列表容器,因此它所能容纳的是Ref及子类所创建的对象指针,其中的T是模板,表示能够放入到容器中的类型,在Cocos2d-x 3.x中T ...

  4. 实例介绍Cocos2d-x中Box2D物理引擎:HelloBox2D

    我们通过一个实例介绍一下,在Cocos2d-x 3.x中使用Box2D物理引擎的开发过程,熟悉这些API的使用.这个实例运行后的场景如图所示,当场景启动后,玩家可以触摸点击屏幕,每次触摸时候,就会在触 ...

  5. C++中vector容器的常用操作方法实例总结

    C++中vector容器的常用操作方法实例总结 参考 1. C++中vector容器的常用操作方法实例总结: 完

  6. 5种样式实现div容器中三图摆放实例对比说明

    代码地址如下:http://www.demodashi.com/demo/11593.html 效果演示: demo点查看效果 需求说明: 如下图所示为设计图,希望在图片上传无规则无规律的情况下实现设 ...

  7. spring中IOC容器注册和获取bean的实例

    spring中常用的功能主要的是ioc和aop,此处主要说明下,实例注册和使用的方法,此为学习后的笔记记录总结 1.使用xml文件配置 在idea中创建maven工程,然后创建实例Person,然后在 ...

  8. oracle中print_table存储过程实例介绍

    oracle中pro_print_table存储过程实例介绍 存储过程(Stored Procedure),就是一组用于完成特定数据库功能的SQL语句集,该SQL语句集经过编译后存储在数据库系统中.这 ...

  9. STL中的容器介绍

    STL中的容器主要包括序列容器.关联容器.无序关联容器等. 一]序列容器 (1) vector vector 是数组的一种类表示,提供自动管理内存的功能,除非其他类型容器有更好满足程序的要求,否则,我 ...

随机推荐

  1. Linux - CentOS 6.3 (x86_64)安装过程详细图解

    I:下载CentOS 6.3 楼主已经从CentOS官方公布下载列表当中整理出了2个在国内的下载地址,这样就不需要为访问墙外的龟速网络而费心了. 32位:下载地址1,下载地址2 64位:下载地址1,下 ...

  2. Codeforces Round #327 (Div. 2) E. Three States BFS

    E. Three States Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/591/probl ...

  3. js中substr与substring的差别

    Js的substring和C#的Substring的作用都是从一个字符串中截取出一个子字符串,但它们的用法却有非常大的不同,下边我们来比較看看:  Js的substring  语法:  程序代码  S ...

  4. 最简单的视频编码器:编译(libx264,libx265,libvpx)

    ===================================================== 最简单的视频编码器系列文章列表: 最简单的视频编码器:编译 最简单的视频编码器:基于libx ...

  5. android UI进阶之实现listview的分页加载

    上篇博文和大家分享了下拉刷新,这是一个用户体验非常好的操作方式.新浪微薄就是使用这种方式的典型. 还有个问题,当用户从网络上读取微薄的时候,如果一 下子全部加载用户未读的微薄这将耗费比较长的时间,造成 ...

  6. 关于flash player debugger 无法弹窗报错的解决办法

    第一个是IE的插件, Download the Windows Flash Player 10.2 ActiveX control content debugger (for IE) (EXE, 2. ...

  7. Particle designer 粒子工具中属性对应功能的简单介绍

    粒子配置 Max Particles 粒子的数量  一般而言,我们的目标是用最少的粒子创造出所需的效果.单个粒子的大小对游戏运行效率也有很大的影响——单个粒子越小,性能越高. Lifespan 生命周 ...

  8. shell脚本分为三类:登录脚本、交互式脚本、非交互式脚本

    shell脚本分为三类:登录脚本.交互式脚本.非交互式脚本 一. 登录脚本类似于windows下的计算机设置中的登录脚本和账户设置下的登录脚本的合集(我是这么理解的哈). 其配置文件的关键词为pref ...

  9. printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf - 输出格式转换函数

    参考:http://blog.sina.com.cn/s/blog_674b5aae0100prv3.html 总览 (SYNOPSIS) #include <stdio.h> int p ...

  10. 探索 Linux 内存模型--转

    引用:http://www.ibm.com/developerworks/cn/linux/l-memmod/index.html 理解 Linux 使用的内存模型是从更大程度上掌握 Linux 设计 ...