1:文字在一个聊天框内能够自适应的换行显示。
2:大段的文字逐字符的进行显示。
于是我进行了简单的封装。
首先我们来看中文字符的支持:
FKCommon.h
- #include <iostream>
- #include <cstring>
- #pragma comment( lib, "libiconv.lib" )
- #include "iconv\iconv.h"
- //--------------------------------------------------------------------
- namespace FKStringConvert
- {
- int code_convert( const char* from_charset, const char* to_charset,
- const char* inbuf, size_t inlen, char* outbuf, size_t outlen );
- /* UTF8 - GB2312 */
- std::string u2a( const char* inbuf );
- /* GB2312 - UTF8 */
- std::string a2u( const char* inbuf );
- }
- //--------------------------------------------------------------------
FKCommon.cpp
- //--------------------------------------------------------------------
- namespace FKStringConvert
- {
- //--------------------------------------------------------------------
- int code_convert( const char* from_charset, const char* to_charset, const char* inbuf, size_t inlen, char* outbuf, size_t outlen )
- {
- iconv_t cd;
- const char* temp = inbuf;
- const char** pin = &temp;
- char** pout = &outbuf;
- memset( outbuf, 0, outlen );
- cd = iconv_open( to_charset, from_charset );
- if( cd == 0 ) return -1;
- if( iconv( cd, pin, &inlen, pout, &outlen ) == -1 )
- {
- return -1;
- }
- iconv_close( cd );
- return 0;
- }
- //--------------------------------------------------------------------
- /* UTF8 -> GB2312 */
- std::string u2a( const char* inbuf )
- {
- size_t inlen = strlen( inbuf );
- char* outbuf = new char[inlen * 2 + 2 ];
- std::string strRet;
- if( code_convert("utf-8", "gb2312", inbuf, inlen, outbuf, inlen * 2 + 2 ) == 0 )
- {
- strRet = outbuf;
- }
- delete [] outbuf;
- return strRet;
- }
- //--------------------------------------------------------------------
- /* GB2312 -> UTF8 */
- std::string a2u( const char* inbuf )
- {
- size_t inlen = strlen( inbuf );
- char* outbuf = new char[inlen * 2 + 2];
- std::string strRet;
- if( code_convert("gb2312", "utf-8", inbuf, inlen, outbuf, inlen * 2 + 2 ) == 0 )
- {
- strRet = outbuf;
- }
- delete [] outbuf;
- return strRet;
- }
- //--------------------------------------------------------------------
- }
- //--------------------------------------------------------------------
使用方法如下:
- std::string szInfo = "Test中文";
- std::string szUTF8 = FKStringConvert::a2u(szInfo.c_str());
第二个问题,自适应多行文字
Scene.cpp
- //--------------------------------------------------------------------
- // 自适应换行文字
- /*
- horizontalSpacing: 水平间距
- verticalSpacing: 垂直间距
- lineWidth: 一行的最大宽度
- */
- CCLabelTTF* CXXScene::AutoNewLineText(std::string _string, const char *fontName,
- float fontSize, float horizontalSpacing, float verticalSpacing, float lineWidth, ccColor3B p_fontColor )
- {
- CCArray* labelTTF_arr = CCArray::create();
- int index = 0;
- int index_max = strlen(_string.c_str());
- bool is_end = true;
- // 根据ASCII码找出中英文字符,并创建成一个CCLabelTTF对象存入labelTTF_arr数组中
- while (is_end)
- {
- if (_string[index] >= 0 && _string[index] <= 127)
- {
- std::string englishStr = _string.substr(index,1);
- labelTTF_arr->addObject(CCLabelTTF::create(englishStr.c_str(), fontName, fontSize));
- index+= 1;
- }
- else
- {
- std::string chineseStr =_string.substr(index,3).c_str();
- labelTTF_arr->addObject(CCLabelTTF::create(chineseStr.c_str(), fontName, fontSize));
- index+= 3;
- }
- if (index>=index_max) {
- is_end=false;
- }
- }
- // 在CCLabelTTF对象上添加子对象CCLabelTTF,以此组合成一句话,以左上角第一个字为锚点。。
- CCLabelTTF* returnTTF = (CCLabelTTF*)labelTTF_arr->objectAtIndex(0);
- float nowWidth = returnTTF->getContentSize().width; // 本行的行宽
- CCLabelTTF* BeforeCurTTF = (CCLabelTTF*)labelTTF_arr->objectAtIndex(0);
- CCLabelTTF* CurLineBeginTTF = (CCLabelTTF*)labelTTF_arr->objectAtIndex(0); // 行首最左边的字符
- int arr_count = labelTTF_arr->count();
- for (int i=1; i < arr_count; i++)
- {
- CCLabelTTF* CurTTF = (CCLabelTTF*)labelTTF_arr->objectAtIndex(i);
- CurTTF->setColor( p_fontColor );
- CurTTF->setAnchorPoint(ccp(0, 0.5));
- nowWidth+= CurTTF->getContentSize().width;
- char* pNewLineKey = "\n"; // 该符号换行
- char* pMissKey = "\r"; // 该符号不处理
- // 宽度超长
- if ( nowWidth >= lineWidth )
- {
- CurTTF->setPosition(ccp( ( -nowWidth + CurTTF->getContentSize().width) - BeforeCurTTF->getContentSize().width * 0.5f,
- -BeforeCurTTF->getContentSize().height * 0.5 -verticalSpacing));
- nowWidth = returnTTF->getContentSize().width;
- // 保存行首
- CurLineBeginTTF = CurTTF;
- }
- // 是换行符
- else if( strcmp( CurTTF->getString() , pNewLineKey ) == 0 )
- {
- CurTTF->setPosition(ccp( ( -nowWidth + CurTTF->getContentSize().width) - BeforeCurTTF->getContentSize().width * 0.5f,
- -BeforeCurTTF->getContentSize().height * 0.5 -verticalSpacing));
- nowWidth = returnTTF->getContentSize().width;
- // 保存行首
- CurLineBeginTTF = CurTTF;
- }
- else if( strcmp( CurTTF->getString() , pMissKey ) == 0 )
- {
- continue;
- }
- else
- {
- CurTTF->setPosition(ccp(BeforeCurTTF->getContentSize().width+horizontalSpacing, BeforeCurTTF->getContentSize().height*0.5f));
- }
- CurTTF->setTag( 0 );
- BeforeCurTTF->addChild(CurTTF);
- BeforeCurTTF = CurTTF;
- }
- return returnTTF;
- }
- //--------------------------------------------------------------------
使用方式如下:
- std::string szInfo = "测试多行自动换行,这里随便改 by FreeKnight";
- CCLabelTTF* pHeadTTF = AutoNewLineText( FKStringConvert::a2u(szInfo.c_str()), "Arial", 24, 1, 10, 200, ccc3( 255, 255, 255 ) );
- pHeadTTF->setColor( ccc3( 255, 255, 255 ) );
- pHeadTTF->setPosition( CENTER_POS );
- this->addChild( pHeadTTF );
然后是逐字符显示功能,仅仅改动一下调用处即可,代码如下
- std::string szInfo = "测试多行自动换行,这里随便改 by FreeKnight";
- // 逐字显示
- CCLabelTTF* pHeadTTF = AutoNewLineText( FKStringConvert::a2u(szInfo.c_str()), "Arial", 24, 1, 10, 200, ccc3( 255, 255, 255 ) );
- pHeadTTF->setColor( ccc3( 255, 255, 255 ) );
- pHeadTTF->setPosition( CENTER_POS + ccp( -240, -70 ) );
- CCArray* pTTFList = pHeadTTF->getChildren();
- CCObject* pObject = NULL;
- CCLabelTTF* pChild = NULL;
- int nIndex = 1;
- CCARRAY_FOREACH( pTTFList, pObject )
- {
- pChild = (CCLabelTTF*)pObject;
- if( pChild == NULL )
- break;
- for( ; ; )
- {
- if( pChild == NULL )
- break;
- pChild->setVisible( false );
- CCDelayTime* pAction = CCDelayTime::create( 0.05f * nIndex );
- CCCallFuncN* pDone = CCCallFuncN::create( this, callfuncN_selector(CSecen::TTFItemDelayOver) );
- CCSequence* pSeq = CCSequence::create( pAction, pDone, NULL );
- pChild->runAction( pSeq );
- nIndex++;
- pChild = (CCLabelTTF*)pChild->getChildByTag( 0 );
- }
- }
- this->addChild( pHeadTTF );
注意,里面有个CSecen::TTFItemDelayOver的回调函数,这个函数代码如下:
- // 文字延迟回调
- void CScene::TTFItemDelayOver( CCNode* pSender )
- {
- if( pSender )
- pSender->setVisible( true );
- }
这样就可以了。
代码简单明确,故不做过多说明。如有不清楚理解的部分,可留言说明问题,我尽力解答。同时,因为要支持中文,所以使用了效率低下的CCLabelTTF,若有什么更好的建议,欢迎交流指出,谢谢。
cocos2d-html5的中文支持是默认的,label换行貌似也和C++版的行为不太一样。
回复删除我的卡牌桌游客户端目前是用cocos2d-html5在写。可以在运行途中调出js控制台直接敲命令修改程序是超惊艳的便利功能
souga,我使用的还是cocos2dx,我依然轻度质疑Html5的性能问题。话说,我这个FKCocos2dxWrapper增加了自定义解释脚本,部分功能也可以利用重加载的方式直接运行时热更新~嘿嘿
删除