概览
这段时间忙着做游戏平台H5游戏的接入,趁着刚做完还热乎劲儿,将其中的技术要点总结下来。H5游戏的接入主要分为两个部分:游戏的下载和游戏对战。本篇博客着重讲述游戏的下载部分,下篇博客将着重讲述H5游戏与app通过JS进行数据交互以及在线对战的技术要点。
H5游戏资源本质上是由一些目录以及目录下的文件资源组成,要能够在app中运行H5游戏,就是要在WKWebView
的浏览器中用HTTPServer搭建本地服务,然后去加载游戏资源根目录下的index.html文件,换句话说index.html文件是游戏的入口文件。HTTPServer我们采用的是开源的CocoaHTTPServer,关于在app中搭建HTTPServer服务的内容就不多赘述,感兴趣的可以去Github上了解。当然,这也需要H5与iOS开发人员沟通和调试才能真正地在WKWebView
中流畅运行。
游戏资源下载思路
知道了怎样在app中运行H5游戏,接下来最重要的就是游戏资源的下载。当用户进入一个游戏后,游戏的状态分为三种:未下载,已下载,暂停下载和需要更新。如何判断游戏此时的状态呢?首先我们需要区分每一个游戏,因此,约定将游戏资源的URL进行MD5加密后的字符串作为游戏的唯一标识符。之后,我们创建game.plist
文件,文件中存储一个字典,字典的key为游戏的标识符,value为游戏资源的大小。每当一个游戏开始下载,则在plist文件中添加一条记录。检查游戏的状态时,拿游戏的标识符与plist文件中所有的记录进行对比,若未找到相同的记录则状态为未下载。否则,在存储游戏资源的文件夹中查找以游戏标识符命名的.zip压缩包,若找到将其包的大小与plist文件中找到的记录的大小进行比较,若大小不同,则状态为暂停下载,若未找到压缩包且未找到解压后的资源文件夹显示为未下载。否则,状态为已下载。至于更新的状态则需要与服务器端进行沟通和约定,在此就不讲了。
确定完当前进入游戏的状态后,当游戏处于未下载或者暂停的状态时,用户可以点击下载按钮进行下载。下载的过程分为两种情况:未下载开始下载和暂停继续下载。第一种情况的下载过程是这样:在资源下载目录下创建以游戏标识符命名的.zip压缩文件,用NSURLSession
创建NSURLSessionDataTask
任务负责资源数据的接收,用NSOutputStream
负责数据流的写入工作。写入完毕后,关闭NSOutputStream
服务,验证资源包数据的完整性。若资源包数据完整,则对其进行解压缩,得到游戏运行的全部资源文件后便可以开始游戏。第二种情况则是在资源下载目录下查找以游戏标识符命名的.zip压缩包,获取包文件的内容大小,将其放入NSURLRequest
的HTTP请求头中,剩下的步骤与第一种情况相同。
游戏资源下载的代码实现
思路厘清了,就需要用代码去实现它。因此,我创建了名为XRDownloadManger
的类负责游戏资源的下载工作。为了更好的辅助XRDownloadManager
工作,又创建了模型类XRSessionModel
来存储游戏资源的相关数据。
下面列出的是XRSessionModel
的类结构:
|
|
XRDownloadManger
采用了单例设计模式,该类主要的工作包括开启任务下载游戏资源并回调下载进度和下载状态,获取资源大小,删除已下载资源,判断游戏资源是否下载完成等。
|
|
XRDownloadManger
实现文件中包含两个可变字典类型的成员变量tasks
和sessionModels
,tasks
负责保存所有的下载任务,sessionModels
负责保存所有的下载资源的相关信息。tasks
和sessionModels
均是以url为key,但value分别为NSURLSessionDataTask
和XRSessionModel
的键值对。
download:::
方法是负责下载的主要方法。每一个NSURLSessionDataTask
对象负责一个游戏资源的下载,并将该对象存入tasks中。当下载完成并验证压缩包内容的完整性后将NSURLSessionDataTask
对象移除,当需要暂停的时候,以游戏URL的md5字符串为key拿到NSURLSessionDataTask
对象并执行suspend方法将下载任务暂停。暂停后继续下载也与之类似,同样是从tasks中拿到NSURLSessionDataTask
对象并执行resume方法继续下载任务。
|
|
整个网络数据的请求和处理都依赖于NSURLSessionDataDelegate
的代理方法。请求得到反馈时根据response拿到游戏资源的完整大小,并将其写入到game.plist
文件中。当客户端开始接收服务器返回的数据时,打开NSOutputStream
并开始将接收到的数据写入到指定路径下的文件中,并返回下载进度。接收数据完成后对数据包进行解压缩,解压成功则将写入流关闭并将下载任务从tasks中移除。
|
|
结语
以上是对下载过程实现的大概描述,其中的实现细节还有很多值得推敲和优化的地方,接下来会发时间去优化并会将优化后的效果总结出来。如果其中有错误的地方欢迎指正。