来自:Software MyZone | 时间:2012-11-19 14:21:37
原文链接: http://www.firedragonpzy.com.cn/index.php/archives/2614
- By firedragonpzy
- 19 十一月, 2012
- No Comments
- 13 views
本节所用Cocos2d-x版本:cocos2d-2.0-x-2.0.2
在引擎开发中,通过名称或索引快速找到所对应的节点,资源,物体是最最基础的算法需求。如何更高效的满足引擎灵活的存储与查询需求,是任何一款引擎要考虑的问题,在诸多款开源或商业引擎中,都有过为了解决此类需求而专门设计的模版类或容器,它们通常被称为“词典”或“字典”。
我们在Cocos2d-x中的很多地方也遇到过词典类CCDictionary。它是利用哈希表算法来进行CCObject管理的一个类。学习它可以让我们对于Cocos2d-x的内部管理机制有更清晰的认识。同时也可以学习这种思想,帮助我们在以后的项目开发中设计出更棒的管理器架构。
CCDictionary中的元素是通过哈希表进行存储的,这个哈希表算法是放在uthash.h中的。其封装了大量的宏来进行相应的哈希表处理。
通过HASK_MAK_TABLE宏来创建一个原始的哈希表。默认的存储空间为32。这个数值是由宏HASH_INITIAL_NUM_BUCKETS定义的。每次往里面插入元素时会判断存储空间是否足够,如果不足会扩展为原来的2倍大小的内存空间,并将原来的哈希表数据放入其中。
其中比较重要的一些宏:
HASH_MAKE_TABLE:建立一个哈希表。
HASH_ADD:将元素放入哈希表。
HASH_FIND:查找元素。
HASH_FIND_STR: 通过名称字符串查询哈希表中的相应词汇。
HASH_FIND_INT: 通过索引查询哈希表中的相应词汇。
HASH_DELETE:从哈希表中删除元素。
HASH_EXPAND_BUCKETS: 扩展为原来的2倍大小的内存空间,并将原来的哈希表数据放入其中。
首先来看CCDictionary.h:
#ifndef __CCDICTIONARY_H__ #define __CCDICTIONARY_H__ //需要哈希表的支持 #include "support/data_support/uthash.h" #include "CCObject.h" #include "CCArray.h" #include "CCString.h" //Cocos2d命名空间 NS_CC_BEGIN //声明一下CCDictionary类,因为CCDictElement要用到CCDictionary指针。 class CCDictionary; //词典元素,或者简单理解就是词典中的一个词汇。我们从小查词典都知道,通过词汇名称或索引查找到对应的解释。解释与词汇名称或索引之间是一一对应的关系。与这种关系相同,在这个词汇类中存储一个字符串名称或一个索引以及与其相应的CCObject指针,这个CCObject指针就相当于是我们查出来的解释一样与字符串名称或索引构成了对应关系。 class CC_DLL CCDictElement { //定义字符串名称的长度. #define MAX_KEY_LEN 256 public: //构造函数。 //参1:字符串名称。 //参2:对应的CCObject指针。 CCDictElement(const char* pszKey, CCObject* pObject) { //初始化。 init(); m_pObject = pObject; // const char* pStart = pszKey; //字符串的字节长度 int len = strlen(pszKey); if (len > MAX_KEY_LEN ) { //如果长度大于MAX_KEY_LEN,截取后面MAX_KEY_LEN长度字符串。 char* pEnd = (char*)&pszKey[len-1]; pStart = pEnd - (MAX_KEY_LEN-1); } //字符串COPY strcpy(m_szKey, pStart); } //构造函数 //参1:所在哈希表中的索引 //参2:对应的CCObject指针。 CCDictElement(int iKey, CCObject* pObject) { init(); m_iKey = iKey; m_pObject = pObject; } //取得名称字符串。 inline const char* getStrKey() const { CCAssert(m_szKey[0] != '\0', "Should not call this function for integer dictionary"); return m_szKey; } //取得哈希索引。 inline int getIntKey() const { CCAssert(m_szKey[0] == '\0', "Should not call this function for string dictionary"); return m_iKey; } //取得CCObject指针。 inline CCObject* getObject() const { return m_pObject; } private: //初始化。 inline void init() { m_iKey = 0; m_pObject = NULL; memset(m_szKey, 0, sizeof(m_szKey)); memset(&hh, 0, sizeof(hh)); } private: char m_szKey[MAX_KEY_LEN+1]; //存储名称的字符数组。 int m_iKey; //哈希表索引 CCObject* m_pObject; //哈希值(CCObject指针) public: UT_hash_handle hh; //哈希表结构指针 friend class CCDictionary; //词典为友元类 }; //遍历词典中的所有词汇的一个宏,它内部调用HASH_ITER来进行for循环遍历链表。 #define CCDICT_FOREACH(__dict__, __el__) \ CCDictElement* pTmp##__dict__##__el__ = NULL; \ HASH_ITER(hh, (__dict__)->m_pElements, __el__, pTmp##__dict__##__el__) //词典类,由CCObject派生 class CC_DLL CCDictionary : public CCObject { public: //构造函数 CCDictionary(); //析构函数 ~CCDictionary(); //取得所有词汇的数量。 unsigned int count(); //返回所有的查询关键字。 CCArray* allKeys(); //取得对应CCObject指针的所有关键字或索引值。 CCArray* allKeysForObject(CCObject* object); //通过查询关键字取得对应CCObject指针 CCObject* objectForKey(const std::string& key); //通过哈希索引值取得对应CCObject指针 CCObject* objectForKey(int key); //通过查询关键字取得对应CCString指针 const CCString* valueForKey(const std::string& key); //通过哈希索引值取得对应CCString指针 const CCString* valueForKey(int key); //设置一个CCObject和对应的名称存入词典。 void setObject(CCObject* pObject, const std::string& key); //设置一个CCObject和对应的哈希索引存入词典。 void setObject(CCObject* pObject, int key); //按照查询关键字找到对应CCObject并删除。 void removeObjectForKey(const std::string& key); //按照哈希索引找到对应CCObject并删除。 void removeObjectForKey(int key); //按照容器中的查询关键字找到对应CCObject并删除。 void removeObjectsForKeys(CCArray* pKeyArray); //从词典中删除相应的词汇。 void removeObjectForElememt(CCDictElement* pElement); //从词典中清空所有的词汇。 void removeAllObjects(); //重载CCObject的拷贝函数。产生一个一模一样的词典。 virtual CCObject* copyWithZone(CCZone* pZone); //静态函数,取得单例的词典。请改用create函数,因为这个函数以后将被删除掉。 CC_DEPRECATED_ATTRIBUTE static CCDictionary* dictionary(); //静态函数,取得一个指定词典的COPY,请改用createWithDictionary函数,因为这个函数以后将被删除掉。 CC_DEPRECATED_ATTRIBUTE static CCDictionary* dictionaryWithDictionary(CCDictionary* srcDict); //静态函数:从一个plist文件中加载词典内容。此函数创建的词典是交由内存管理器来进行资源计数的,不需手动release。但请改用createWithContentsOfFile函数,因为这个函数以后也将被删除掉。 CC_DEPRECATED_ATTRIBUTE static CCDictionary* dictionaryWithContentsOfFile(const char *pFileName); //静态函数:从一个plist文件中加载词典内容,但此函数是多线程安全的,另外此函数创建的词典需要手动release。请改用 createWithContentsOfFileThreadSafe函数,因为这个函数以后也将被删除掉。 CC_DEPRECATED_ATTRIBUTE static CCDictionary* dictionaryWithContentsOfFileThreadSafe(const char *pFileName); //静态函数,创建一个新词典 static CCDictionary* create(); //静态函数,取得一个指定词典的COPY。 static CCDictionary* createWithDictionary(CCDictionary* srcDict); //静态函数:从一个plist文件中加载词典内容。 static CCDictionary* createWithContentsOfFile(const char *pFileName); //静态函数:从一个plist文件中加载词典内容,但此函数是多线程安全的,另外此函数创建的词典需要手动release。 static CCDictionary* createWithContentsOfFileThreadSafe(const char *pFileName); private: //将CCObject实例指针与对应的字符串名称存入哈希表。 void setObjectUnSafe(CCObject* pObject, const std::string& key); //将CCObject实例指针与对应的索引值存入哈希表。 void setObjectUnSafe(CCObject* pObject, const int key); public: //词汇的哈希表头部结构指针。 CCDictElement* m_pElements; private: //词典查询类型。 enum CCDictType { kCCDictUnknown = 0, kCCDictStr,//字符串名称 kCCDictInt //索引 }; CCDictType m_eDictType; //当前词典查询类型。一个词典实例要求只有一种固定词典查询类型。 CCDictType m_eOldDictType; //上次词典查询类型。这个变量是用来比对是否改变了词典查询类型。 }; NS_CC_END
再看CCDictionary.cpp:
#include "CCDictionary.h" #include "CCString.h" #include "CCInteger.h" using namespace std; //使用Cocos2d命名空间 NS_CC_BEGIN //构造函数 CCDictionary::CCDictionary() : m_pElements(NULL) , m_eDictType(kCCDictUnknown) , m_eOldDictType(kCCDictUnknown) { } //析构函数。 CCDictionary::~CCDictionary() { //请空词汇,释放所有词汇占用的内存。 removeAllObjects(); } //取得词典中的所有词汇数量。 unsigned int CCDictionary::count() { //通过HASH_CONT宏来取得哈希表的元素数量。 return HASH_COUNT(m_pElements); } //返回所有的查询关键字。 CCArray* CCDictionary::allKeys() { //取得词汇的数量 int iKeyCount = this->count(); if (iKeyCount m_szKey); pOneKey->autorelease(); pArray->addObject(pOneKey); } } else if (m_eDictType == kCCDictInt) { //如果当前词典查询类型是通过索引。 //遍历所有词汇。 HASH_ITER(hh, m_pElements, pElement, tmp) { //取得每一个词汇的名称字符串放入CCArray中。 CCInteger* pOneKey = new CCInteger(pElement->m_iKey); pOneKey->autorelease(); pArray->addObject(pOneKey); } } return pArray; } //取得对应CCObject指针的所有关键字或索引值。 CCArray* CCDictionary::allKeysForObject(CCObject* object) { //取得词汇的数量 int iKeyCount = this->count(); if (iKeyCount m_pObject) { //如果与指定的词汇相同,将其名称字符串放入CCArray中。 CCString* pOneKey = new CCString(pElement->m_szKey); pArray->addObject(pOneKey); pOneKey->release(); } } } else if (m_eDictType == kCCDictInt) { //如果当前词典查询类型是通过索引。 //遍历所有词汇。 HASH_ITER(hh, m_pElements, pElement, tmp) { //如果与指定的词汇相同,将其名称字符串放入CCArray中。 if (object == pElement->m_pObject) { CCInteger* pOneKey = new CCInteger(pElement->m_iKey); pArray->addObject(pOneKey); pOneKey->release(); } } } return pArray; } //通过查询关键字取得对应CCObject指针 CCObject* CCDictionary::objectForKey(const std::string& key) { //当前词典查询类型值有效性判断。此处有错,应该改为:if (m_eDictType == kCCDictUnknown || m_eDictType == kCCDictInt) return NULL; if (m_eDictType == kCCDictUnknown && m_eDictType == kCCDictUnknown) return NULL; //要求当前词典查询类型为按字符串查询。 CCAssert(m_eDictType == kCCDictStr, "this dictionary does not use string as key."); //定义临时词汇指针变量。 CCObject* pRetObject = NULL; CCDictElement *pElement = NULL; //通过名称字符串查询哈希表中的相应词汇 HASH_FIND_STR(m_pElements, key.c_str(), pElement); if (pElement != NULL) { //如果查询到词汇,返回其对应的CCObject指针 pRetObject = pElement->m_pObject; } return pRetObject; } //通过查询索引取得对应CCObject指针 CCObject* CCDictionary::objectForKey(int key) { //当前词典查询类型值有效性判。此处有错,应该改为:if (m_eDictType == kCCDictUnknown || m_eDictType == kCCDictStr) return NULL; if (m_eDictType == kCCDictUnknown && m_eDictType == kCCDictUnknown) return NULL; //要求当前词典查询类型为按字符串查询。 CCAssert(m_eDictType == kCCDictInt, "this dictionary does not use integer as key."); //定义临时词汇指针变量。 CCObject* pRetObject = NULL; CCDictElement *pElement = NULL; //通过索引查询哈希表中的相应词汇 HASH_FIND_INT(m_pElements, &key, pElement); if (pElement != NULL) { //如果查询到词汇,返回其对应的CCObject指针 pRetObject = pElement->m_pObject; } return pRetObject; } //通过查询关键字取得对应CCString指针,其实即要求存入词汇的CCObject指针是CCString实例对象指针。 const CCString* CCDictionary::valueForKey(const std::string& key) { //将通过查询关键字取得对应CCString指针强转为CCString指针。 CCString* pStr = (CCString*)objectForKey(key); if (pStr == NULL) { //如果没找到,返回空字符串 pStr = CCString::create(""); } return pStr; } //通过查询索引取得对应CCString指针,即要求存入词汇的CCObject指针是CCString实例对象指针。 const CCString* CCDictionary::valueForKey(int key) { //将通过查询索引取得对应CCString指针强转为CCString指针。 CCString* pStr = (CCString*)objectForKey(key); if (pStr == NULL) { //如果没找到,返回空字符串 pStr = CCString::create(""); } return pStr; } //设置一个CCObject和对应的名称存入词典。 void CCDictionary::setObject(CCObject* pObject, const std::string& key) { //参数有效性判断 CCAssert(key.length() > 0 && pObject != NULL, "Invalid Argument!"); //如果是第一次存入,记录查询类型为字符串类型。 if (m_eOldDictType == kCCDictUnknown) { m_eOldDictType = kCCDictStr; } //将当前词典查询类型设为字符串查询类型。这个变量是可以省略的,因为要求词典查询类型为固定。只用m_eOldDictType就可以了。 m_eDictType = kCCDictStr; CCAssert(m_eDictType == m_eOldDictType, "this dictionary does not use string as key."); //定义临时指针变量从词典中取得对应名称的词汇。 CCDictElement *pElement = NULL; HASH_FIND_STR(m_pElements, key.c_str(), pElement); if (pElement == NULL) { //如果词典中没有此词汇,将此新词汇放入词典。 setObjectUnSafe(pObject, key); } else if (pElement->m_pObject != pObject) { //如果词典中已有此词汇,则删除老词汇放入新词汇。 CCObject* pTmpObj = pElement->m_pObject; //此处调用retain对引用计数器加1可以避免在后面的删除函数中释放pTmpObj指向的CCObject。 pTmpObj->retain(); //删除此词汇 removeObjectForElememt(pElement); //放入新词汇。 setObjectUnSafe(pObject, key); //因为之前retain对引用计数器加1一次,所以必须release对引用计数器减1一次才能保证由内存管理器来进行内存释放时,pTempObj指向的CCObject可以正确的被释放掉。 pTmpObj->release(); } } //设置一个CCObject和对应的哈希索引存入词典。 void CCDictionary::setObject(CCObject* pObject, int key) { //参数有效性判断 CCAssert(pObject != NULL, "Invalid Argument!"); //如果是第一次存入,记录查询类型为索引类型。 if (m_eOldDictType == kCCDictUnknown) { m_eOldDictType = kCCDictInt; } //将当前词典查询类型设为索引查询类型。这个变量是可以省略的,因为要求词典查询类型为固定。只用m_eOldDictType就可以了。 m_eDictType = kCCDictInt; //一致性判断 CCAssert(m_eDictType == m_eOldDictType, "this dictionary does not use integer as key."); //定义临时指针变量从词典中取得对应名称的词汇。 CCDictElement *pElement = NULL; HASH_FIND_INT(m_pElements, &key, pElement); if (pElement == NULL) { //如果词典中没有此词汇,将此新词汇放入词典。 setObjectUnSafe(pObject, key); } else if (pElement->m_pObject != pObject) { //如果词典中已有此词汇,则删除老词汇放入新词汇。 CCObject* pTmpObj = pElement->m_pObject; //此处调用retain对引用计数器加1可以避免在后面的删除函数中释放pTmpObj指向的CCObject。 pTmpObj->retain(); //删除此词汇 removeObjectForElememt(pElement); //放入新词汇。 setObjectUnSafe(pObject, key); //因为之前retain对引用计数器加1一次,所以必须release对引用计数器减1一次才能保证由内存管理器来进行内存释放时,pTempObj指向的CCObject可以正确的被释放掉。 pTmpObj->release(); } } //按照查询关键字找到对应CCObject并删除。 void CCDictionary::removeObjectForKey(const std::string& key) { //当前词典是否有效 if (m_eOldDictType == kCCDictUnknown) { return; } //当前词典的查询类型是否为字符串名称查询方式 CCAssert(m_eDictType == kCCDictStr, "this dictionary does not use string as its key"); //参数有效性判断 CCAssert(key.length() > 0, "Invalid Argument!"); //定义临时指针变量从词典中取得对应名称的词汇。 CCDictElement *pElement = NULL; HASH_FIND_STR(m_pElements, key.c_str(), pElement); //从词典中删除相应的词汇。 removeObjectForElememt(pElement); } void CCDictionary::removeObjectForKey(int key) { //当前词典是否有效 if (m_eOldDictType == kCCDictUnknown) { return; } //当前词典的查询类型是否为索引查询方式 CCAssert(m_eDictType == kCCDictInt, "this dictionary does not use integer as its key"); //定义临时指针变量从词典中取得对应索引的词汇。 CCDictElement *pElement = NULL; HASH_FIND_INT(m_pElements, &key, pElement); //从词典中删除相应的词汇。 removeObjectForElememt(pElement); } //将CCObject实例指针与对应的字符串名称存入哈希表。 void CCDictionary::setObjectUnSafe(CCObject* pObject, const std::string& key) { //对pObject指向的实例对像引用计数器加1,即告诉其被词典使用.避免万一其的其它使用者都不再使用时被内存管理器释放. pObject->retain(); //由pObject和名称字符串产生一个新的词汇。 CCDictElement* pElement = new CCDictElement(key.c_str(), pObject); //将新的词汇放入哈希表中。 HASH_ADD_STR(m_pElements, m_szKey, pElement); } //将CCObject实例指针与对应的索引存入哈希表。 void CCDictionary::setObjectUnSafe(CCObject* pObject, const int key) { //对pObject指向的实例对像引用计数器加1,即告诉其被词典使用.避免万一其的其它使用者都不再使用时被内存管理器释放. pObject->retain(); //由pObject和名称字符串产生一个新的词汇。 CCDictElement* pElement = new CCDictElement(key, pObject); //将新的词汇放入哈希表中。 HASH_ADD_INT(m_pElements, m_iKey, pElement); } //按照容器中的查询关键字找到对应CCObject并删除。 void CCDictionary::removeObjectsForKeys(CCArray* pKeyArray) { //遍历CCArray实例对像的所有名称字符串,查询与之对应的词汇。并删除。 CCObject* pObj = NULL; CCARRAY_FOREACH(pKeyArray, pObj) { CCString* pStr = (CCString*)pObj; removeObjectForKey(pStr->getCString()); } } //从词典中删除相应的词汇。 void CCDictionary::removeObjectForElememt(CCDictElement* pElement) { //参数有效性判断 if (pElement != NULL) { //从哈希表中删除pElement指向的词汇 HASH_DEL(m_pElements, pElement); //前面在将词汇加入词典时对引用计数器加1,这里删除词汇是就应该对引用计数器减1。 pElement->m_pObject->release(); //释放词汇 CC_SAFE_DELETE(pElement); } } //从词典中清空所有的词汇。 void CCDictionary::removeAllObjects() { //定义遍历哈希表所用的指针变量 CCDictElement *pElement, *tmp; //遍历哈希表 HASH_ITER(hh, m_pElements, pElement, tmp) { //删除词汇并释放 HASH_DEL(m_pElements, pElement); pElement->m_pObject->release(); CC_SAFE_DELETE(pElement); } } //重载CCObject的拷贝函数。产生一个一模一样的词典。 CCObject* CCDictionary::copyWithZone(CCZone* pZone) { //参数有效性判断 CCAssert(pZone == NULL, "CCDirctionary should not be inherited."); //创建一个新的词典 CCDictionary* pNewDict = new CCDictionary(); //定义用来遍历的临时变量 CCDictElement* pElement = NULL; CCObject* pTmpObj = NULL; //如果是索引查询方式 if (m_eDictType == kCCDictInt) { //遍历所有词汇 CCDICT_FOREACH(this, pElement) { //产生遍历词汇对应的CCObject的COPY,生成新的词汇放入新的词典中. pTmpObj = pElement->getObject()->copy(); pNewDict->setObject(pTmpObj, pElement->getIntKey()); pTmpObj->release(); } } else if (m_eDictType == kCCDictStr) { //如果是名称字符串查询方式. //遍历所有词汇 CCDICT_FOREACH(this, pElement) { //产生遍历词汇对应的CCObject的COPY,生成新的词汇放入新的词典中. pTmpObj = pElement->getObject()->copy(); pNewDict->setObject(pTmpObj, pElement->getStrKey()); pTmpObj->release(); } } return pNewDict; } //静态函数,取得单例的词典,内部调用create函数。 CCDictionary* CCDictionary::dictionary() { return CCDictionary::create(); } //静态函数,取得单例的词典。 CCDictionary* CCDictionary::create() { //创建一个新的词典 CCDictionary* pRet = new CCDictionary(); if (pRet != NULL) { //将其设为由引用计数器来判断释放时机.交由内存管理器进行管理. pRet->autorelease(); } //返回新创建的词典指针 return pRet; } //静态函数,取得一个指定词典的COPY,内部调用createWithDictionary函数. CCDictionary* CCDictionary::dictionaryWithDictionary(CCDictionary* srcDict) { return CCDictionary::createWithDictionary(srcDict); } //静态函数,取得一个指定词典的COPY. CCDictionary* CCDictionary::createWithDictionary(CCDictionary* srcDict) { //查生一个指定词典的COPY. CCDictionary* pNewDict = (CCDictionary*)srcDict->copy(); pNewDict->autorelease(); return pNewDict; } //声明静态函数:从一个plist文件中加载词典内容,此函数是多线程安全的,其内部调用 createWithContentsOfFileThreadSafe函数。 extern CCDictionary* ccFileUtils_dictionaryWithContentsOfFileThreadSafe(const char *pFileName); //静态函数:从一个plist文件中加载词典内容,此函数是多线程安全的. CCDictionary* CCDictionary::dictionaryWithContentsOfFileThreadSafe(const char *pFileName) { return CCDictionary::createWithContentsOfFileThreadSafe(pFileName); } //静态函数:从一个plist文件中加载词典内容,此函数是多线程安全的. CCDictionary* CCDictionary::createWithContentsOfFileThreadSafe(const char *pFileName) { //这里调用Cocos2d-x的文件函数集中的带多线程安全的从plist文件加载词典函数实现相应功能. return ccFileUtils_dictionaryWithContentsOfFileThreadSafe(pFileName); } //静态函数:从一个plist文件中加载词典内容,其内部调用 createWithContentsOfFile函数。 CCDictionary* CCDictionary::dictionaryWithContentsOfFile(const char *pFileName) { return CCDictionary::createWithContentsOfFile(pFileName); } //静态函数:从一个plist文件中加载词典内容. CCDictionary* CCDictionary::createWithContentsOfFile(const char *pFileName) { CCDictionary* pRet = createWithContentsOfFileThreadSafe(pFileName); pRet->autorelease(); return pRet; } NS_CC_END
Cocos2d-x的词典类讲完了,相信大家已经大致了解了本词典的功能和用法。最后希望大家在领悟了它的意义后在各自的工作中设计出更高效的词典类。相信我,做游戏的太多地方会遇到类似的需求了。
最后,我想说,本博的内容比较唠叨,主要还是希望大家能够体会到本博的努力。另外本人目前阶段对于Cocos2d-x也属于学习阶段,暂时主要做代码分析,等到一阶段了才会进行项目实战的讲解,所以,希望各位理解。
相关推荐
资源名称:Cocos2d-x实战:JS卷——Cocos2d-JS开发内容简介:本书是介绍Cocos2d-x游戏编程和开发技术书籍,介绍了使用Cocos2d-JS中核心类、瓦片地图、物理引擎、音乐音效、数据持久化、网络通信、性能优化、多平台...
这份API文档不仅提供了关于Cocos2d-x的基本信息,还深入到具体的技术细节,对于学习和使用cocos2d-x开发游戏的开发者来说,是非常宝贵的参考资料。通过这份文档,开发者可以了解如何利用cocos2d-x的API构建游戏场景...
在Cocos2d-x 3.x中,有丰富的动画支持,如动作(Actions)、时间线(Timeline)等。同时,Cocos2d-x集成了Box2D物理引擎,使开发者能轻松实现物理效果,如碰撞检测、重力模拟等。 游戏中的音频管理也是不可或缺的一...
谨记,该事件只能用于cocos2d-x中。 事件发送者需要继承EventDispatcher类 事件接收者需要继承EventHandle类,还需要实现handleEvent方法 事件发送者和事件接收者要在构造函数和析构函数中调用一下方法 事件发送者...
cocos2d-x 是一个开源的游戏开发框架,使用 C++ 语言编写,支持多平台发布,包括 iOS、Android、Windows、macOS、Linux 和 Web。cocos2d-x v3.16 是该框架的一个版本号,本文档主要介绍了该版本的安装流程以及环境...
在Cocos2d-x中,C++作为主要的编程语言,相比初版,第二版可能涵盖了更多Cocos2d-x的新特性和优化。C++的使用可以提供更好的性能和更直接的内存管理,同时也能充分利用面向对象编程的特性来构建复杂的游戏逻辑。 源...
接下来,把 F:\cocos2d-1.0.1-x-0.9.1\cocos2dx 和 F:\cocos2d-1.0.1-x-0.9.1\CocosDenshion 这两个文件夹里面的全部内容拷贝一份到 D:\cocos2d-xProjects\HelloWorld 中去。 九、设置静态链接库 接下来,打开 F:\...
《cocos2d-x 3.8:经典游戏引擎源码解析》 cocos2d-x 是一个跨平台的游戏开发框架,它基于...对于想要深入理解游戏引擎工作原理或者研究历史版本的开发者来说,这个“cocos2d-x-3.8.zip”压缩包无疑是宝贵的参考资料。
这个压缩包“cocos2d-x-cocos2d-x-2.2.2.zip”包含了cocos2d-x 的2.2.2版本,该版本是cocos2d-x发展中的一个重要里程碑,它提供了许多改进和优化,使得开发者能够更加高效地创建2D游戏和应用。 在cocos2d-x 2.2.2中...
Cocos2d-x提供了一个SpineNode类,它是Cocos2d-x的CCNode的子类,可以直接在场景中添加和管理Spine动画。通过Lua绑定,你可以轻松地调用Spine的API来播放、停止、暂停或重置动画,以及改变动画的速度、时间缩放等...
开发者可以利用Flash强大的动画编辑功能,创建出丰富的动态效果,然后在cocos2d-x中无缝使用。 其次,该工具提供了详细的资源映射,确保Flash中的图层、帧和时间轴等元素能够准确地对应到cocos2d-x的节点结构中。这...
读者需要理解C++的基本语法、类与对象、模板等核心概念,以便更好地运用到Cocos2d-x中。 在Cocos2d-x框架内,主要包括场景(Scene)、层(Layer)、节点(Node)等概念。场景是游戏的顶层容器,可以包含多个层,层...
Cocos2d-x是一个开源的游戏开发框架,广泛用于2D游戏、实时渲染应用程序和其他互动内容的制作。...解压并研究“cocos2d-x-3.1”中的源码,可以深入学习游戏开发的各个方面,并为更新版本的学习打下坚实基础。
6. **音频和音乐**:介绍如何在Cocos2d-x中播放背景音乐和音效,以及音乐的控制和管理。 7. **网络与存储**:讨论如何进行网络通信,如下载更新、保存和读取游戏数据。 8. **性能优化**:提供关于代码优化、内存...
本篇文章将深入探讨cocos2d-x 3.0中实现人物行走的关键技术和步骤,以及如何结合提供的代码和图片资源进行实践。 一、cocos2d-x 3.0简介 cocos2d-x 3.0是cocos2d-x系列的一个重要升级,它基于C++编写,支持跨平台...
标题中提到了"Cocos2d-x实战++JS卷++Cocos2d-JS开发+PDF电子书下载+带书签目录+完整",这里面包含了几个关键知识点: 1. Cocos2d-x:是一个开源的游戏开发框架,它主要用于开发跨平台的游戏和应用程序,支持iOS、...
《cocos2d-x 2.1.4:探索移动游戏开发的新篇章》 cocos2d-x 是一个跨平台的2D游戏开发框架,它为开发者提供了强大的工具和...通过深入理解和熟练运用cocos2d-x,开发者可以充分发挥其潜力,打造出引人入胜的游戏世界。
在Cocos2d-x中,Lua与C++的交互是通过tolua++或tolua+1等绑定工具完成的,这使得游戏逻辑可以独立于底层系统,提高开发效率。 书中可能详细讲解了如何设置Cocos2d-x开发环境,包括安装、配置以及Lua的集成。此外,...
cocos引擎老版本下载集合(cocos2d-x-2.2.1 - 3.5),分别有cocos2d-x-3.5、cocos2d-x-3.4、cocos2d-x-3.2、cocos2d-x-2.2.6、cocos2d-x-2.2.2和cocos2d-x-2.2.1。
cocos2d-x-2.1.5