Clash of Clans,简称为COC,中文名《部落冲突》,是ios平台上一款相当火爆的战斗策略类游戏,开发商是芬兰的supercell,据说日收入上百万美刀,创造了手游史上的一个神话。
不管在画质,玩法,操作体验,玩家交互等上面,COC都做得相当极致,是普通手游开发商所不及的。
好了,废话到此为止,今天主要是给大家分享一下其资源压缩中的秘密:
COC的安装程序总大小不到50M,却能呈现这么好的画质,不管在低端的iphone、ipad设备,还是视网膜屏的设备上,画质依然那么好。这其中到底采用了什么NB的技术呢?
其实,答案很简单,它的资源是使用了修改的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 0x00 0x00 0x00 0x00 0x00 0x00 0x07 0xFF 0xFD
保存,便可用7-zip等工具解压了。
压缩后的资源文件总大小约为35.7M, 解压出来的资源文件总大小约为195M,其压缩比达18.3%,把这项技术用于手游项目,无疑会给你的游戏加分!!!
附一段简单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,具体目录参看代码。