利用Android遊戲引擎Angle開發介面——顯示漢字

NO IMAGE

Angle不支援漢字的顯示,內帶的AngleFont,對E文的支援是沒問題。AngleFont通過把字元變為Bitmap的方式來載入字型檔,準備紋理。對於漢字字型檔,這個過程會耗時很長,全部載入進來,佔用記憶體也很多;如果部分載入、根據使用頻度更新字型檔快取,演算法又太麻煩。

我使用的是笨方法,先使用Android的Canvas,把漢字繪製到記憶體圖片,然後根據圖片生成一個AngleSprite(含配套的AngleSpriteLayout及AngleSpriteLayout關聯的Texture)。下面是轉換漢字為Bitmap的類,支援單行文字繪製,可以根據需要做省略處理。

public final class StringToBitmap {
public static Bitmap getBitmapFromSingleLineString(String text, int textColor, int backgroundColor, String fontType,
int fontSize, int bitmapWidth, int bitmapHeight, Paint.Align align) {
Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight,
Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
// 背景顏色
canvas.drawColor(backgroundColor);
TextPaint paint = new TextPaint();
Typeface typeface = Typeface.create(fontType, Typeface.NORMAL);
// 消除鋸齒
paint.setAntiAlias(true);
// 字型為紅色
paint.setColor(textColor);
paint.setTypeface(typeface);
paint.setTextSize(fontSize);
paint.setTextAlign(align);
CharSequence truncateText = TextUtils.ellipsize(text, paint
, bitmapWidth, TextUtils.TruncateAt.END);
// 繪製字型
canvas.drawText(truncateText, 0, truncateText.length(), 0, bitmapHeight - 1,  paint);
return bitmap;
}
}

僅僅是上面的處理還不夠,生成了一個Bitmap,還需要轉變成紋理。

Angle類庫中的AngleTextureEngine只能從Resouce中載入紋理。第一步,我修改了AngleTextureEngine類,新增了下面的方法以便從已有的Bitmap生成紋理物件。

	public AngleTexture createTextureFromBitmap(Bitmap bitmap)
{
AngleTexture tex = null;
Iterator<AngleTexture> it = mTexturesX.iterator();
while (it.hasNext())
{
tex = it.next();
if (tex instanceof AngleBitmapTexture)
{
// Texture already exists
if (((AngleBitmapTexture) tex).mBitmap == bitmap)
{
tex.mRefernces  ;
return tex;
}
}
}
tex = new AngleBitmapTexture(this, bitmap);
mTexturesX.add(tex);
return tex;
}

第二步,還要修改AngleSpriteLayout類來支援從Bitmap建立紋理,新增下面兩個方法(沒有指定cropWidth和cropHeight,只指定紋理尺寸width和height)。

	public AngleSpriteLayout(AngleSurfaceView view, Bitmap bitmap)
{
doInit(view, 0, 0, bitmap);
}
public AngleSpriteLayout(AngleSurfaceView view, int width, int height, Bitmap bitmap)
{
doInit(view, width, height, bitmap);
}

上面兩個方法呼叫的doInit函式,我參考AngleSpriteLayout類原有的doInit函式做了過載。

第三步,還得實現一個紋理類AngleBitmapTexture。程式碼如下:

public class AngleBitmapTexture extends AngleTexture {
protected Bitmap mBitmap;
public AngleBitmapTexture(AngleTextureEngine textureEngine, Bitmap bmp) {
super(textureEngine);
mBitmap = bmp;
}
@Override
public Bitmap create() {
return mBitmap;
}
void setBitmap(Bitmap bitmap){
mBitmap = bitmap;
mTextureEngine.releaseHWTexture(this);
}
}

好了,準備工作完成了,下面看怎麼使用。其實很簡單,舉個例子:

		long t = System.currentTimeMillis();
AngleObject textHolder = mGLSurfaceView.addObject(new AngleObject());
int x = 120;
int y = 100;
for (int i = 0; i < 30; i  ) {
if (i % 6 == 0) {
y  = 60;
x = 120;
}
AngleSprite textSprite = new AngleSprite(x, y,
new AngleSpriteLayout(mGLSurfaceView, 190, 50,
StringToBitmap.getBitmapFromSingleLineString(
"渲染測試中"   i, 0xFFEEEEEE, 0x00000000, "宋體",
28, 190, 50, Paint.Align.LEFT)));
textHolder.addObject(textSprite);
x  = 200;
}
Log.v("StringBitmap", "create 30 string bitmap, use: "   (System.currentTimeMillis() - t));

OK,到此為止,可以正常顯示漢字了,就是不知道效能如何。我在上面的程式碼中,加了些測試的程式碼,建立耗時還不算太多,在我的裝置上,建立30個字串文理,150毫秒左右。

似乎應該先分析一下Angle引擎的框架,不過程式碼和類都不太多,比較容易理清楚,閱讀程式碼花不了太多時間,等我有時間再補了。這也可能是這個引擎沒有文件的原因之一,作者認為程式碼可以說明大部分東西,不需要。