Чтобы использовать согласованные шрифты на разных устройствах, я использовал растровые шрифты. То есть каждый символ представлен растровым изображением.
Например, мы можем создать изображение для каждой буквы в алфавите и цифре, и всякий раз, когда мы хотим отобразить текст, мы рисуем изображения символов из строки в заданной позиции.
Но ждать! Не загружается ли изображение для каждого персонажа излишним? Да, это. Мы можем использовать утилиты Android для управления растровыми изображениями в наших интересах.
Все, что нам нужно, это растровое изображение, содержащее все символы, которые мы хотим использовать, и разделить его на отдельные растровые изображения. Чтобы сделать это простым способом, мы будем использовать моноширинный шрифт. Моноширинный шрифт — это шрифт, буквы и символы которого занимают одинаковое горизонтальное пространство. Другими словами, символы имеют одинаковую ширину.
Простая карта персонажей может выглядеть следующим образом.
Обратите внимание, что фон прозрачен.
Приведенная выше карта символов организована в виде сетки. Ширина символа составляет 8 пикселей. Высота 12 пикселей. Обратите внимание, что вторая строка начинается с 15 пикселей, поэтому между строками есть промежуток. Это просто выбор, а также то, как Photoshop нарушил границы, и я не стал их менять.
На изображении выше показано начало первого ряда и то, как символы организованы в ячейки.
После этого его легко нарезать. Простая итерация сделает свое дело. Для простоты я создал карту только из английского алфавита, цифр и нескольких знаков препинания. Вы можете расширить его, как хотите. Используйте моноширинный шрифт в Photoshop, Gimp или любом другом редакторе изображений, который вам нравится, и создайте свой собственный лист.
Вот множество растровых шрифтов на выбор.
Как мы можем использовать это? Моя идея отобразить текст на экране — создать метод drawString, который принимает текст для отображения в качестве параметра вместе с позицией, в которой мы хотим его отобразить.
Что-то вроде этого сделает это:
1
|
void drawString(Canvas canvas, String text, int x, int y) |
Я также передаю объект canvas , на котором я хочу нарисовать текст. Это просто для простоты. В случае рендерера OpenGL нам придется использовать рекламные щиты (квадраты с текстурами). Но для нарезки изображений и отображения шрифтов давайте придерживаться этого подхода.
Создайте простой проект Android, который использует простой 2D-холст. Мы будем опираться на это.
Я реализовал SurfaceView для хранения холста и назвал его DrawingPanel .
В его конструкторе я просто регистрирую его, чтобы получать события при касании поверхности и загружать ресурсы. Ресурсы на самом деле просто изображения глифов / символов.
Загрузите следующий файл изображения и перетащите его в папку ресурсов проектов eclipse по адресу : / res / drawable-mdpi для ADP, чтобы сгенерировать идентификатор для ресурса.
Создайте класс DrawingPanel .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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, который содержит ассоциацию символов с изображениями. Переменная glyphs создается в методе loadResources () . Он вызывает конструктор класса Glyphs с ранее скопированным изображением листа персонажа.
Проверьте класс Glyphs :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
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 ); } } } } |
Линия
1
|
private Map<Character, Bitmap> glyphs = new HashMap<Character, Bitmap>( 62 ); |
создает карту, которая связывает растровое изображение с каждым символом.
Чтобы загрузить это нам нужны растровые изображения для каждого символа. Я создал 3 массива для персонажей, для которых у меня есть растровые изображения.
символы L [] содержат строчные буквы английского алфавита, символы U [] буквы верхнего регистра и цифры [] содержат цифры. В качестве упражнения добавьте массив знаков препинания, так как этот отсутствует.
Обратите внимание, что порядок символов такой же, как и в таблице символов.
Для удобства я создал массив для каждой строки из изображения. Чтобы связать изображения с символами, я буду проходить через них и вырезать соответствующее изображение из листа на основе индекса. Имея фиксированную ширину для персонажей, все это просто. Внимательно изучите и поймите конструктор. Это делает нарезку и ассоциацию.
Метод drawString (Canvas canvas, String text, int x, int y) выполняет рисование. Он занимает позицию для рисования, просматривает переданный текст и постепенно рисует каждый символ. Горизонтальное смещение легко рассчитать, поскольку каждый символ имеет одинаковую ширину.
Вот и все. Чтобы попробовать это, добавьте следующий метод в DrawingPanel :
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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 в качестве нашего представления. Это сделано в деятельности, созданной с проектом. Я также отключил заголовок.
01
02
03
04
05
06
07
08
09
10
|
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) .
Справка: Использование растровых шрифтов в Android от нашего партнера по JCG Тамаса Яно из блога « Против зерна ».
- Введение в разработку игр для Android Введение
- Разработка игр для Android — Идея игры
- Разработка игр для Android — Создать проект
- Разработка игр для Android — базовая игровая архитектура
- Разработка игр для Android — основной игровой цикл
- Разработка игр для Android — Отображение изображений с Android
- Разработка игр для Android — перемещение изображений на экране
- Разработка игр для Android — The Game Loop
- Разработка игр для Android — Измерение FPS
- Разработка игр для Android — Sprite Animation
- Разработка игр для Android — Particle Explosion
- Разработка игр для Android — Дизайн игровых объектов — Стратегия
- Разработка игр для Android — переход с Canvas на OpenGL ES
- Разработка игр для Android — отображение графических элементов (примитивов) с помощью OpenGL ES
- Разработка игр для Android — OpenGL Texture Mapping
- Разработка игр для Android — Дизайн игровых сущностей — Государственный паттерн
- Серия игр для Android