遊戲中開發不同于一般應用程式的開發,它更注重于界面美觀,我們需要在遊戲界面設計中花費大量的時間以便使它看起來更炫、更酷,當然這其中就少不了遊戲中的字元文本,那麼如何制作出漂亮的遊戲文本呢?今天我們就一起來看一下。
在xna中2d文本的繪制方式種類比較多,這有助于我們制作出更美觀的文本效果,下面我就逐一來看一下。
一、spritefont
這種方式在xna遊戲開發中應該算是最基本的一種形式,使用方法就是在遊戲對應的content項目中添加spritefont檔案(右鍵add—new item—sprite font)。之後你會看到生成了一個xml格式的檔案:
view code
在這個檔案中定義了你使用的字型類型、字型大小、字元間距等資訊。值得一提的是上面的字型區間,它的意思是指你在遊戲中使用的的字元範圍,從上面的值可以看出是ascii的32-126,具體對應字元如下:
ascii碼
字元
32
[空格]
33
!
34
"
35
#
36
$
37
%
38
&
39
'
40
(
41
)
42
*
43
+
44
,
45
-
46
.
47
/
48
49
1
50
2
51
3
52
4
53
5
54
6
55
7
56
8
57
9
58
:
59
;
60
<
61
=
62
>
63
?
64
@
65
a
66
b
67
c
68
d
69
e
70
f
71
g
72
h
73
i
74
j
75
k
76
l
77
m
78
n
79
o
80
p
81
q
82
r
83
s
84
t
85
u
86
v
87
w
88
x
89
y
90
z
91
[
92
\
93
]
94
^
95
_
96
`
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
{
124
|
125
}
126
~
當然它幾乎涵蓋了所有常用英文字元。之是以要定義這個區間主要是為了減少遊戲資源,畢竟在一個遊戲中并不是所有的字元我們都要用到。到這裡可能會有朋友問,既然如此我要是使用中文怎麼辦,這個區間肯定不夠啊,中文有兩萬多個字元,定義這個區間的意義也不大啊?
事實上我們如果需要用到中文字元的話一般并不是修改這個區間(當然修改它是可以做到的,但是占用資源十分大,畢竟字元太過了),而是通過font description processor來處理。具體做法就是:準備一個txt檔案,其中存放我們遊戲中要用到的中文字元,例如我們建立一個fontdescription.txt檔案,裡面寫上"中文字型"四個字存放到遊戲的content項目中;接着在解決方案中添加一個content pipeline extension library(4.0)類型的項目,然後編寫一個類繼承于fontdescriptionprocesor,重寫process方法。在這個方法中我們讀取外部的一個txt檔案,當然你也可以直接寫到代碼中或存儲到其他位置,然後将txt檔案中的字元(當然我們這裡是中文字元了)讀取到fontdescription中,具體代碼如下:
using system;
using system.collections.generic;
using system.linq;
using microsoft.xna.framework;
using microsoft.xna.framework.graphics;
using microsoft.xna.framework.content.pipeline;
using microsoft.xna.framework.content.pipeline.graphics;
using microsoft.xna.framework.content.pipeline.processors;
using system.io;
using system.text;
using system.componentmodel;
namespace contentpipelineextensiondemo
[contentprocessor(displayname = "contentpipelineextensiondemo.mycontentprocessor")]//這個名字将用于spritefont的content processor屬性
public class mycontentprocessor : fontdescriptionprocessor
private string fdescription = @"../xnagamefontcontent/fonts/fontdescription.txt";//注意這裡的路徑,因為fontdescription.txt檔案在xnagamefontcontent項目的fonts檔案夾中
public override spritefontcontent process(fontdescription input, contentprocessorcontext context)
string path = path.getfullpath(fdescription);
context.adddependency(path);
string content = file.readalltext(path,encoding.utf8);//fontdescription.txt檔案必須儲存成utf-8格式,此處也需使用utf-8讀取
foreach (char c in content)//讀取檔案中字元,存放到fontdescription中
input.characters.add(c);
return base.process(input, context);
做完上面兩步之後,此時檔案目錄結構如圖:
這裡需要注意兩點:fontdescription.txt檔案必須儲存成utf-8;由于檔案在content項目中預設xnagamefontcontent中的檔案都需要進行編譯,編譯時會自動檢測裡面的檔案類型,而txt檔案不屬于這其中任何類型,是以我們需要修改它的buildaction屬性為none。接下來我們在xnagamefontcontent下面中添加對contentpipelineextensiondemo生成的dll檔案的引用,然後在xnagamefontcontent項目上右鍵選擇project dependencies,彈出如下圖視窗:
在project項中選擇xnagamefont,depends on中勾選contentpipelineextensiondemo,确定,以此添加遊戲項目對内容管道擴充的依賴(這樣一來就可以修改spritefont檔案的processor為我們自定義的擴充内容)。最後我們在xnagamefontcontent項目中添加spritefontforchinese.spritefont檔案(上面txt中隻是定義了中文字元的範圍,在這裡可以指定字型類型、字型大小等資訊),檔案内容如下:
<?xml version="1.0" encoding="utf-8"?>
<xnacontent xmlns:graphics="microsoft.xna.framework.content.pipeline.graphics">
<asset type="graphics:fontdescription">
<fontname>華文行楷</fontname>
<size>30</size>
<spacing>0</spacing>
<usekerning>true</usekerning>
<style>regular</style>
<characterregions>
<characterregion>
<start> </start>
<end>~</end>
</characterregion>
</characterregions>
</asset>
</xnacontent>
修改檔案的content processor屬性為我們自定義的contentpipelineextensiondemo.mycontentprocessor(這就是上面添加依賴關系的原因),然後我們就可以在遊戲中使用我們文本中的中文漢字了。具體使用時的代碼如下:
using microsoft.xna.framework.audio;
using microsoft.xna.framework.content;
using microsoft.xna.framework.gamerservices;
using microsoft.xna.framework.input;
using microsoft.xna.framework.input.touch;
using microsoft.xna.framework.media;
namespace xnagamefont
public class mygame : microsoft.xna.framework.game
graphicsdevicemanager graphics;
spritebatch spritebatch;
spritefont sf1;//spritefont文本
vector2 sfposition;//spritfont文本所在位置
spritefont sfchinese;//spritefont中文文本
vector2 sfchineseposition;//spritefont中文文本的顯示位置
public mygame()
graphics = new graphicsdevicemanager(this);
content.rootdirectory = "content";
graphics.preferredbackbufferwidth = 480;
graphics.preferredbackbufferheight = 800;
targetelapsedtime = timespan.fromticks(333333);
protected override void initialize()
sfposition = new vector2(130,200);
sfchineseposition = new vector2(160, 400);
base.initialize();
protected override void loadcontent()
spritebatch = new spritebatch(graphicsdevice);
sf1 = content.load<spritefont>(@"fonts/spritefont");
sfchinese = content.load<spritefont>(@"fonts/spritefontforchinese");
protected override void unloadcontent()
protected override void update(gametime gametime)
if (gamepad.getstate(playerindex.one).buttons.back == buttonstate.pressed)
this.exit();
base.update(gametime);
protected override void draw(gametime gametime)
graphicsdevice.clear(color.cornflowerblue);
spritebatch.begin();
spritebatch.drawstring(sf1, "spritefont", sfposition, color.white);
spritebatch.drawstring(sfchinese, "中文字型", sfchineseposition, color.red);
spritebatch.end();
base.draw(gametime);
運作效果如圖:
二、spritefonttexture
由于spritefont文本對于顯示效果的調整很有限,是以xna又對其進行了擴充。spritefonttexture事實上是以圖檔來作為xna的字元集,我們實作隻要制作好相關字元的圖檔,然後像使用spritefont一樣使用就可以了。當然使用起來很簡單,主要問題就是如何來制作圖檔字庫了。這個不用擔心,很多牛人早已經想過這類問題了,下面我們看幾種這類工具:
2.1 ttf2bmp
我們将需要的字元編碼範圍确定下來,在min char中輸入最小字元編碼,在max char中輸入最大字元編碼,然後點選export就可以生成類似于下面的圖檔:
将上圖添加到xnagamefontcontent下面的fonts檔案夾中,接下來就可以寫代碼使用了,當然這時我們的字元圖檔在xnagamefontcontent下面中預設的是textrue圖檔類型,還需要修改圖檔的processor屬性為sprite font texture - xna framework。具體使用代碼如下:
spritefont sftexture;//sprite font texture文本(ttf2bmp制作)
vector2 sftextureposition;//sprite font texture文本位置
sftextureposition = new vector2(60, 350);
sftexture = content.load<spritefont>(@"fonts/spritefonttexture");
spritebatch.drawstring(sftexture, "sprite font texture", sftextureposition, color.yellow);
2.2 spritefont2
使用這個工具我們制作下面一張sprite font texture圖檔:
然後添加到xnagamefontcontent項目的fonts檔案夾,當然别忘了修改片的processor屬性為sprite font texture - xna framework。然後再就可以在程式中使用我們制作的字型:
spritefont sftextureextend;//sprite font texture文本效果擴充(spritefont2制作)
vector2 sftextureextendposition;//sprite font texture extend文本位置
sftextureextendposition = new vector2(100, 330);
sftextureextend = content.load<spritefont>(@"fonts/spritefonttexture2");
spritebatch.drawstring(sftextureextend, "sft 2", sftextureextendposition, color.white);
運作效果:
2.3 xna bitmap font plus
!"#$%&'()*+,-./
0123456789:;<=>?
@abcdefghijklmno
pqrstuvwxyz[\]^_
`abcdefghijklmno
pqrstuvwxyz{|}~
然後調整字元的樣式,修改字元間距:
接着 ctrl+c複制,此時字元資訊複制到了剪貼闆,打開xna bitmap font plus,它會自動加載剪貼闆的内容,如下圖:
當然此時我們需要調整字元行數、偏移量和間隔等資訊,點選generate bitmap font按鈕檢視效果是否符合我們的要求:
當調整好之後,我們就可以點選save image as…按鈕來儲存生成的圖檔:
最後将圖檔添加到xnagamefontcontent項目的fonts檔案夾,修改圖檔的processor屬性為sprite font texture - xna framework。就可以在程式中使用我們制作的字型:
spritefont sftextureplus;//sprite font texture文本(xna bitmap font plus制作)
vector2 sftextureplusposition;//sprite font texture 文本位置
sftextureplusposition = new vector2(40, 350);
sftextureplus = content.load<spritefont>(@"fonts/spritefonttexture3");
spritebatch.drawstring(sftextureplus, "sprite font texture 3", sftextureplusposition, color.white);
下面給出所有以上這幾種字型綜合到一起的代碼:
sfposition = vector2.zero;
sfchineseposition = new vector2(0, 100);
sftextureposition = new vector2(0, 200);
sftextureextendposition = new vector2(0, 300);
sftextureplusposition = new vector2(0, 400);
最終效果:
ok,就到這裡吧!
最後附上源代碼(上面提到的幾個工具,都可以點選相關連結下載下傳):