原地址:http://www.cppblog.com/wc250en007/archive/2012/10/15/193320.html

在使用cocos2d-x发布Android平台游戏时,游戏中可能需要显示中文字体, 或者想显示漂亮的自定义字体,这怎么办呢?
cocos2d-x中字体标签提供了CCLabelAtlas, CCLabelBMFont CCLabelTTF

1.CCLabelAtlas速度快,支持简单有限的几个字符或数字集合

2.CCLabelBMFont 
我们可以用CCLabelBMFont来加载字体编辑器生成的.plist文件,但是当显示的文字很多时,这种做法就有点费时费力了
如:我们想显示游戏中剧情介绍

3.CCLabelTTF
支持选择一种字体来显示文字,但是只支持系统中默认字体
CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
 

问题:我们在Android游戏中想显示游戏剧情,想用自己指定的一种字体gril.ttf(非系统默认字体),怎么办

其实cocos2d-x已经提供了帮我们实现了
构造CCLabelTTF中指定的字体名传给了 CCTexture2D 
void CCLabelTTF::updateTexture()
{
    CCTexture2D *tex;
     if (m_tDimensions.width == 0 || m_tDimensions.height == 0)
    {
        tex =  new CCTexture2D();
        tex->initWithString(m_string.c_str(),  m_pFontName->c_str(), m_fFontSize * CC_CONTENT_SCALE_FACTOR()) ;
    }
     else
    {
        tex =  new CCTexture2D();
        tex->initWithString(m_string.c_str(),
                            CC_SIZE_POINTS_TO_PIXELS(m_tDimensions), 
                            m_hAlignment,
                            m_vAlignment,
                            m_pFontName->c_str(),
                            m_fFontSize * CC_CONTENT_SCALE_FACTOR());
    }

    .
}
CCTexture2D又将字体名传给了CCImage
(PS:这里调用的是android平台下的CCImage类(./platform/android/CCImage.h)
而不是win32平台下的CCImage类(./platform/win32/CCImage.h) )

android平台下的CCImage
bool CCImage::initWithString(
                                const  char *    pText, 
                                int             nWidth /*  = 0 */
                                int             nHeight /*  = 0 */,
                               ETextAlign      eAlignMask /*  = kAlignCenter */,
                                const  char *    pFontName /*  = nil */,
                                int             nSize /*  = 0 */)
{
     bool bRet =  false;

     do 
    {
        CC_BREAK_IF(! pText);
        
         BitmapDC &dc = sharedBitmapDC();

        CC_BREAK_IF(! dc.getBitmapFromJava(pText, nWidth, nHeight, eAlignMask,  pFontName, nSize));

         //  assign the dc.m_pData to m_pData in order to save time
        m_pData = dc.m_pData;
        CC_BREAK_IF(! m_pData);

        m_nWidth    = ( short)dc.m_nWidth;
        m_nHeight   = ( short)dc.m_nHeight;
        m_bHasAlpha =  true;
        m_bPreMulti =  true;
        m_nBitsPerComponent = 8;

        bRet =  true;
    }  while (0);

     return bRet;
}

然后调用了android平台下的BitmapDC
     bool getBitmapFromJava( const  char *text,  int nWidth,  int nHeight, CCImage::ETextAlign eAlignMask,  const  char * pFontName,  float fontSize)
    {
        JniMethodInfo methodInfo;
         if (! JniHelper::getStaticMethodInfo(methodInfo, " org/cocos2dx/lib/Cocos2dxBitmap", " createTextBitmap", 
            "(Ljava/lang/String;Ljava/lang/String;IIII)V"))
        {
            CCLOG("%s %d: error to get methodInfo", __FILE__, __LINE__);
             return  false;
        }

        
}

这里显示了调用JAVA代码 Cocos2dxBitmap.java 下的 createTextBitmap 函数

     /*
     * @width: the width to draw, it can be 0
     * @height: the height to draw, it can be 0
     
*/
     public  static  void createTextBitmap(String content, String fontName, 
             int fontSize,  int alignment,  int width,  int height){
        
        content = refactorString(content);       
        Paint paint =  newPaint( fontName, fontSize, alignment);
        
        TextProperty textProperty = computeTextProperty(content, paint, width, height);          

         int bitmapTotalHeight = (height == 0 ? textProperty.totalHeight:height);

         //  Draw text to bitmap
        Bitmap bitmap = Bitmap.createBitmap(textProperty.maxWidth, 
                bitmapTotalHeight, Bitmap.Config.ARGB_8888);
        Canvas canvas =  new Canvas(bitmap);
        
         //  Draw string
        FontMetricsInt fm = paint.getFontMetricsInt();
         int x = 0;
         int y = computeY(fm, height, textProperty.totalHeight, alignment);
        String[] lines = textProperty.lines;
         for (String line : lines){
            x = computeX(paint, line, textProperty.maxWidth, alignment);
            canvas.drawText(line, x, y, paint);
            y += textProperty.heightPerLine;
        }
        
        initNativeObject(bitmap);
    }

newPaint 函数中调用了字体加载
private  static Paint newPaint(String fontName,  int fontSize,  int alignment){
        Paint paint =  new Paint();
        paint.setColor(Color.WHITE);
        paint.setTextSize(fontSize);      
        paint.setAntiAlias( true);    
        
         /*
         * Set type face for paint, now it support .ttf file.
         
*/
         if (fontName.endsWith( ".ttf")){       // 字体需要.ttf结束
              try {
                 // Typeface typeFace = Typeface.createFromAsset(context.getAssets(), fontName);
                  Typeface typeFace = Cocos2dxTypefaces.get(context, fontName);
                   paint.setTypeface(typeFace);
             }  catch (Exception e){
                 Log.e("Cocos2dxBitmap", 
                     "error to create ttf type face: " + fontName);
                 
                  /*
                  * The file may not find, use system font
                  
*/
                 paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
             }
        }
         else {
            paint.setTypeface(Typeface.create(fontName, Typeface.NORMAL));
        }
        
        .......
        
         return paint;
    }
(PS:Typeface类定义字体和字体内在的类型。这个类被用在画笔Paint设置的时候,比如用textSize,textSkewX和textScale设置来指定text在画的时候如何来显示和测量。
android中用Typeface来指定字体)

另一点需要注意的是:字体需要.ttf结束

使用方法
1.在proj.android\assets文件夹中添加 girl.ttf
2.程序中调用对应的字体就可以了
    CCSize size = CCDirector::sharedDirector()->getWinSize();
    CCLabelTTF* label = CCLabelTTF::create("少女HelloWorld", " girl.ttf", 24);
    label->setPosition(ccp(size.width/2, size.height/2));
    addChild(label);
3.如果你需要显示汉字,则需要将包含有字符串的文件(如.cpp)转换为UTF-8格式编码,否则会显示乱码

IOS和win32平台没有测试,相信的差不多

附上测试图片:




哈哈 可以在游戏中打包自己想要的字体啦