安卓游戏开发者:我是如何把包体减了88%

2015年11月24日 11:02 0 点赞 0 评论 更新于 2025-11-21 16:54

尽管谷歌此前宣布将Google Play的应用大小限制从50MB提高到了100MB,但对于碎片化严重的Android平台而言,一款游戏若要适配多种屏幕尺寸,仍需考虑包体大小的问题。最近,一位安卓游戏开发者在博客中分享了自己将游戏包体从106M缩减至12M的方法,遇到类似问题的开发者不妨借鉴。以下是编译后的正文:

初始分析与问题发现

在分析了各类安卓设备的不同分辨率后,我决定将所有游戏资源以6种不同尺寸进行制作。不过,我担心这样做会使最终游戏的apk文件大小增加。因此,在首次开发这款游戏时,我便决定对所有资源进行检查。

我创建了一个仅包含最低(800×480)和最高(2560×1600)分辨率图片的包体,其大小达到了106M!由于我还需要增加4种其他大小的分辨率,所以推测最终的apk大小至少会超过300MB。查阅文档后我发现,谷歌要求包体大小在100MB以下,超出部分必须通过分割资源包的形式下载。此外,也可以为不同的设备提供不同的apk文件,但这两种方式我都不太青睐,因为我不希望玩家在下载安卓游戏后,还需等待很长时间来下载数百兆的资源。所以,我需要寻找新的方法来解决这一冲突。

探索优化方法

我在网上进行了搜索,大多数建议是使用压缩器或模糊处理(obfuscator programs)软件对代码进行打包,但实际效果微乎其微。随后,一个建议引起了我的注意,即全部采用JPEG图片格式。我使用TextureAtlas自动打包所有资源,同时可以将图片中没有透明区域的部分分隔出来,然后将它们分别作为PNG或JPG图片集进行打包。

然而,我游戏中90%的图片都需要透明度,其中主要问题集中在卡牌图片上,这些图片都带有圆角。于是,我想到了一个办法:将这些卡牌图片分为框架和内容两部分。在这款游戏中,只有4种卡牌类型,同类卡牌的框架相同。卡牌内部的内容各不相同,但这些内容并不需要透明度。我没有将126张卡片打包成PNG图片,而是全部做成了JPG图片,再加上4张PNG框架图。

在分步处理图片时,要确保JPG图片首先被绘制出来,然后将PNG框架覆盖在上面。这里所说的分步处理,是指将图形放置在libGDX Stage(Group)中。为了简化代码,我创建了Cardimage类(class)来处理透明化的绘图。这个Group包含来自JPG图片的卡牌中心部分,然后将来自PNG图片的框架覆盖在上面。

进一步优化与细节处理

虽然上述方法节省了大量空间,但我仍担心卡牌翻转动作会导致包体过大。当卡牌向左或向右翻转时,我直接将图片进行翻转,这样可以节省空间,因为无需存储完整的卡牌图像。我曾尝试只翻转部分图像,这可能需要使用AtlasRegion.flip()函数,但我不想翻转完整的JPG图像,因为部分图片内容应保持不变,且只有完整的图形才需要展示。因此,在调用flip(true, false)之后,我使用setRegionY和setRegionHeight来缩减翻转区域的大小。通过使用翻转区域,我创建了另一个图形并将其添加到CardImaeg group中。在运行时,只需简单地展示或隐藏这个图片即可。

优化结果

采用新方法制作的apk文件,在包含相同内容的情况下,大小降至12MB,这意味着节省了88%的空间。加入其他四种分辨率后,apk包体降至42MB,与此前预计的300MB相比,相差了9倍多。

总结建议

除了网上常见的建议(如压缩代码等)外,还可以考虑以下三条建议:

  1. 优先使用JPG格式图片:在可能的情况下,尽量采用JPG图片格式,以减少包体大小。
  2. 图片分割处理:如果使用PNG只是为了实现半透明边框,最好将图片剪裁成边框和内容两部分,将框架以PNG格式存储,内容以JPG格式存储。或者,将边框拆分为四部分(左右上下),在运行时进行组合,这样不仅可以节省存储空间,还能减少图片数量,提高游戏运行速度。
  3. 图片翻转处理:如果图片需要翻转或旋转,只需存储初始版本,在运行时进行相应操作即可。

作者信息

洞悉

洞悉

共发布了 3994 篇文章