为了在设备之间使用一致的字体,我使用了位图字体。 即,每个字符由位图表示。
例如,我们可以为字母和数字中的每个字母创建一个图像,并且每当要显示文本时,我们都会在给定位置绘制字符串中的字符图像。
可是等等! 难道不是为每个角色的杀伤力加载图像吗? 是的。 我们可以使用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游戏开发教程简介
- Android游戏开发–游戏创意
- Android游戏开发–创建项目
- Android游戏开发–基本游戏架构
- Android游戏开发–基本游戏循环
- Android游戏开发–使用Android显示图像
- Android游戏开发–在屏幕上移动图像
- Android游戏开发–游戏循环
- Android游戏开发–测量FPS
- Android游戏开发–雪碧动画
- Android游戏开发–粒子爆炸
- Android游戏开发–设计游戏实体–策略模式
- Android游戏开发–从Canvas切换到OpenGL ES
- Android游戏开发–使用OpenGL ES显示图形元素(原语)
- Android游戏开发– OpenGL纹理映射
- Android游戏开发–设计游戏实体–状态模式
- Android游戏文章系列
翻译自: https://www.javacodegeeks.com/2011/09/android-game-development-using-bitmap.html