游戏中除了图像动画,最重要的传递信息的媒介就是文字。除了类似地狱边境那类游戏,大部分都是有文本交互的。
在《权威》第五章中讲到了文本渲染系统,这里主要使用其中的CCLableTTF类。
值得一提的是关于中文显示的问题。在Windows上调试时,中文会显示乱码,这是由于在Windows上中文的编码不符合导致的。解决这个问题参考了前辈提出的方法。(见:http://www.jb51.cc/article/p-mfhqrewo-bea.html)然后在Windows调试中可以显示了。但是后来问题又来了,在打包apk时,发生了故障(返回错误代码:2)经过测试,是由于使用了Windows函数导致的(安卓系统上当然没有Windows的api)。那么在安卓上如何使用?这里参考了另一位前辈的文章(http://www.jb51.cc/article/p-debrnujf-bkt.html)得知在安卓上使用的是UTF8,只需要设置VS的文件格式即可,无需转换。但这样在Windows调试的时候就是乱码,二者不可兼得,除非使用条件编译区分两者,但太麻烦,在学习中没必要,于是后面的例子都是用英文,实际开发中,到安卓上测试可以使用中文。
首先设定一个使用文本的目标:建立一个对话框,可以显示输入的文字(游戏中功能是显示人物对话),且这个对话框可以随时弹出、消除。
思路:
创建一个对话框类,使用单例模式(因为游戏中对话框只有一个),任何一个结点传入自己的指针以调用对话框,对话框具有的功能有:显示、隐藏、添加文字、播放文字、删除文字。
实现类如下:
class cwind{
private:
std::string text;
static cwind *PTR;
CCSprite*wind;
std::vector<CCLabelTTF*> pLabels;
int id;
bool txton;
bool haveparent;
float txtspeed = 1.0;
cwind(){
txton = false;
haveparent = false;
wind = CCSprite::create("wind.png");
//图为960*240 实际操作范围:宽900 高170 分为4行可显示 每行225*42
wind->setAnchorPoint(ccp(0,0));
wind->setPosition(ccp(0,0));
id = 9291;
wind->setTag(id);
}
public:
static cwind*getInstance(){
if(!PTR){
PTR = new cwind();
}
return PTR;
}
void addtext(std::string str){
auto p = CCLabelTTF::create(str,"Arial",34);
p->setHorizontalAlignment(kCCTextAlignmentLeft);//左对齐
p->setAnchorPoint(ccp(0,0));//锚点 左下角
int line = pLabels.size();
p->setPosition(30,170 - line * 40);
pLabels.push_back(p);
}
void playtext(){
if (txton)return;
txton = true;
//auto *to = CCProgressTo::create(txtspeed,100);
for (auto t : pLabels){
wind->addChild(t);
//t->runAction(to);
}
}
void hidetext(){
if(txton = true)
for (auto t : pLabels){
t->setVisible(false);
}
}
void relasetext(){
wind->removeAllChildrenWithCleanup(true);
txton = false;
pLabels.clear();
}
bool showon(CCNode*pnode,int floor = 3){
CCNode* p = pnode->getChildByTag(id);
if (p){
p->setVisible(true);
}
else{
if (haveparent)return false;
haveparent = true;
pnode->addChild(wind,floor);
}
return true;
}
void hide(){
wind->setVisible(false);
}
bool deletefrom(CCNode*pnode){//彻底删去(之后确定很长时间不会再用到或者切换至别的场景要用到)
CCNode* p = pnode->getChildByTag(id);
if (p){
haveparent = false;
pnode->removeChild(p,true);
wind->release();
//此时需要重新创建:
wind = CCSprite::create("wind.png");
wind->setPosition(480,120);
}
else return false;
return true;
}
void set_txtspeed(float spd){
txtspeed = spd;
}
};
关于对话框的消除,每次用隐藏即可,只需要重新渲染文字即可。这样可以减少文件读取次数。文字的位置要根据对话框具体形状来计算,且每一行是有长度限制的(这里并没有给出限制)。
使用该类,效果如下: