做RPG游戏的时候会有剧情对,中英文混搭,要求打字效果,一个字一个字的往出蹦。
先看一下xml文件
- <?xml version="1.0" encoding="UTF-8"?>
- <plist version="1.0">
- <talk anchor="0" icon="talk/icon.png" name="路人甲:" content=" 听说他已经30了。"/>
- <talk anchor="1" icon="talk/icon.png" name="路人乙:" content=" 是啊!都30了还叫to3(奔三),装嫩呢!"/>
- <talk anchor="0" icon="talk/icon.png" name="路人甲:" content=" 哈哈哈……"/>
- </plist>
anchor:对齐方式 0左 1右
创建一个对话映射的节点TalkNode
- class TalkNode
- {
- public:
- bool anchor;
- std::string icon;
- std::string name;
- std::string content;
- void init(TiXmlNode *node);
- bool getAnchor(){return anchor;};
- const char* getIcon(){returnicon.c_str();};
- const char* getName(){returnname.c_str();};
- const char* getContent(){returncontent.c_str();};
- std::string getContentByLength(intlength);
- int contentLeght;
- int getContentLength();
- };
再看TalkNode的实现
- voidTalkNode::init(TiXmlNode *node)
- {
- TiXmlElement *element =node->ToElement();
- int intValue;
- if(element->QueryIntAttribute("anchor", &intValue) ==TIXML_SUCCESS)
- {
- anchor = intValue;
- }
- else
- {
- anchor = false;
- }
- name =element->Attribute("name");
- icon =element->Attribute("icon");
- content =element->Attribute("content");
- contentLeght = 0;
- int length = content.length();
- int i = 0;
- while(i < length)
- {
- char ch = getContent()[i];
- //重点在这里
- //中文在ASCII码中是-127~0
- if (ch > -127 && ch< 0)
- {
- //这里为什么+=3呢
- //因为一个中文占3个字节
- i+=3;
- }
- else
- {
- i++;
- }
- contentLeght++;
- }
- }
- //获取内容的总长度
- int TalkNode::getContentLength()
- {
- return contentLeght;
- }
- //返回所需长度的字符串
- std::string TalkNode::getContentByLength(int length)
- {
- if (length >= contentLeght)
- {
- return getContent();
- }
- int i = 0;
- int index = 0;
- while(index < length)
- {
- char ch = getContent()[i];
- //这里上面说过了
- if (ch > -127 && ch < 0)
- {
- i+=3;
- }
- else
- {
- i++;
- }
- index++;
- }
- //截取strng
- std::string str = content.substr(0, i);
- return str;
- }
有同学会问TiXmlElement是哪来的? to3是用的tinyxml解析xml,度娘可以找的到。
下面看一下to3的读取xml的函数
- std::vector <TalkNode*> talkList;
- void Talking::readXml(const char *filename)
- {
- unsigned long filesize;
- const char *path = CCFileUtils::sharedFileUtils()->fullPathFromRelativePath(filename);
- char *buffer = (char *)CCFileUtils::sharedFileUtils()->getFileData(path, "rb", &filesize);
- if (buffer == NULL)
- {
- return;
- }
- TiXmlDocument doc;
- doc.Parse(buffer);
- TiXmlNode *root = doc.FirstChild("plist");
- if (root)
- {
- TiXmlElement *element = root->ToElement();
- for (TiXmlNode* entityNode = root->FirstChild(); entityNode; entityNode = entityNode->NextSibling())
- {
- TalkNode *node= new TalkNode();
- node->init(entityNode);
- talkList.push_back(node);
- }
- talkCount = talkList.size();
- }
- }
到这里就可以实现打字效果了,但我们还得自动换行,这个cocos2d-x的CCLabelTTF有提供这个API
CCLabelTTF * CCLabelTTF::create(const char *string, const char *fontName, float fontSize, const CCSize& dimensions, CCTextAlignment hAlignment);
string:内容
fontName:字体
fontSize:字号
dimensions:显示框
hAlignment:对齐方式
最后在逻辑循环里更新你的CCLabelTTF字符串就可以了
- void Talking::logic(float cTime)
- {
- TalkNode* node = (TalkNode*)talkList[talkIndex];
- if (wordCount > node->getContentLength())
- {
- return;
- }
- wordCount++;
- CCLabelTTF* label = (CCLabelTTF*)this->getChildByTag(kTalkingLabelTag);
- label->setString(node->getContentByLength(wordCount).c_str());
- }
再加上点击屏幕显示全部内容
- bool Talking::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
- {
- TalkNode* node = (TalkNode*)talkList[talkIndex];
- if (wordCount < node->getContentLength())
- {
- wordCount = node->getContentLength();
- }
- return true;
- }
附上效果图两张