#
一切又歸零了。不解釋什么! 無所謂得,無所謂失 有任性,有責任 2016終于開始。
本文地址:http://www.shnenglu.com/zdhsoft/archive/2014/09/03/208216.html 本文基于cocos2dx 3.2 cocos2dx 提供了一個基于xml的用戶數據存貯類,給基于cocos2dx開發的用戶數據存貯,這個類名就是UserDefault,在cocos2dx 2.x中是CCUserDefault。我的程序用的就是這個,但是最近老出錯,于是分析源代碼,發現了一個讓我震驚的東西。經過分析,發現用UserDefault每讀寫一次數據,都會創建一個tinyxml對象,然后讀取xml內容。如果是寫數據,還是寫入xml一次。下面是對應的代碼: 讀取key,所以各種讀取key的操作,都是類似這樣。 double UserDefault::getDoubleForKey(const char* pKey, double defaultValue) { const char* value = nullptr; tinyxml2::XMLElement* rootNode; tinyxml2::XMLDocument* doc; tinyxml2::XMLElement* node; node = getXMLNodeForKey(pKey, &rootNode, &doc); // find the node if (node && node->FirstChild()) { value = (const char*)(node->FirstChild()->Value()); }
double ret = defaultValue;
if (value) { ret = utils::atof(value); }
if (doc) delete doc;
return ret; } 關于getXMLNodeForKey的實現 /** * define the functions here because we don't want to * export xmlNodePtr and other types in "CCUserDefault.h" */
static tinyxml2::XMLElement* getXMLNodeForKey(const char* pKey, tinyxml2::XMLElement** rootNode, tinyxml2::XMLDocument **doc) { tinyxml2::XMLElement* curNode = nullptr;
// check the key value if (! pKey) { return nullptr; }
do { tinyxml2::XMLDocument* xmlDoc = new tinyxml2::XMLDocument(); *doc = xmlDoc;
std::string xmlBuffer = FileUtils::getInstance()->getStringFromFile(UserDefault::getInstance()->getXMLFilePath());
if (xmlBuffer.empty()) { CCLOG("can not read xml file"); break; } xmlDoc->Parse(xmlBuffer.c_str(), xmlBuffer.size());
// get root node *rootNode = xmlDoc->RootElement(); if (nullptr == *rootNode) { CCLOG("read root node error"); break; } // find the node curNode = (*rootNode)->FirstChildElement(); while (nullptr != curNode) { const char* nodeName = curNode->Value(); if (!strcmp(nodeName, pKey)) { break; }
curNode = curNode->NextSiblingElement(); } } while (0);
return curNode; } 關于setValueForKey的實現 static void setValueForKey(const char* pKey, const char* pValue) { tinyxml2::XMLElement* rootNode; tinyxml2::XMLDocument* doc; tinyxml2::XMLElement* node; // check the params if (! pKey || ! pValue) { return; } // find the node node = getXMLNodeForKey(pKey, &rootNode, &doc); // if node exist, change the content if (node) { if (node->FirstChild()) { node->FirstChild()->SetValue(pValue); } else { tinyxml2::XMLText* content = doc->NewText(pValue); node->LinkEndChild(content); } } else { if (rootNode) { tinyxml2::XMLElement* tmpNode = doc->NewElement(pKey);//new tinyxml2::XMLElement(pKey); rootNode->LinkEndChild(tmpNode); tinyxml2::XMLText* content = doc->NewText(pValue);//new tinyxml2::XMLText(pValue); tmpNode->LinkEndChild(content); } }
// save file and free doc if (doc) { doc->SaveFile(UserDefault::getInstance()->getXMLFilePath().c_str()); delete doc; } } 它的flush方法也有驚人的發現: void UserDefault::flush() { } 它是一個空函數,也就是說,你在寫入數據的時候,會以為最后會通過flush才會寫入數據,沒想全錯了! 如果你用它存貯比較多的字段時,你就會現,你悲劇了。 幸好發現及時,這里不建議大家使用UserDefault做為你的數據存貯。 可以可以用自定義的方式文件讀寫 如可以通過標準的C讀寫 fopen,fwrite等或iostream也都可以,重點是讀寫的文件路徑,會有所不同,下面是得到文件路徑的例子 std::string strFullFileName = FileUtils::getInstance()->getWritablePath() + DATA_FILE_NAME;
最后:不要求寫太高質量的代碼,但也不要寫的太低質量了
本文地址:http://www.shnenglu.com/zdhsoft/archive/2014/08/23/208104.html 經過幾天的填坑,終于將現有的項目由cocos2dx 2.2.2移到cocos2dx 3.2,差點放棄3.2了,但在最后一刻,又把坑填平了。 cocos2dx 2.x到3.x是一個巨大的變化,可以算是完全不同。以前的類名,全是CC開頭的,現在全部去掉了。很多enum都改用enum class了 所以,你知道2.x,對不起,你比小白學習3.x更難。你用2.x的做法用在3.x,那就全是坑了... 言歸正傳, 2.x的時候,按鈕設置為Disabled的時候,是看不見。3.x的是沒有禁用狀態的,但是不會響應touch事件。 在cocostudio UI編輯的時候,按鈕是三種狀態的(有三個不同狀態的圖片),但沒有相應改變狀態的函數 于是,就分析源碼,發現它是在onPressStateChangedToDisabled();更改為禁用狀態的圖片。再找,是于 在其基類的ui:Widget的setBright和setHighlight有調用這個onPressStateChangedToDisabled,但是setEnabled僅僅是改為了一個成員變化, 所以你在這里設置disabled,就不會有任何效果。除了上面兩個函數之后,還有一個函數setBrightStyle是設置按鈕是普通狀態還是高亮狀態 下面是BrightStyle的定義 enum class BrightStyle { NONE = -1, NORMAL, HIGHLIGHT }; 下面是一個包裝的禁用啟用的函數 //設置按鈕禁用啟用狀態 inline void SetButtonEnabled(ui::Button * paramButton, bool paramEnabled) { if (isNULL(paramButton)) return; if (paramEnabled) { paramButton->setBright(true); paramButton->setEnabled(true); paramButton->setTouchEnabled(true); } else { paramButton->setBright(false); paramButton->setEnabled(false); paramButton->setTouchEnabled(false); } }
結果是:大家不要采用3.x系列的cocos2dx,還是用2.2.x吧 原因如下: 1、坑非常多,多的讓你放棄 2、兼容性非常不好,如果你是2.x的工程,還是用2.x的吧 3、資料非常少,開發方提供了3.x版本,但是3.x的版本各項資料都非常欠缺!論壇上各種3.x的問題貼子,很多都沒人回答。 4、3.x做了很多無所謂的精減,結果是,你用到這些他們精減的庫時,你只有去哭了。(你的開發環境不可能和他們的一樣,他們沒問題,你的一定會有問題) 5、千萬不要拿來3.x做商業化的程序,會大大增加你的開發周期和成本。
本文地址: http://www.shnenglu.com/zdhsoft/archive/2014/08/04/207906.html今天,有空翻了一下<C++Primer plus(第六版)>,看到里面有介紹新的for循環和初始化列表,但是我實現的動態數組XDynamicArray不支持這些新特性,沒辦法,只好進行改造了。 首先是for循環,如下面的樣式 for(auto e:stList) { cout<<e<<endl; } 是于就各種google,和查找C++11的array的源代碼,總結:就是提供一個標準的iterator和begin,end這兩個方法,就可以了。 是于定義了一個iterator //一個數組的Array的Iterator類 /* 這里提供XArrayIterator這個類,目的是使得這里支持C++11的for循環 */ template<class Array> class XArrayIterator { public: typedef typename Array::ElementType & reference; typedef typename Array::ElementType * pointer;
XArrayIterator() :m_Index(ARRAY_INVALID_INDEX), m_Array(nullptr) {}
XArrayIterator(Array * paramArray, XInt paramIndex) :m_Index(paramIndex), m_Array(paramArray) {}
XArrayIterator(Array & paramArray, XInt paramIndex) :m_Index(paramIndex), m_Array(¶mArray) {}
XArrayIterator(const XArrayIterator<Array> & paramR) :m_Index(paramR.m_Index), m_Array(paramR.m_Array) {}
XArrayIterator & operator = (const XArrayIterator<Array> & paramR) { if (this != ¶mR) { m_Index = paramR.m_Index; m_Array = paramR.m_Array; } return *this; }
XArrayIterator & operator = (Array * paramArray) { m_Array = paramArray; if (isNotNULL(m_Array)) { m_Array = m_Array->getFirstIndex(); } else { m_Index = ARRAY_INVALID_INDEX; } return *this; }
bool operator == (const XArrayIterator<Array> & paramR) { return m_Index == paramR.m_Index && m_Array == paramR.m_Array; }
bool operator != (const XArrayIterator<Array> & paramR) { return m_Index != paramR.m_Index || m_Array != paramR.m_Array; } reference operator*() { return (*m_Array)[m_Index]; } const reference operator*() const { return (*m_Array)[m_Index]; }
pointer operator->() { return &(*m_Array[m_Index]); }
const pointer operator->() const { return &(*m_Array[m_Index]); }
XArrayIterator & operator ++() { if (m_Index != ARRAY_INVALID_INDEX && isNotNULL(m_Array)) { m_Index++; if (m_Index >= m_Array->getLength()) m_Index = ARRAY_INVALID_INDEX; } return *this; }
XArrayIterator operator ++(int) { XArrayIterator stRet = *this; if (m_Index != ARRAY_INVALID_INDEX && isNotNULL(m_Array)) { m_Index++; if (m_Index >= m_Array->getLength()) m_Index = ARRAY_INVALID_INDEX; } return stRet; }
XArrayIterator & operator --() { if (m_Index != ARRAY_INVALID_INDEX && isNotNULL(m_Array)) { m_Index--; if (m_Index < 0) m_Index = ARRAY_INVALID_INDEX; } return *this; }
XArrayIterator operator --(int) { XArrayIterator stRet = *this; if (m_Index != ARRAY_INVALID_INDEX && isNotNULL(m_Array)) { m_Index--; if (m_Index < 0) m_Index = ARRAY_INVALID_INDEX; } return stRet; }
XArrayIterator & operator +=(XInt paramOffset) { if (m_Index != ARRAY_INVALID_INDEX && isNotNULL(m_Array)) { m_Index += paramOffset; if (!(m_Index >= 0 && m_Index < m_Array->getLength())) { m_Index = ARRAY_INVALID_INDEX; } } return *this; }
XArrayIterator operator + (XInt paramOffset) const { XArrayIterator stRet = *this; stRet += paramOffset; return stRet; }
XArrayIterator & operator -=(XInt paramOffset) { return operator += (-paramOffset); }
XArrayIterator operator - (XInt paramOffset) const { XArrayIterator stRet = *this; stRet -= paramOffset; return stRet; } private: XInt m_Index; Array * m_Array; }; 然后在XDynamicArray兩個方法 typedef XArrayIterator<XDynamicArray<T> > iterator /*這里定義begin和end主要有兩個目的 目的1:使它可以像標準STD容器那樣遍歷 目的2:使它可以支持C++11的for循環 例子: XDynamicArray<int> st; for(auto x:st) { cout<<x<<endl; } */ iterator begin() { iterator stRet(this, this->getFirstIndex()); return stRet; }
iterator end() { iterator stRet(this, ARRAY_INVALID_INDEX); return stRet; } 這樣就可以了,測試通過。你們也可以試試。 C++11的另一個特性,就是新初始化列表,如下面例子 vector st {1,2,3,4,5}; 看起來有點意思,于是又google一下,翻閱了各位大神的貼子,最終找到,然后我就實現了。這部分需要使用C++11的initializer_list模板類,具體使用代碼如下。 //這個構造函數的定義,是為了實現C++11的初始化列表,如下例子 /* XDynamicArray<int> st {1,2,3,4,5}; 或 XDynamicArray<int> st = {1,2,3,4,5}; */ XDynamicArray(std::initializer_list<T> paramList) : m_Length(0), m_Capacity(0), m_Data(NULL) { this->ensureCapacity((XInt)paramList.size()); for (auto e : paramList) { Append(e); } } 使用initializer_list需要頭文件:#include <initializer_list> 上述代碼,已經放到我的開放庫中了,大家可以自行下載。 我的開放代碼
本文地址: http://www.shnenglu.com/zdhsoft/archive/2014/08/01/207880.html現在C++智能指針有無數個實現了,多一個也無所謂。哈。 這個智能指針是專門為cocos2dx 2.2.x定制的。主要是為了方便使用,同時又要遵循現有的cocos2dx的內存管理。特實現這樣一個智能指針。在使用的時候不需要考慮retain或release操作,也不需要new或delete操作! 下面是實現代碼 //在很多時候,類的成員是CCObject的子對象,為了保證對其正常使用,又要遵循cocos2dx的內存管理,特實現了這樣的一個智能指針,方便使用。 #ifndef _X_COCOS_PTR_H_ #define _X_COCOS_PTR_H_ namespace zdh { template<class T> class XCocosPtr { public: XCocosPtr() :m_Object(nullptr) {}
XCocosPtr(T * paramObject) :m_Object(paramObject) { if (m_Object != nullptr) { m_Object->retain(); } }
XCocosPtr(const XCocosPtr & paramPtr) :m_Object(paramPtr.m_Object) { if (m_Object != nullptr) { m_Object->retain(); } }
~XCocosPtr() { ptr_release(); } //重載賦值運算符 XCocosPtr & operator = (T * paramObject) { set(paramObject); return *this; }
XCocosPtr & operator = (XCocosPtr & paramObject) { set(paramObject.m_Object); return *this; } //重載比較運算符 bool operator == (T * paramObject) const { return m_Object == paramObject; }
bool operator != (T * paramObject) const { return m_Object != paramObject; } //重載*運算符 T & operator*() { return *m_Object; }
const T & operator*() const { return *m_Object; } //重載->運算符,使其可以像指針那樣使用 T * operator ->() { return m_Object; }
const T * operator ->() const { return m_Object; } //判斷對象是否為空 bool is_null() const { return m_Object == nullptr; } //判斷對象是否為不空 bool is_not_null() const { return m_Object != nullptr; } //創建對象 這里會使用調用對象的create來創建對象 T * create() { T * pNewObject = T::create(); set(pNewObject); return pNewObject; } //設置對象 void set(T * paramObject) { if (m_Object != paramObject) { T * p = m_Object; m_Object = paramObject; if (m_Object != nullptr) { m_Object->retain(); } if (isNotNULL(p)) { p->release(); } } } //取對象 T * get() { return m_Object; } //這里沒有使用release這個名稱,是為了防止和object的release混淆 void ptr_release() { if (m_Object != nullptr) { m_Object->release(); m_Object = nullptr; } } private: T * m_Object; }; } #endif 例子 //類的數據成員定義:
XCocosPtr<CCSprite> m_Sprite; //在init中
m_Sprite = CCSprite::create("  "); //或
m_Sprite.create()
本文地址: http://www.shnenglu.com/zdhsoft/archive/2014/07/25/207805.html用CCLabelTTF顯示的數字不好看,于是就想到用圖片來代理。目前網上的實現都是把每個數字做一個CCSprite組合的方式。但是我想,動態生成紋理的方式。沒有就只好自己手動寫一個。 頭文件 #ifndef _X_NUMBER_H_ #define _X_NUMBER_H_ #include <cocos2d.h> #include <xtype.h> namespace cocos2d { //基于圖片顯示的數字 /* 這個類不是用一個一個數字拼起來,而是渲染成一個獨立的紋理 zdh::XDDWord是一個64位無符號整數 */ class CCPictureNumber : public CCSprite { public: typedef CCSprite Inherited; public: CCPictureNumber(); ~CCPictureNumber(); virtual bool init(void); int BuildNumber(zdh::XDDWord paramNumber, const char * paramNumberResName); int BuildNumber(zdh::XDDWord paramNumber, CCTexture2D * paramTexture); int BuildNumber(zdh::XDDWord paramNumber); CREATE_FUNC(CCPictureNumber);
void setNumberTexture(CCTexture2D * paramTexture); void setNumberTexture(const char * paramNumberResName); CCTexture2D * getNumberTexture();
zdh::XDDWord getNumber() const; void setNumber(zdh::XDDWord paramNumber); int Build(); private: CCTexture2D * m_NumberTexture; zdh::XDDWord m_Number; }; } #endif 源文件 #include "xpicture_number.h" #include <xstring.h> namespace cocos2d { //-------------------------------------------------------------------------------------- //從指定資源名稱構建 int CCPictureNumber::BuildNumber(zdh::XDDWord paramNumber, const char * paramNumberResName) { this->setNumber(paramNumber); this->setNumberTexture(CCTextureCache::sharedTextureCache()->addImage(paramNumberResName)); return this->Build(); }
//-------------------------------------------------------------------------------------- //從指定紋理構建 int CCPictureNumber::BuildNumber(zdh::XDDWord paramNumber, CCTexture2D * paramTexture) { this->setNumber(paramNumber); this->setNumberTexture(paramTexture); return this->Build(); } //-------------------------------------------------------------------------------------- int CCPictureNumber::BuildNumber(zdh::XDDWord paramNumber) { this->setNumber(paramNumber); return this->Build(); }
//-------------------------------------------------------------------------------------- bool CCPictureNumber::init(void) { if (!Inherited::init()) return false; return true; } //-------------------------------------------------------------------------------------- CCPictureNumber::CCPictureNumber() { m_NumberTexture = nullptr; m_Number = 0; } //-------------------------------------------------------------------------------------- CCPictureNumber::~CCPictureNumber() { if (zdh::isNotNULL(m_NumberTexture)) { m_NumberTexture->release(); } } //-------------------------------------------------------------------------------------- void CCPictureNumber::setNumberTexture(CCTexture2D * paramTexture) { if (m_NumberTexture == paramTexture) return; if (zdh::isNotNULL(m_NumberTexture)) { m_NumberTexture->release(); } m_NumberTexture = paramTexture; if (zdh::isNotNULL(m_NumberTexture)) { m_NumberTexture->retain(); } } //-------------------------------------------------------------------------------------- void CCPictureNumber::setNumberTexture(const char * paramNumberResName) { this->setNumberTexture(CCTextureCache::sharedTextureCache()->addImage(paramNumberResName)); }
//-------------------------------------------------------------------------------------- CCTexture2D * CCPictureNumber::getNumberTexture() { return m_NumberTexture; } //-------------------------------------------------------------------------------------- int CCPictureNumber::Build() { if (zdh::isNULL(m_NumberTexture)) return zdh::ERR_FAIL;
zdh::XAnsiString strNumber(m_Number); //將整數轉換為字符串 int iNumCount = strNumber.getLength(); //取得字符個數 CCSize stSize = m_NumberTexture->getContentSize(); //取得紋理大小,要求紋理中每個數字都是等寬等高,并依照0123456789排列 int iNumWidth = (int)stSize.width / 10; //紋理中每個數字的寬度 int iNumHeight = (int)stSize.height; //紋理中每個數字的高度
CCRenderTexture * pRT = CCRenderTexture::create(iNumWidth * iNumCount, iNumHeight); //創建渲染紋理對象,并數字確定寬度 CCSprite * pSprite = CCSprite::create(); //創建精靈對象,用于繪制數字 pSprite->setAnchorPoint(0, 0); pSprite->setTexture(m_NumberTexture); CCRect stRect; pRT->begin(); for (int i = 0; i < iNumCount; i++) { int iNumber = strNumber[i] - '0'; //設置要顯示數字的紋理區域,這個區域是指參數中paramTexture中區域 stRect.setRect(iNumber * iNumWidth, 0, iNumWidth, iNumHeight); pSprite->setTextureRect(stRect, false, stRect.size); pSprite->setPosition(i * iNumWidth, 0); //計算顯示的偏移位置 pSprite->visit(); //渲染到pRT中 } pRT->end(); //取得生成的紋理 this->setTexture(pRT->getSprite()->getTexture()); //設置顯示的內容 stRect.setRect(0, 0, iNumWidth * iNumCount, iNumHeight); this->setTextureRect(stRect, false, stRect.size); //默認的情況下,通過CCRenderTexture得到的紋理是倒立的,這里需要做一下翻轉 this->setFlipY(true); //釋放資源 delete pSprite; delete pRT; return zdh::ERR_OK; } //-------------------------------------------------------------------------------------- zdh::XDDWord CCPictureNumber::getNumber() const { return m_Number; } //-------------------------------------------------------------------------------------- void CCPictureNumber::setNumber(zdh::XDDWord paramNumber) { m_Number = paramNumber; }
} 數字圖片文件  使用例子 CCPictureNumber * pNum = CCPictureNumber::create(); pNum->BuildNumber(1234567, "ui_play_num05.png"); pNum->setPosition(200, 200); pNum->setAnchorPoint(0, 0);
this->addChild(pNum, 100); //
本文地址: http://www.shnenglu.com/zdhsoft/archive/2014/07/23/207760.html使用cocostudio可以裝載編輯好的UI,但是過于復雜。特別是在加截UI后,發現觸屏事件有些問題。如果直接使用程序寫死加載UI又過于麻煩。花點時間,增加了一個基于ini的UI配置類,目前只實現了CCSprite和plist的加載。其它的可以后面慢慢加 頭文件 #ifndef _X_UI_H_ #define _X_UI_H_ #include <cocos2d.h> namespace zdh { USING_NS_CC; void CreateByXUI(CCNode * paramParent, const char * paramFileName); } #endif 源文件 #include "xui.h" #include "xini.h" #include "xlog.h"
namespace zdh { namespace xui { //-------------------------------------------------------------------------------------- int GetIntValue(XIniText::TSection * paramSection, const char * paramKeyName) { auto pV = paramSection->getEntry(paramKeyName); if (isNULL(pV)) return 0; else return pV->getValue().getField().ToIntDef(0); } //-------------------------------------------------------------------------------------- int GetDoubleValue(XIniText::TSection * paramSection, const char * paramKeyName) { auto pV = paramSection->getEntry(paramKeyName); if (isNULL(pV)) return 0; else return pV->getValue().getField().ToIntDef(0); } //-------------------------------------------------------------------------------------- const XAnsiString & GetStringValue(XIniText::TSection * paramSection, const char * paramKeyName) { static const XAnsiString strEmpty; auto pV = paramSection->getEntry(paramKeyName); if (isNULL(pV)) return strEmpty; else return pV->getValue().getField(); } };
//-------------------------------------------------------------------------------------- void CreateSpriteByXUI(CCNode * paramParent, XIniText::TSection * paramSpriteSection) { XInt ix = xui::GetIntValue(paramSpriteSection, "x"); XInt iy = xui::GetIntValue(paramSpriteSection, "y"); XInt izOrder = xui::GetIntValue(paramSpriteSection, "zOrder"); const XAnsiString & pImageName = xui::GetStringValue(paramSpriteSection, "image"); XInt iTag = xui::GetIntValue(paramSpriteSection, "tag"); CCSprite * pSprite = NULL; if (pImageName[0] == ':') //如果是從Cache中讀取 { pSprite = CCSprite::createWithSpriteFrameName(pImageName.c_str()+1); } else { pSprite = CCSprite::create(pImageName.c_str()); } pSprite->setPosition(ix, iy); pSprite->setAnchorPoint(0, 0); pSprite->setTag(iTag); pSprite->setZOrder(izOrder); paramParent->addChild(pSprite, izOrder); } void LoadSpriteFrameByPList(CCNode * /*paramParent*/, XIniText::TSection * paramSection) { const XAnsiString & pPListName = xui::GetStringValue(paramSection, "filename"); CCSpriteFrameCache::sharedSpriteFrameCache()->addSpriteFramesWithFile(pPListName.c_str()); }
//-------------------------------------------------------------------------------------- void CreateByXUI(CCNode * paramParent, const char * paramFileName) { std::string strFullFileName = CCFileUtils::sharedFileUtils()->fullPathForFilename(paramFileName); unsigned long dwGetSize = 0; const unsigned char * pData = CCFileUtils::sharedFileUtils()->getFileData(strFullFileName.c_str(), "rb", &dwGetSize); ZDH_INFO("Load XUI:%s size=%u", paramFileName, dwGetSize); if (dwGetSize == 0) { if (isNotNULL(pData)) delete[] pData; return; }
std::string strData((const char *)pData, dwGetSize); std::stringstream ss(strData); XIniText stIni; if (!stIni.Load(ss)) { ZDH_INFO("Load XUI Fail, %s", paramFileName); return; } for (int s = 0; s < stIni.getSectionCount(); s++) { auto pSection = stIni.getSection(s); auto pType = pSection->getEntry("type"); if (isNULL(pType)) { ZDH_INFO("Section=[%s] not exist key:\"type\"", pSection->getSectionName().c_str()); continue; } const XAnsiString & paramTypeValue = pType->getValue().getField(); if (paramTypeValue == "CCSprite") { CreateSpriteByXUI(paramParent, pSection); } else if (paramTypeValue == "plist") { LoadSpriteFrameByPList(paramParent, pSection); } } } } 配置文件 #支持UTF-8格式 [gk_label.png] type = CCSprite image = gk_label.png tag = 1 x = 18 y = 914 zOrder = 1
[mb_label.png] type = CCSprite image = :mb_label.png ·#冒號開頭表示從CCSpriteFrameCache加載圖片 tag = 1 x = 348 y = 916 zOrder = 1
[score_label.png] type = CCSprite image = score_label.png tag = 1 x = 258 y = 855 zOrder = 1
[game_star.plist] #批量裝載 type = plist filename = game_star.plist 相關用到的TTextIni和XAnsiString,參考 我的開源代碼
本文地址: http://www.shnenglu.com/zdhsoft/archive/2014/07/23/207756.html這四個是我用的主要IDE。 VS+Visual AssistX可以用無敵開形容,太強大了。雖然我只用來寫C++代碼。我個人覺得,應該沒有什么IDE可以超過它的。沒有什么好形容它的,就是一直在用它... Eclipse也是一個非常強的,除了java,它還可以是C++,lua,tcl,python,ActionScript3等語言的IDE,現在cocos2dx也基于它推出cocos2dx 3.x系列的lua語言IDE。最新版本是luna,但是這次感覺和以前有一個最大的變化就是Menu->Help->Install new software,以前你要裝C++,那需要到CDT的頁面找插件的更新地址,其它語言也是類似。但是這次它提供一個luna的插件鏈接,可以安裝各種你想要的eclipse插件,不用再一個一個找了。  當然,一些不是eclipse一起開發的,就還是要用老方法了。在eclipse這個工具,又衍生出FlashBuilder和ADT這兩個目前比較常見的開發工具,一個用于開發Flash,一個用于開發Android。雖然它很NB,但是我也只是拿它打打醬油。另然,eclipse的工程文件,是讓我非常無語的地方,比起vs等IDE,復雜多了。它的重構功能,還不夠,這是兩點是我拿它打醬油的原因。 C++Builder是我曾經用過的編輯器,它曾經是非常牛的。用它開發數據庫和windows應用,一個字,就是快。兼顧速度和可視開發以及C++,雖然比它的本尊delphi差些,也比那個時候的vc強很多,易用性不比vb差。C++Builder6最后一個值得懷念的,后面borland把它的根本開發工具賣了。最近最新的RAD Studio XE6也發布了,可以可視化開發Android和windows以及iOS應用,可惜bug太多,當玩具可以,不怕死的,可以拿它去開發商業軟件。如果你沒買正版,它們的代理會來找你麻煩。還有它的安裝文件巨大,你的C盤沒20G,就不要去試了。borland為什么會死,就是自己作死的。還有不得不提一下Turbo C 2.0,這是我用過最好的IDE之一,非常經典。(Borland Turbo C,Turbo Pascal,Borland C++ 3.1,等都是經典) JCreator是我當用java語言開發的時候,用到的。我用它的原因是,它非常小,非常干凈,比eclipse用起來清爽多了。可惜它發展的不怎么樣。 除了上面4個,我還常用editplus,notepad++和vi等編輯器。nodepad重點在語言加亮,editplus在于它非常小巧,功能強大,非常清爽,是我開發必備的工具。因為要常在linux下修改數據,所以vi也是常用之一,可惜只用它皮毛。 現在vs的版本是2013,從2012提供了python插件。python開發者們有福了。
|