Android游戏开发–使用位图字体

Android是一种在具有不同屏幕尺寸的多种类型的设备上运行的操作系统。 因此,在这些平台上解决与字体大小和外观有关的字体相关问题非常困难。
为了在设备之间使用一致的字体,我使用了位图字体。 即,每个字符由位图表示。

例如,我们可以为字母和数字中的每个字母创建一个图像,并且每当要显示文本时,我们都会在给定位置绘制字符串中的字符图像。
可是等等! 难道不是为每个角色的杀伤力加载图像吗? 是的。 我们可以使用android的实用程序来操纵位图,以发挥我们的优势。

我们需要的只是一个位图,其中包含我们要使用的所有字符,并将其切成单独的位图。 为此,我们将使用等宽字体。 等宽字体是指字母和字符占据相同水平空间的字体。 换句话说,字符具有相同的宽度。

一个简单的字符映射可能看起来像这样。

请注意,背景是透明的。
上面的字符图排列在一个网格中。 字符的宽度为8像素。 高度为12像素。 请注意,第二行开始于15像素,因此各行之间存在间隙。 这只是一个选择,也是Photoshop如何打破界限的选择,而我却不愿意更改它们。

上图显示了第一行的开始以及字符如何组织到单元格中。
在此之后,很容易将其切成薄片。 一个简单的迭代就可以解决问题。 为简单起见,我创建了仅包含英文字母,数字和一些标点符号的地图。 您可以根据需要扩展它。 在Photoshop或Gimp或您喜欢的任何图像编辑器中使用等宽字体,然后创建自己的图纸。 这里有很多位图字体可供选择。

我们如何使用呢? 我想在屏幕上显示文本的想法是创建一个drawString方法,该方法将要显示的文本与要显示的位置一起作为参数显示。

这样的事情会做到这一点:

void drawString(Canvas canvas, String text, int x, int y)

我还将画布对象传递到其中,以在上面绘制文本。 这只是为了简单起见。 如果是OpenGL渲染器,我们将不得不使用广告牌(带有纹理的正方形)。 但是出于切片图像和显示字体的目的,让我们坚持使用这种方法。

创建一个使用简单2D画布的简单Android项目。 我们将利用它。
我实现了SurfaceView来保存我的画布,并将其命名为DrawingPanel
在其构造函数中,我只需注册它即可在接触表面并加载资源时接收事件。 资源实际上只是字形/字符的图像。

下载以下图像文件并将其拖到eclipse的projects资源文件夹中: / res / drawable-mdpi for ADP以生成资源的ID。

创建DrawingPanel类。

public class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {

	private Canvas canvas;		// the canvas to draw on
	private Glyphs glyphs;		// the glyphs

	public DrawingPanel(Context context) {
		super(context);
		// adding the panel to handle events
		getHolder().addCallback(this);

		// initialise resources
		loadResources();

		// making the Panel focusable so it can handle events
		setFocusable(true);
	}

	/** Loads the images of the glyphs */
	private void loadResources() {
		this.glyphs = new Glyphs(BitmapFactory.decodeResource(getResources(), R.drawable.glyphs_green));
		Log.d(TAG, "Green glyphs loaded");
	}

我省略了需要实现的其他方法,因为它们只是存根。

canvas变量用于在其上绘制文本,并在每次触摸事件时获取。 您稍后会在onTouchEvent方法中看到。
最有趣的类是Glyphs类,它包含字符与图像的关联。 字形变量在loadResources()方法中实例化。 它使用前面复制的字符表图像调用Glyphs类的构造函数。

查看Glyphs类:

package net.obviam.fonts;

import java.util.HashMap;
import java.util.Map;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.util.Log;

/**
 * @author impaler
 *
 */
public class Glyphs {

	private static final String TAG = Glyphs.class.getSimpleName();
	private Bitmap bitmap;	// bitmap containing the character map/sheet

	// Map to associate a bitmap to each character
	private Map<Character, Bitmap> glyphs = new HashMap<Character, Bitmap>(62);

	private int width;	// width in pixels of one character
	private int height;	// height in pixels of one character

	// the characters in the English alphabet
	private char[] charactersL = new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
			'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
			'u', 'v', 'w', 'x', 'y', 'z' };
	private char[] charactersU = new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G',
			'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
			'U', 'V', 'W', 'X', 'Y', 'Z' };
	private char[] numbers = new char[] { '1', '2', '3', '4', '5', '6', '7',
			'8', '9', '0' };

	public Glyphs(Bitmap bitmap) {
		super();
		this.bitmap = bitmap;
		this.width = 8;
		this.height = 12;
		// Cutting up the glyphs
		// Starting with the first row - lower cases
		for (int i = 0; i < 26; i++) {
			glyphs.put(charactersL[i], Bitmap.createBitmap(bitmap,
					0 + (i * width), 0, width, height));
		}
		Log.d(TAG, "Lowercases initialised");

		// Continuing with the second row - upper cases
		// Note that the row starts at 15px - hardcoded
		for (int i = 0; i < 26; i++) {
			glyphs.put(charactersU[i], Bitmap.createBitmap(bitmap,
					0 + (i * width), 15, width, height));
		}
		// row 3 for numbers
		Log.d(TAG, "Uppercases initialised");
		for (int i = 0; i < 10; i++) {
			glyphs.put(numbers[i], Bitmap.createBitmap(bitmap,
					0 + (i * width), 30, width, height));
		}
		Log.d(TAG, "Numbers initialised");

		// TODO - 4th row for punctuation
	}

	public Bitmap getBitmap() {
		return bitmap;
	}

	/**
	 * Draws the string onto the canvas at <code>x</code> and <code>y</code>
	 * @param text
	 */
	public void drawString(Canvas canvas, String text, int x, int y) {
		if (canvas == null) {
			Log.d(TAG, "Canvas is null");
		}
		for (int i = 0; i < text.length(); i++) {
			Character ch = text.charAt(i);
			if (glyphs.get(ch) != null) {
				canvas.drawBitmap(glyphs.get(ch), x + (i * width), y, null);
			}
		}
	}
}

线

private Map<Character, Bitmap> glyphs = new HashMap<Character, Bitmap>(62);

创建将位图与每个字符相关联的映射。
要加载此代码,我们需要每个字符的位图。 我为具有位图的字符创建了3个数组。 characterL []保留英文字母的小写字母, charactersU []保留大写字母, 数字[]保留数字。 作为练习,请添加标点符号数组,因为该数组不存在。

请注意,字符的顺序与字符表中的顺序相同。
为了方便起见,我为图像的每一行创建了一个数组。 为了使图像与字符相关联,我将遍历它们,并根据索引从工作表中剪切出相应的图像。 字符具有固定的宽度,使所有这些操作变得容易。 仔细检查并了解构造函数。 它进行切片和关联。

drawString(Canvas canvas,String text,int x,int y)方法执行绘图。 它占据绘制位置,遍历传入的文本并逐步绘制每个字符。 由于每个字符具有相同的宽度,因此很容易计算水平偏移量。

这就对了。 要尝试,请将以下方法添加到DrawingPanel中

public boolean onTouchEvent(MotionEvent event) {
	// draw text at touch
	try {
		canvas = getHolder().lockCanvas();
		synchronized (getHolder()) {
			if (event.getAction() == MotionEvent.ACTION_DOWN
					|| event.getAction() == MotionEvent.ACTION_MOVE) {
				// clear the screen
				canvas.drawColor(Color.BLACK);
				// draw glyphs
				glyphs.drawString(canvas, "Drawing string at "
						+ (int) event.getX() + " " + (int) event.getY(),
						(int) event.getX(), (int) event.getY());
			}
			if (event.getAction() == MotionEvent.ACTION_UP) {
				canvas.drawColor(Color.BLACK);
				glyphs.drawString(canvas, "Drawn string at "
						+ (int) event.getX() + " " + (int) event.getY(),
						(int) event.getX(), (int) event.getY());
			}
		}
	} finally {
		if (canvas != null) {
			getHolder().unlockCanvasAndPost(canvas);
		}
	}
	// event was handled
	return true;
}

每次触摸屏幕时,我们都会尝试抓住画布以能够在其上进行绘制。 如果发生触摸或拖动,我们只需清除画布并在其上绘制字符串即可。
当我们停止触摸屏幕时,我们在最后一个位置显示略有不同的文本。
最后,我们释放画布。 确保返回true表示事件已处理。

这就对了。 最后需要做的就是将DrawingPanel设置为我们的视图。 这是在项目创建的活动中完成的。 我也禁用了标题。

public class PrintingActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // turn off title
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(new DrawingPanel(this));
    }
}

生成的应用程序应如下所示:

要使用OpenGL执行此操作,请遵循相同的原理,并将位图用于纹理。 我将在某个时候发布本文的OpenGL版本,敬请期待。

此处下载代码(obviam.bitmapfont.tar.gz)

参考:来自我们“ 反对谷物 ”博客的JCG合作伙伴Tamas Jano 在Android中使用位图字体

不要忘记查看我们的新Android游戏 ArkDroid (以下屏幕截图) 。 您的反馈将大有帮助!
相关文章:

翻译自: https://www.javacodegeeks.com/2011/09/android-game-development-using-bitmap.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值