段時間想做一款像素風的游戲,中文像素字體就是一個繞不過去的問題。這里記錄下我制作 12 像素字體的過程。
使用的軟件是 fontforge:https://fontforge.org/en-US/
自己一個字一個字的做是不可能自己做的,所以在網上找到了兩個開源的字體庫
1. M+ BITMAP FONTS
https://mplus-fonts.osdn.jp/mplus-bitmap-fonts/download/index.html
這是來自日本的完全免費字體,看著還蠻好看,有一部分的中文部分。
2. HZK-12
https://github.com/aguegu/BitmapFont
覆蓋 GB2312 的中文 12 像素字體
靈感來自 ipix 中文像素字體的制作 我在原作的基礎上進行了一些修改。原作是將字模導出為 png 然后 Potrace 轉化成 svg 圖片, 最后再把 SVG 圖片導入 FontForge 中就制作。
我是直接調用了命令行的 fontforge, 使用 python 腳本讀取字模信息,然后調用 fontforge 的矩形繪制函數,把每個像素點繪制成一個 100x100
的正方形。省去了一些中間步驟,所以效率提升了很多,制作過程只用了幾分鐘就完成了。當然摸索這個方法的時間也用了三個晚上,好在以后重新制作的時間縮短到了幾分鐘。這里記錄下詳細的制作步驟,以及分享下源碼。
1. 安裝 fontforge 并添加支持庫 bdflib
bdf 支持庫是為了解析 M+ BITMAP FONTS ,hzk12 不需要額外插件。
fontforge 安裝步驟省略,fontforge 會默認安裝上 python 運行環境到軟件目錄下面 。
下載 bdflib 的 whl 文件解壓到
FontForgeBuilds\lib\python3.8\site-packages
目錄下就安裝好了。
2. 利用 Hzk12 生成 fontforge 工程
新建一個文件夾使用 vscode 打開, 新建 python 腳本命名為 hzk_to_sfd.py
,安裝 python 插件,設置 python 目錄為 fontforge 下的 python 環境 如圖所示:
源碼部分:
import fontforge
import binascii
KEYS = [0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01]
sdf_path = "HZK12.sfd"
hzk_path = "C:/Users/lo/Downloads/HZK/HZK12"
gb2312_path = "C:/Users/lo/Downloads/HZK/gb2312.txt"
defDraw(font, ch, rect_list):
gb2312 = ch.encode('gb2312')
hex_str = binascii.b2a_hex(gb2312)
result = str(hex_str, encoding='utf-8')
area = eval('0x' + result[:2]) -0x80
index = eval('0x' + result[2:]) -0x80
ioj = (area <<8) + index
# print(ch, gb2312, hex_str, result, ioj)
glyph = font.createMappedChar(ioj)
pen = glyph.glyphPen
y =11
max_x =0
for row in rect_list:
y = y -1
x = -1
for i in row:
x = x +1
if i:
pen.moveTo((100* x ,100* y ))
pen.lineTo((100* x ,100* y +100))
pen.lineTo((100* x +100,100* y +100))
pen.lineTo((100* x +100,100* y ))
pen.closePath
max_x = max(max_x,x)
# print("#")
# else:
# print(" ")
# print("\n")
pen = None
glyph.removeOverlap
glyph.width = max_x*100+200
def draw_glyph(ch):
rect_list = *12
for i in range(12):
rect_list.append([] *16)
# 獲取中文的 gb2312 編碼,一個漢字是由 2 個字節編碼組成
gb2312 = ch.encode('gb2312')
# 將二進制編碼數據轉化為十六進制數據
hex_str = binascii.b2a_hex(gb2312)
# 將數據按 unicode 轉化為字符串
result = str(hex_str, encoding='utf-8')
# 前兩位對應漢字的第一個字節:區碼,每一區記錄 94 個字符
area = eval('0x' + result[:2]) -0xA0
# 后兩位對應漢字的第二個字節:位碼,是漢字在其區的位置
index = eval('0x' + result[2:]) -0xA0
# 漢字在 HZK16 中的絕對偏移位置,最后乘 24 是因為字庫中的每個漢字字模都需要 24 字節
offset = (94* (area-1) + (index-1)) *24
font_rect = None
# 讀取 HZK16 漢字庫文件
with open(hzk_path, "rb") as f:
# 找到目標漢字的偏移位置
f.seek(offset)
# 從該字模數據中讀取 24 字節數據
font_rect = f.read(24)
# font_rect 的長度是 24,此處相當于 for k in range(16)
for k in range(len(font_rect) // 2):
# 每行數據
row_list = rect_list[k]
for j in range(2):
for i in range(8):
asc = font_rect[k *2+ j]
# 此處&為 Python 中的按位與運算符
flag = asc & KEYS[i]
# 數據規則獲取字模中數據添加到 16 行每行中 16 個位置處每個位置
row_list.append(flag)
return rect_list
defOpenGBK:
f = open(gb2312_path, 'r', encoding='UTF-8')
line = f.readline
for index, ch in enumerate(line):
if ch == "\n":
continue
print(index, end=' ')
print(ch)
f.close
defStart:
font = fontforge.font # Open a font
font.encoding = "gb2312"
font.ascent =1200
f = open(gb2312_path, 'r', encoding='UTF-8')
line = f.readline
while line:
for index, ch in enumerate(line):
if ch == "\n":
continue
print(ch)
rect = draw_glyph(ch)
Draw(font, ch, rect)
line = f.readline
font.save(sdf_path)
f.close
Start
這里依賴兩個文件 HZK12 和 gb2312.txt ,可以在 源碼中下載,在 Vscode 中運行腳本,或者在終端輸入:
"c:/Program Files (x86)/FontForgeBuilds/bin/ffpython.exe" c:/Users/lo/Downloads/HZK/hzk_to_sfd.py
#當然這里的 ffpython.exe 文件和 python 文件的路徑需要修改。
就能生成一個 hzk12.sfd
的文件,雙擊使用 fontforge 打開。看看效果。
還行 文字沒有錯位(hzk12 沒有前面的英文字模,所以看效果需要向下多翻一點)下面就來添加英文字模進來
3. 利用 M+ BITMAP FONTS 生成 fontforge 工程
我這里選擇的是 mplus_jf12r.bdf
文件作為字模,也可以使用其他的。
與第二步相同新建一個名為 bdf_to_sdf.py
的文件,這里依賴了第一步中安裝的bdflib
插件。
from bdflib import reader
from bdflib import writer
import fontforge
defOpenBDF(path):
with open(path, "rb") as handle:
return reader.read_bdf(handle)
defStart:
bdf_font =OpenBDF("C:/Users/lo/Downloads/HZK/mplus_jf12r.bdf")
sdf_font = fontforge.font
sdf_font.encoding = "jis208"
sdf_font.ascent =1200
for bdf_glyph in bdf_font.glyphs:
# bdf_glyph = bdf_font[12321]
x = -1
y =10
print(bdf_glyph.codepoint)
glyph = sdf_font.createMappedChar(bdf_glyph.codepoint)
pen = glyph.glyphPen
for ch in bdf_glyph.__str__:
if ch == '\n':
y = y -1
x = -1
print("")
if ch == '#' :
pen.moveTo((100* x ,100* y ))
pen.lineTo((100* x ,100* y +100))
pen.lineTo((100* x +100,100* y +100))
pen.lineTo((100* x +100,100* y ))
pen.closePath
print("#",end=" ")
else:
print(" ",end=" ")
x = x +1
pen = None
glyph.removeOverlap
# break
# sdf_font.autoWidth
sdf_font.save("mplus_jf12r.sfd")
Start
這里使用的文件同 mplus_jf12r.bdf 樣放在了源碼中。和第二步一樣的運行方式,運行后得到一個 mplus_jf12r.sfd 的 fontforge 工程。
也沒有錯位,太棒了。第 4 步就是把這兩個字體合并一下了。
4. 合并字體
hzk12 和 mplus bitmap 中有很多重合的字,所以有兩種合并方式,一個是重合的部分使用 hzk12 的字模,一個是使用 mplus 的。我選擇保留 mplus 的重合部分。
由于兩者編碼格式不同所以先統一下編碼格式,一個是 gb2312 一個是 jis208,所以我這全都設置成 Unicode Full 的格式。(fontforge 下的菜單 Encoding
->reencode
->ISO 10646-1 ( Unicode, Full )
)。然后在打開 Mplus-jf12r 的 fontforge 的窗口中 選擇菜單Element
->Merge Fonts
然后選擇hzk12.sfd
文件,然后會彈出一個對話框詢問 是否用導入的 graph 替換本工程的同位置 graph,這里選擇NO
,就是使用 mplus 的重合部分。
選擇英文和符號部分 調整下 Graph 的寬度 ,推薦 菜單 Metrics
->Auto Width
。
推薦按下
下一步生成 ttf 字體文件。生成之前可以先編輯下字體信息, 菜單 Element
->font info
,這里不介紹了。
5. 生成 ttf 文件
菜單 File
->Generate Fonts
設置下 TrueType 就可以點擊 Generate
了。這里會有對話框提示:“有重合的點或者面”, 我還沒有找到比較好的辦法消除,但是并不影響使用,所以就沒有再多處理。依然點擊Generate
生成。
好了現在打開字體看下效果。
還行吧 就是符號的部分不是很好看,也可以重新找點好看的字模用上面的方法替換下,我覺得也能用就沒換了,有需要可以自己動手了,接著看下在 Unity 中的效果怎么樣吧。
效果不錯 沒有錯位。
結束。
源碼以及 TTF 文件: https://github.com/Luckeee/mplus_hzk_12
參考:
ipix 中文像素字體的制作https://indienova.com/u/purestudio/blogread/20097
如何將點陣漢字矢量化https://indienova.com/indie-game-development/vectorize-chinese-bitmap-font/
Python 解析 HZK16https://zhuanlan.zhihu.com/p/54931969
雙標簽:就是成對出現的,類似于這種 <html> </html>
單標簽:就是可以單個使用的,類似于 <br> 換行標簽 或 <hr>水平線標簽。
標簽的屬性是用來定義文字或字符的 顏色、寬高、粗細、大小、等,這個是標簽屬性的作用。
1、每一個標簽都有自己的屬性,單標簽和雙標簽都有。
2、一個標簽可以有多個屬性。
3、每個屬性都有對應的值,值要用單或雙引號引起來。
4、多個屬性之間使用空格隔開。
5、屬性沒有順序之分。
6、字體屬性值,必須是系統可以識別的字體,一般為系統自帶字體。
7、HTML5 中 font 屬性已經棄用。
源代碼:↓
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--網頁抬頭-->
<title>中央氣象局</title>
</head>
<body>
<!--水平線的寬度是500像素,這個width就是標簽屬性-->
<hr width="500">
<!--下面這個是多個標簽屬性,多個屬性之間用空格隔開-->
<font color="red" face="黑體" size="7">標簽屬性</font>
</body>
</html>
字是網頁展示的重要內容之一,所以對文字的修飾也是CSS重點關注的一部分, CSS提供了以下常用的樣式屬性來修飾文字。
color 用來設置文字顏色。
設置方式支持以下幾種格式
<style>
.box {
color: red;
}
</style>
<div class="box">文字顏色</div>
<style>
.box {
color: #ff0000;
}
.box1 {
color: #f00;
}
</style>
<div class="box">文字顏色</div>
<div class="box1">簡寫形式</div>
<style>
.box {
color: rgb(255, 0, 0);
}
</style>
<div class="box">文字顏色</div>
<style>
.box {
color: rgba(255, 0, 0, 0.5);
}
</style>
<div class="box">文字顏色</div>
font-size 屬性用來設置字體大小,單位通常為px 也可以為em,rem
單位的解釋
<style>
.box {
font-size: 30px;
}
</style>
<div class="box">文字大小</div>
設置字體的粗細程度,常用的屬性有 normal 和 bold 兩個值。
可以用以下值表示,也可以用數字表示。
值 | 意義 |
normal | 正常粗細,和400值相等 |
bold | 加粗,與700數值相等 |
lighter | 比 正常粗細還細, 不常用 |
bolder | 比 加粗還粗,不常用 |
100 200 300 400 500 600 700 800 900 | 使用數字定義字體粗細 |
inherit | 從父元素繼承字體粗細 |
<style>
.box_normal {
font-weight: normal;
}
.box_bold {
font-weight: bold;
}
.box_lighter {
font-weight: lighter;
}
.box_bolder {
font-weight: bolder;
}
.box_number {
font-weight: 600;
}
</style>
<body>
<div class="box_normal">font-weight演示:正常粗細</div>
<div class="box_bold">font-weight演示,加粗</div>
<div class="box_lighter">font-weight演示,更細</div>
<div class="box_bolder">font-weight演示, 更粗</div>
<div class="box_number">font-weight演示, 數字</div>
</body>
設置字體的傾斜程度
值 | 意義 |
normal | 正常字體, 不帶傾斜效果 |
italic | 傾斜字體(常用,使用傾斜字體) |
oblique | 傾斜字體(用常規字體模擬傾斜,不常用) |
<style>
.box1 {
font-style: normal;
}
.box2 {
font-style: italic;
}
.box3 {
font-style: oblique;
}
</style>
<body>
<div class="box1">正常字體</div>
<div class="box2">傾斜字體</div>
<div class="box3">傾斜字體2</div>
</body>
設置文本的修飾線的樣式
示例 | 意義 |
none | 無線(a標簽去除下劃線會用到) |
underline; | 下劃線 |
line-through; | 刪除線 |
…等等 | 還有很多,可自行百度 |
<style>
.decoration-none {
text-decoration: none;
}
.decoration-underline {
text-decoration: underline;
}
.decoration-line-through {
text-decoration: line-through;
}
</style>
<body>
<div class="decoration-none">無線修飾</div>
<div class="decoration-underline">下劃線</div>
<div class="decoration-line-through">刪除線</div>
</body>
指定使用的字體族,操作系統一般自帶很多字體;
例如:window操作系統中的 ‘微軟雅黑’ ,黑體等。
字體文件的格式有很多,比如 eot,woff2,woff,ttf,svg等。
font-family 可以一次指定多個字體, 后面的字體屬于后備字體,只有前面的字體沒有找到,才會使用后面的字體。
<style>
div {
font-family: serif, "Time New Roman", "微軟雅黑"
}
</style>
<body>
<div>字體</div>
</body>
自定義字體
某些時候,我們的字體比較個性化,或者我們的字體是一個圖標字體(一種用符號表示圖片的方式)。那么此時,需要我們使用 @font-face 自定義字體
自定義的字體一般是隨著網頁發布在服務器端,操作系統中并沒有。
推薦一個比較好用的字體庫網站:https://www.iconfont.cn/(具體使用方式請自行百度)。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。