Clash of Clans(COC)资源打包相关技巧探密

Clash of Clans,简称为COC,中文名《部落冲突》,是iOS平台上一款相当火爆的战斗策略类游戏,开发商是芬兰的SuperCell,据说日收入上百万美刀,创造了手游史上的一个神话。

不管在画质,玩法,操作体验,玩家交互,平衡性等方面,COC都做得相当极致,是普通手游开发商所不及的。

好了,废话到此为止,今天主要是给大家分享一下其资源打包相关的技巧:

COC的安装程序总大小约50M(v4.120版),其中资源约35.6M,不管在低端的iphone、ipad设备,还是视网膜屏的设备上,画质都相当出色。这其中到底采用了什么技术?请往下看:

下载iOS版COC安装程序,将扩展名ipa改成zip,解压出来,其中资源文件便是res/sc目录下的sc文件(推测此sc应该是SuperCell的缩写),从文件名便可知COC采用了普清和高清两套资源,如:buildings.sc和buildings_lowres.sc,其中含_lowres的是普清版本,不含的是高清版本。

或许你会问,既然有高清版,为什么不在普清设备上直接用高清版缩放,这样一来资源量更小。

因为在低端设备下,内存是有限的,假如高清图尺寸2048px*2048px,普清图尺寸1024px*1024px,即普清图尺寸为高清图的1/4,加载一张2048px*2048px RGBA8888格式的位图,理论上会占用16M内存,而相同格式1024px*1024px的只需4M内存,显而易见,使用普清图可以节省很多内存,这在低端设备上是相当可观的。

其实还有另一种方法,既只用一套资源,又在低端设备上节省内存。即只用高清图,在高清设备上直接使用,在普清设备上首次启动时,程序自动根据高清图缩小出普清图保存到缓存目录,以后就直接用缓存目录下的普清图。

 

sc文件是一个压缩文件,它是使用了修改的LZMA压缩算法进行压缩的,或许,你对LZMA压缩算法不了解,但是应该知道7-zip这款压缩工具,或者linux下新兴的高压缩比的xz压缩工具,事实上,7-zip的压缩默认是采用LZMA压缩算法的,linux下的xz相当于LZMA的升级版。

标准的LZMA压缩文件的文件头由5+8个字节组成,其中前5个字节中存储了压缩方式,字典大小等信息,后8个字节为压缩前的文件大小;COC所使用的修改后的LZMA算法,其文件头由5+4个字节组成,跟标准算法相比,仅仅是将表示压缩前的文件大小那8个字节,改成了4个字节(对于游戏资源,4个字节能表示的文件大小已经足够用了),这样一来,使用标准的LZMA压缩算法的解压工具,都不能正常解压(因为绝大多数情况下取出来的压缩前的文件大小会相当大),这样一来,通过简单的修改,既能较好的压缩游戏资源,又能较好的保护资源不被别人直接解压,真的是很高明。


如果要使用标准LZMA算法的解压工具能正确解压COC中的资源,只要在第9个字节后面插入4个0字节,如loading.sc文件,其前13个字节如下:

0x5D 0x00 0x00 0x04 0x00 0x2F 0xC9 0x42 0x00 0x00 0x07 0xFF 0xFD

在第9个字节后插入4个0字节,得到如下格式:

0x5D 0x00 0x00 0x04 0x00 0x2F 0xC9 0x42 0x000x00 0x00 0x00 0x00 0x00 0x07 0xFF 0xFD

保存,便可用7-zip等工具解压了。

解压出来的文件,总共约195M,压缩比高达18.26%,将LZMA压缩算法应用到自己的项目,是个不错的选择。

这样解压出来的文件,还是不能直接相看的,因为还不是位图。

 

解压出来的文件格式暂时称它为sc文件格式,它的结构如下:

类型1长度1数据块1
类型2长度2数据块2
.........
类型n长度n数据块n

其中:类型为1个字节,标识数据块是何类型,长度为4个字节,表示随后的数据块的字节长度。

 

类型1便是纹理(texture),其数据块结构如下:

纹理格式纹理宽度纹理高度纹理数据

其中:格式为1个字节,宽度为2个字节,高度为2个字节。

格式3为RGBA8888格式,如果要得到位图,需要的同学自己写代码实现吧,这里不提供了。

 

附一段简单PHP的解压代码:

<?php
define('DS', DIRECTORY_SEPARATOR);

function fixFile($filename) {
    echo "Begin fix {$filename} ... \n";
    $dataStr = file_get_contents($filename);
    $newDataStr = substr($dataStr, 0, 9) . "\x00\x00\x00\x00" . substr($dataStr, 9);
    $newFilename = str_replace('.sc', '.lzma', $filename);
    file_put_contents($newFilename, $newDataStr);
    echo "Fix {$filename} OK!\n\n";
}

// $dir = dirname(__FILE__); // 中文路径取不到?
$dir = substr(__FILE__, 0, -1 * (strlen(basename(__FILE__)) + 1));
$zipFileArr = glob($dir . DS . 'Clash of Clans*.ipa');
foreach ($zipFileArr as $zipFile) {
    echo "Begin extract {$zipFile} ...\n";
    $zip = new ZipArchive();
    if ($zip->open($zipFile) === TRUE) {
        $extractPath = str_replace('.ipa', '', $zipFile);
        if (!file_exists($extractPath)) {
            mkdir($extractPath);
        }
        $zip->extractTo($extractPath);
        $zip->close();
        echo "Extract to {$extractPath} OK!\n\n";

        $scPath = $extractPath . DS . 'Payload' . DS . 'Clash of Clans.app' . DS . 'res' . DS . 'sc';
        $scFileArr = glob($scPath . DS . '*.sc');
        foreach ($scFileArr as $scFile) { // 修复
            fixFile($scFile);
        }
        $exePath = 'D:\Program Files (x86)\7-Zip\7z.exe';
        if (file_exists($exePath)) {
            $cmd = sprintf('"%s" e -y -o"%s" "%s"', $exePath, $scPath, $scPath . DS . '*.lzma');
            echo "{$cmd}\n";
            passthru($cmd);
        }
        $cmd = "%SystemRoot%\explorer.exe /e,{$scPath}";
        passthru($cmd);
    } else {
        echo "Extract {$zipFile} fail!\n";
    }
}

将COC的ipa安装文件放到脚本所在目录,需要安装7-zip,具体目录参看代码。

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值