首页 > 代码库 > Cocos2d-x显示中文与字幕滚动--之游戏开发《赵云要格斗》(14)

Cocos2d-x显示中文与字幕滚动--之游戏开发《赵云要格斗》(14)

    这里是林炳文Evankaka的博客,欢迎大家前来讨论与交流~~~~~~

    转载请注明出处http://blog.csdn.net/evankaka
    本文将要解决Cocos2d-x中显示中文时出现乱码的情形,并且实现一个字幕滚动的功能,这个功能是通过遮罩来实现的。

      cocos2d-x版本:2.2.5

    工程环境:windows7+VS2010

    打开方式:将工程放在cocos2d-x安装目录下的project文件夹下用VS打开

先来看看效果:

技术分享

       在windows环境下使用visual studio开发cocos2d-x,由于visual studio 默认编码为GBK格式,而cocos2d-x引擎默认编码为UTF-8如果有用到中文,在游戏运行时有可能会出现乱码的情况,这个问题一般有三种解决方案,如下

    (1)将源码文件保存为utf-8格式(不建议,治标不治本)

    (2)自己编写编码转换代码,在用到中文的地方手动转换

    (3)将显示文本单独保存为文本文件(该文件编码为utf-8),由系统统一模块管理文本读取显示,建议使用这种方式,便于后期系统维护,并实现国际化。(这里没写了)

 第一种方式很简单就不不介绍了,下面将对第2种进行介绍。第3种还没写好。

一、自己编写编码转换代码,在用到中文的地方手动转换。

   cocos2d-x的开发包内置了用于编码转换的iconv库,头文件"iconv.h"。iconv命令可以将一种已知的字符集文件转换成另一种已知的字符集文件。它的作用是在多种国际编码格式之间进行文本内码的转换。

1、 直接把代码写进要用到的地方

  如果是只能到一次的话,推荐可以这么做。

(1)首先,新建一个工程,然后在HelloWorldScene.cpp中添加头文件#include"iconv/iconv.h"/

(2)然后在HelloWorldScene.cpp添加全局函数(记得要把它们放在所有函数的最上头,要不就是最上头再定义函数一下)

bool IConvConvert(const char *from_charset, const char *to_charset, const char *inbuf, int inlen, char *outbuf, int outlen)
{
	iconv_t cd = iconv_open(to_charset, from_charset);
	if (cd == 0) return false;
	const char **pin = &inbuf;
	char **pout = &outbuf;
	memset(outbuf,0,outlen);
	size_t ret = iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
	iconv_close(cd);
	return ret == (size_t)(-1) ? false : true;

}
std::string IConvConvert_GBKToUTF8(const std::string& str)
{
	const char* textIn = str.c_str();
	char textOut[256];
	bool ret = IConvConvert("gb2312", "utf-8", textIn, strlen(textIn),textOut, 256);
	return ret ? std::string(textOut) : std::string();
}

运行之后报错:

error LNK2019:无法解析的外部符号 _libiconv_close

error LNK2019:无法解析的外部符号 _libiconv

error LNK2019:无法解析的外部符号 _libiconv_open

 fatal error LNK1120: 3个无法解析的外部命令

解决方法:因为你没有加libiconv.lib文件 

工程属性 ->配置属性 ->链接器->输入->附加依赖项添加libiconv.lib

如下:

技术分享

 (3)用法:

在用到的地方,我这里是在init()里添加

	std::string str =IConvConvert_GBKToUTF8("我是林炳文Evankaka~~\n欢迎来到我的世界~~~");
	CCLabelTTF* pLabel = CCLabelTTF::create(str.c_str(), "Arial", 24);
	pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
		origin.y + visibleSize.height - pLabel->getContentSize().height));
	this->addChild(pLabel, 1);

(4)效果:

技术分享

2、单独一个文字转换文件 

    单独保存为 .h头文件,在使用到编码转换的cpp文件include即可。如果要经常用到的话,建议用这种方法

记得工程属性 ->配置属性 ->链接器->输入->附加依赖项添加libiconv.lib

(1)在class文件夹下新建一个名为ChineseString.h的文件,并把它加到工程来。

#ifndef __ChineseString_H__  
#define __ChineseString_H__  
#include "iconv/iconv.h"//重点记得加上去
static char g_GBKConvUTF8Buf[5000] = {0};
class ChineseString
{
public:
	static const char* GBKToUTF8(const char *strChar)//将字符串转成UFT-8
	
		iconv_t iconvH;
		iconvH = iconv_open("utf-8","gb2312");
		if (iconvH == 0)
		{
			return NULL;
		}
		size_t strLength = strlen(strChar);
		size_t outLength = strLength*4;
		size_t copyLength = outLength;
		memset(g_GBKConvUTF8Buf, 0, 5000);

		char* outbuf = (char*) malloc(outLength);
		char* pBuff = outbuf;
		memset(outbuf, 0, outLength);

		if (-1 == iconv(iconvH, &strChar, &strLength, &outbuf, &outLength))
		{
			iconv_close(iconvH);
			return NULL;
		}
		memcpy(g_GBKConvUTF8Buf,pBuff,copyLength);
		free(pBuff);
		iconv_close(iconvH);
		return g_GBKConvUTF8Buf;
	}
};
#endif  
(2)使用方法:

在要用到的地方先添加头文件ChineseString.h(记得加!)

然后是

	CCLabelTTF* pLabel=CCLabelTTF::create(ChineseString::GBKToUTF8("<span style="font-family: Arial, Helvetica, sans-serif;">我是林炳文Evankaka~~\n欢迎来到我的世界~~~</span>"), "Arial", 24);
<pre name="code" class="cpp">        pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
		origin.y + visibleSize.height - pLabel->getContentSize().height));
	this->addChild(pLabel, 1);

(3)效果

技术分享

二、字幕滚动

    字幕滚动应该是要在一个范围内可见的,出了这个范围就不可见了,这里实现其实很简单,就是通过CCClippingNode来实现的.CCClipingNode是一个可裁剪节点,简单理解:

(1)首先它是一个节点,继承于CCNode,所以它可以像普通节点一样放入CCLayer,CCScene,CCNode中。

(2)作为节点,它就可以用作容器,承载其他节点和精灵。我把它叫底板。

(3)如果想要对一个节点进行裁剪,那需要给出裁剪的部分,这个裁剪区域,我把它叫模版。

所以CCClipingNode裁剪节点在组成上=底板+模版,而在显示上=底板-模版。不知道这样解释会不会好理解一点。

技术分享

这里直接建了一个类,将上面新建的中文转换头文件 用了进来,这是头文件 GameString.h

#ifndef __GameString_SCENE_H__
#define __GameString_SCENE_H__
#include "cocos2d.h"
#include "cocos-ext.h"
#include "ChineseString.h"
#include "HelloWorldScene.h"//这是游戏界面的头文件
USING_NS_CC;
USING_NS_CC_EXT;
class GameString : public cocos2d::CCLayer
{
public:
    virtual bool init();  
    static cocos2d::CCScene* scene();
    CREATE_FUNC(GameString);
	//字幕滚动完成后调用
	void RollEnd();
	//跳过按钮的事件
	void menuCloseCallback(CCObject* pSender);
};

#endif // __GameString_SCENE_H__

这是实现文件 GameString.cpp

#include "GameString.h"
CCScene* GameString::scene()
{
    CCScene *scene = CCScene::create();
    GameString *layer = GameString::create();
    scene->addChild(layer);
    return scene;
}
bool GameString::init()
{
    if ( !CCLayer::init() )
    {
        return false;
    }
    
    CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
    CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
	//加个按钮
	CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
		"exct.png",
		"exct.png",
		this,
		menu_selector(GameString::menuCloseCallback));

	pCloseItem->setPosition(ccp( visibleSize.width -80 ,visibleSize.height-60));
	CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
	pMenu->setPosition(CCPointZero);
	this->addChild(pMenu, 1);


  //加背景
    CCSprite* pSprite = CCSprite::create("enter.png");
    pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
    this->addChild(pSprite, 0);


	//创建要显示的文字
	CCLabelTTF* pLabel=CCLabelTTF::create(ChineseString::GBKToUTF8("我是林炳文Evankaka~~\n这是游戏《赵云要格斗》\n欢迎来到我的世界~~~\n我是林炳文Evankaka~~\n这是游戏《赵云要格斗》\n欢迎来到我的世界~~~\n我是林炳文Evankaka~~\n这是游戏《赵云要格斗》"),"Arial",25);
	pLabel->setAnchorPoint(CCPointZero);
	ccColor3B color = ccc3(255,255,0);
	pLabel->setColor(color);
	pLabel->setPosition(ccp(50, -200));//Y轴注意为负,X轴对应下面的point[4]的50,让他们对齐

	//绘制裁剪区域
	CCDrawNode* shap = CCDrawNode::create();
	CCPoint point[4] = {ccp(50,0), ccp(400,0), ccp(400,200), ccp(50,200)};//可以根据文字适当修改下大小
	shap->drawPolygon(point,4,ccc4f(255,255,255,255),0, ccc4f(255,255,255,255));//绘制四边形


	////创建遮罩
	CCClippingNode* pClip = CCClippingNode::create();
	pClip->setInverted(false);
	pClip->setStencil(shap);//一定要有,要不会报错
	pClip->addChild(pLabel);
	this->addChild(pClip);
	
	//开始让字幕滚动啦
	CCMoveBy* moveact=CCMoveBy::create(10.0f,CCPointMake(0,400));//10秒向上移动400
	CCCallFunc* callFunc=CCCallFunc::create(this,callfunc_selector(GameString::RollEnd));//创建回调动作,文字飘动完后
	CCActionInterval* act=CCSequence::create(moveact,callFunc,NULL);//创建连续动作
	pLabel->runAction(act);

    return true;
}

void GameString::RollEnd()
{
CCDirector::sharedDirector()->replaceScene(HelloWorld::scene());//进入游戏主界面
}

void GameString::menuCloseCallback(CCObject* pSender)
{
	RollEnd();//点击跳过直接进入游戏主界面
}

效果:

(1)字幕滚动完成后进入游戏主界面

技术分享

(2)点击跳过直接进入游戏主界面

技术分享




Cocos2d-x显示中文与字幕滚动--之游戏开发《赵云要格斗》(14)