在macOS搭建LÖVE for iOS平台

  欢迎参与讨论,转载请注明出处。

前言

  继上回在macOS搭建LÖVE for Android平台后,这次买了新的iPhone,对iOS平台的发布自然也要开始了。如上回一般,也发现了不少实操中会遇到的问题,特此记录,以便后人。

实机调试

  LÖVE for iOS的编译可谓相当容易,前提是你必须拥有一台macOS以及iOS设备,并且安装了Xcode。如官方教程所言般进行便是,大致上就是下载LÖVE源码工程,并且用Xcode打开love/platform/xcode/love.xcodeproj,然后选择love-ios项目、连上iOS设备、设置签名、然后Build就完事了。
0
  如上图所示那便是签名的设置了,需要登录Apple账号作为Personal Team,并确保这是iOS设备所使用的账号
1
  签名设置完成无错误提示后,那便如上图所示般选择、执行即可。请确保iOS设备与macOS设备是处于连接状态的,过会便可见到iOS设备已将LÖVE安装完毕。此时尚无法直接运行,需要执行设置→通用→设备管理→Apple账号→信任love
  刚装好的LÖVE仍是空空如也,你可以选择打包好一个项目作为test.love,使用Apple的隔空投送(AirDrop)功能进行快速传输,如下图所示:
2
  投送完毕后,iOS会精确的识别到这是LÖVE所需要的文件,于是你可以在LÖVE里见到它了,如下图所示:
3

画面适配

  我所测试的项目的功能很简单:显示一张图片、该图片会拉伸至窗口大小。直接运行的效果如下图所示:
4
  很明显可以得出两个问题:画面并不是水平的,以及顶部的状态栏没去掉。解决它俩的方法很简单,想要画面是水平的,就得在编译设置里进行更改,如下图所示:
5
  如此即可,至于顶部的状态栏的去除,选择编译设置里的Hide status bar是无效的,因为LÖVE在游戏运行时又做了一次设置。而这个设置则是与引擎的love.window.setFullscreen(fullscreen)这个API有关,只需要在游戏运行时设置为全屏即可关闭状态栏。如此便没毛病了,如下图所示:
6

开发调试

  在开发过程中需要不断地进行实机调试时,每次都对项目进行打包那效率未免也太低了。然而鉴于iOS的沙盒机制,又做不到如同Android般使用Git来进行同步工程。好在*.love文件本质上就是*.zip文件,如此开发一个对压缩包进行增量更新的脚本即可。如以下代码所示,用到了zip命令,脚本版本为Python3:

1
2
3
4
5
6
7
8
9
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
85
86
87
88
89
90
91
92
93
import os
import datetime
import zipfile
from os.path import realpath, dirname
def listdir(path):
paths = []
lst = path.split('/')
tree = file_tree
for i in range(len(lst) - 1):
tree = tree[lst[i]]
for k in tree:
v = tree[k]
p = k if v is True else k + '/'
paths.append(p)
return paths
def zip(code):
os.system("zip %s %s" % (file_name, code))
def sync(path):
is_file_a = os.path.isfile(path)
is_dir_a = os.path.isdir(path)
info = path in name_set and zip_file.getinfo(path)
is_file_b = info and not info.is_dir()
is_dir_b = info and not is_file_b
if is_file_a:
if is_dir_b:
zip('-d %s' % path)
if is_file_b:
time_a = os.stat(path).st_mtime
time_b = datetime.datetime(*info.date_time).timestamp()
if abs(time_a - time_b) > 1:
zip(path)
else:
zip(path)
elif is_dir_a:
if is_file_b:
zip('-d %s' % path)
if is_dir_b:
list_a = os.listdir(path)
for i in range(len(list_a)):
if os.path.isdir(path + list_a[i]):
list_a[i] = list_a[i] + '/'
list_b = listdir(path)
list_merger = list(set(list_a + list_b))
for p in list_merger:
sync(path + p)
else:
zip(path)
zip('-r %s*' % path)
else:
if is_dir_b:
zip('-d %s*' % path)
elif is_file_b:
zip('-d %s' % path)
cwd = dirname(realpath(__file__))
os.chdir(cwd)
file_name = 'game.love'
zip_file = zipfile.ZipFile(file_name, 'a')
zip_file.close()
name_set = set(zip_file.namelist())
file_tree = {}
for p in name_set:
ls = p.split('/')
tree = file_tree
length = len(ls)
for i in range(length):
s = ls[i]
if len(s) > 0:
if s not in tree:
tree[s] = True if i == length - 1 else {}
tree = tree[s]
sync('asset/')
sync('source/')
# ...

IPA发布

  以上只能本机运行而已,若是想分享给他人,便要解决新的问题了。iOS的安装包为.ipa文件,你需要提供正式的开发者账号作为签名,方可生成之。开发者账号分为以下三种:

  • 个人账号
    • 只能提供单人使用
    • 其他人若想运行ipa文件,需要注册其UDID
    • 99美元/年
  • 公司账号
    • 允许多个开发者使用
    • 需要填写公司的邓百氏编码(D-U-N-S Number)
    • 其他人若想运行ipa文件,需要注册其UDID
    • 99美元/年
  • 企业账号
    • 允许多个开发者使用
    • 需要填写公司的邓百氏编码(D-U-N-S Number)
    • 该账号下的APP不能发布到App Store
    • 299美元/年

也就是说,除了企业账号以外,想轻松分享给他人是比较麻烦的。这方面可以考虑诸如蒲公英一般的第三方签名平台,会更方便。
  IPA的生成方式为Xcode下Product→Archive,然后根据指示进行即可。顺带一提,在编译设置中将game.love文件加入到APP资源里,变会默认直接运行该项目,以达到发布的效果。如下图所示:
7

LuaJIT

  还有一个需要注意的问题是:Lua代码若是需要转为LuaJIT字节码,所选择的版本得是LuaJIT 2.1.0-beta2 64bit(在LÖVE 0.10.2下)。重点在于这个64位,由于Apple现行规定APP必须得是64位,于是连LuaJIT的字节码也必须同步。而想要生成64位的字节码,则必须编译出64位的LuaJIT,而这需要在编译时填写参数:make CFLAGS=-DLUAJIT_ENABLE_GC64

后记

  总的来说iOS平台较之Android在编译方面更为简单,毕竟是很稳定的平台与设施嘛。但在开发方面则有更多的繁文缛节,也算是福兮祸兮吧。