首页
学习
活动
专区
圈层
工具
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

制作游戏时,如何选择和处理字体?

本文将介绍几款推荐的中文字体,并且分享如何尽量减少字体文件的大小。

昨天我尝试试用一款名叫 Love 的游戏引擎,发现它没有内置任何中文字体,因此游戏中的中文字符会出现乱码。此外,它也无法正确加载 Mac操作系统中的字体,于是我把系统目录中的一个字体文件复制到游戏目录下,解决了问题。

但是,这个字体文件太大了, 有 67M。于是我马上想到了,游戏中只用到一小部分字体和字号,那我是不是可以压缩字体文件?结果果然找到了不少工具。另外,我觉得系统默认字体比较单调,就这网上搜索了可免费商用且无需授权的字体,分享给大家。

可免费商用且无需授权的 7 种中文字体

(精简版,只保留 3500 常用字)

来自 Github项目:https://github.com/DeronW/minify-font

字体文件压缩思路

字体文件中,除了只保留常用字之外,还可以进一步压缩:只保留游戏中遇到的字。这里我用到了一个工具:

https://ecomfe.github.io/fontmin/

Fontmin

第一个纯 JavaScript 字体子集化方案

我在项目中处理字体,经过了三步:

1. 选择一款ttf 格式的字体,并把字体文件放在自己游戏项目中的 font 目录

2. 编写一个Python 脚本(extract_chars.py),用于提取代码中遇到的所有字符

#!/usr/bin/env python3# -*- coding: utf-8 -*-"""字符提取工具 - Python版本用于从项目中的Lua文件提取所有字符,并直接打印到标准输出日志信息输出到标准错误,方便重定向输出空白字符(空格、换行、制表符等)会被排除"""

import osimport sysimport codecs

# 颜色设置(用于彩色输出)class Colors:   GREEN = '\033[92m'   YELLOW = '\033[93m'   RED = '\033[91m'   END = '\033[0m'

def print_color(text, color):   """带颜色打印文本到标准错误"""   print(f"{color}{text}{Colors.END}", file=sys.stderr)

def log(text):   """输出日志到标准错误"""   print(text, file=sys.stderr)

def find_lua_files(directory="src"):   """查找指定目录下的所有Lua文件,不包括tools目录"""   print_color(f"查找{directory}目录中的Lua文件...", Colors.YELLOW)

  lua_files = []   for root, _, files in os.walk(directory):       # 跳过tools目录       if "tools" in root.split(os.sep):           continue

      for file in files:           if file.endswith(".lua"):               lua_files.append(os.path.join(root, file))

  # 如果src目录下没有找到文件,尝试在根目录查找   if len(lua_files) == 0 and directory == "src":       print_color("src目录下未找到Lua文件,尝试在项目根目录查找...", Colors.YELLOW)       return find_lua_files(".")

  # 排序文件列表   lua_files.sort()

  print_color(f"在{directory}目录中找到 {len(lua_files)} 个Lua文件", Colors.GREEN)

  return lua_files

def read_file(filename):   """读取文件内容,处理编码问题"""   try:       # 尝试用UTF-8读取       with codecs.open(filename, "r", "utf-8") as f:           return f.read()   except UnicodeDecodeError:       try:           # 尝试用GBK读取(针对中文Windows系统)           with codecs.open(filename, "r", "gbk") as f:               return f.read()       except:           try:               # 尝试latin-1编码(应该能读取任何文件,但可能解码不正确)               with codecs.open(filename, "r", "latin-1") as f:                   return f.read()           except Exception as e:               print_color(f"无法读取文件 {filename}: {e}", Colors.RED)               return ""

def is_chinese(char):   """判断一个字符是否是中文字符"""   # 检查是否是中文Unicode范围   if '\u4e00' <= char <= '\u9fff':       return True   # 检查是否是中文标点符号范围   if '\u3000' <= char <= '\u303f' or '\uff00' <= char <= '\uffef':       return True   return False

def extract_characters(lua_files):   """从Lua文件中提取所有字符和中文字符"""   print_color("开始提取字符...", Colors.YELLOW)

  all_chars = set()   chinese_chars = set()   whitespacesCount = 0

  for file in lua_files:       content = read_file(file)       if not content:           continue

      log(f"处理文件: {file} ({len(content)} 字节)")

      # 将文件内容拆分为单个字符并分类       for char in content:           # 跳过空白字符(空格、换行符、制表符等)           if char.isspace():               whitespacesCount += 1               continue

          all_chars.add(char)           if is_chinese(char):               chinese_chars.add(char)

  # 转换为排序后的列表   all_chars_list = sorted(list(all_chars))   chinese_chars_list = sorted(list(chinese_chars))

  print_color(f"共找到 {len(chinese_chars_list)} 个中文字符", Colors.GREEN)   print_color(f"共找到 {len(all_chars_list)} 个非空白字符", Colors.GREEN)   print_color(f"过滤掉 {whitespacesCount} 个空白字符", Colors.YELLOW)

  return chinese_chars_list, all_chars_list

def main():   """主函数"""   print_color("===== 字符提取工具 - Python版 =====", Colors.GREEN)

  # 查找Lua文件   lua_files = find_lua_files()

  if not lua_files:       print_color("未找到Lua文件,程序结束", Colors.RED)       return

  # 提取字符   chinese_chars, all_chars = extract_characters(lua_files)

  # 只将所有字符直接写入标准输出(无任何额外文本)   all_chars_str = "".join(all_chars)   sys.stdout.write(all_chars_str)   # 不添加换行,保持输出内容的纯净性

  print_color("\n===== 字符提取工具运行完成 =====", Colors.GREEN)

if __name__ == "__main__":   main()

3. 压缩字体,并在代码中引用。

压缩字体需要先安装fontmin工具:

npm install -g fontmin

然后使用以下命令压缩字体(将提取的字符直接传递给fontmin):

text=`python3 tools/extract_chars.py` && fontmin -t "$text" fonts/ fonts-compressed/

这个命令会:

运行字符提取工具,获取所有使用的字符

从fonts/目录中读取字体文件

创建只包含游戏中使用字符的子集字体

将子集字体保存到fonts-compressed/目录

子集化后的字体大小通常只有原始字体的几分之一,极大地减小了游戏的体积。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OwWZeb4X1GJb6FGCB2MAIDvA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券