TexturePacker是一个常用的制作sprite sheet的工具,它提供了很多实用的功能。

一般我们制作sprite sheet都是使用他的gui版本,纯手工操作,就像下面这张图示的一样。

刚开始我们的项目也是使用这种方式,但后来发现这种方式在开发中有很大的问题。随着图片的增多,sprite sheet会越来越多,为了生成这些sprite sheet需要做很多重复的手工劳动,再考虑到给Android平台打包的sprite sheet配置和iOS的不同,还有包括图片变更,配置优化等情况,算下来光打包sprite sheet就需要巨大的工作量,这还不考虑由于手工误操作造成的各种问题。

于是我就考虑,如何尽可能地减少打包sprite sheet的工作量,提高开发的效率。后来通过搜索,看到raywenderlich上一篇关于使用TexturePacker的文章,里面比较详细地介绍了TexturePacker的用法,特别还提到了它的命令行工具的使用以及这个工具和xcode的集成,这给了我想要的答案。

接下来讲一下我在项目中如何使用这个TexturePacker的命令行工具以及实用它的一些经验。

---------------------------------------正式开始的分割线-----------------------------------------

具体下载和安装TexturePacker以及它命令行工具的方法就不说了,上面提到的那篇文章里有较详细的说明。一些准备就绪后,我们可以在命令行里执行texturepacker命令,正常情况下你将会看到texturepacker的各种参数以及使用方法的说明,如下图:

接下来为了方便说明,我们新建一个测试工程foo,这里以quick-cocos2d-x-2.2.1-rc引擎创建的工程为例,创建好后目录结构如下图:

我们需要一个目录去保存所有原始的(未打到sprite sheet里的)图片,这里我们新建个目录叫originalImages,然后找些图片,丢进这个目录,并将他们分类到不同的文件夹,接着我们再创建一个目录,用来存放我们打包sprite sheet的脚本工具,我们起名叫tools,然后,我们再创建一个目录spriteSheets,用于存放打好的图片,最后,一般我们会将工程用到的图片存放到res/images目录里面,所以为了清楚,再创建一个这个文件夹,最终目录结构如下图所示:

接下来我说一下思路,我们的脚本工具存放在tools文件夹中,运行之后会去遍历originalImages这个目录下的所有文件夹,然后将每个文件夹中的图片打包为一个sprite sheet,这个sprite sheet名字与该文件夹的名字相同,接着将打包后的sprite sheet文件复制两份,一份存入spriteSheets目录中,另一份拷贝到我们程序使用图片的目录。

举例来说,当我运行脚本,会生成三份sprite sheet,分别是button.png,button.plist,checkBox.png,checkBox.plist,common.png,common.plist,他们分别会存放入spriteSheets目录和res目录下的images目录中(一般res目录下的images目录用来存放程序中用到的图片)。

---------------------------------------渐入佳境的分割线------------------------------------------

好的,一切准备就绪,我们开始说说这个脚本究竟要如何编写。

首先我们需要大概了解一下texturepacker的一些常用参数。

  1. --format

指定sprite sheet的格式,默认是cocos2d,做cocos2d-x项目的话,就选cocos2d就行。可选的选项如下:

  1. --texture-format

非常重要的一个属性,指定texture的格式。如果我们做iOS上的游戏,一般都会使用PVR,因为这个format的texture是专门为苹果iPhone和iPad的图形处理器优化的,而Android因为设备硬件多种多样,所以我们一般可能会选用png格式的,感兴趣的朋友可以自己搜索一下相关内容。这个参数如果不指定值的话texturepacker会尝试去根据sprite sheet的命名来自动选择一个合适的format。具体的选项如下:

  1. --data

指定data文件的名字,也就是plist文件的名字

  1. --sheet

sprite sheet文件的名字

  1. --enable-rotation

是否开启旋转。一般我们会开启,为了更有效率的将散图打在一起。

  1. --scale

在创建sprite sheet之前为所有散图做一个调整scale的操作,比如,如果是0.5,那么就把原始图都压缩一般大小,再存入sprite sheet中

  1. --shape-padding

设置每个图片在sprite sheet中的间隔,默认是2

  1. --max-size

sprite sheet的最大尺寸,你不可能将所有图片都打入到一张sprite sheet里,因为没有设备能支持这样的sprite sheet,于是需要限定大小:)。

  1. --opt

这个是很重要的一个属性,决定了sprite sheet的像素格式,这个属性可以很大程序改变sprite sheet所占的内存。常用的选项如下:

  1. --trim

为了能在一张sprite sheet加入更多的图片,裁减掉原始图片的空白像素,但是使用的时候还是按照图片的原始尺寸来使用。

  1. --smart-update

智能更新,为了避免重复生成相同内容的sprite sheet,texturepacker会检查现存的sprite sheet和将要生成的sprite sheet内容是否相同,如果不同再生成新的,如果相同则不生成。

---------------------------------------激动人心的分割线------------------------------------------

好了,最后激动人心的时刻到了,我们上脚本!(脚本写的一般,多包涵)

  1. #! /bin/bash
  2.  
  3. CURRENT_DIR=`dirname $`
  4.  
  5. # input paths
  6. IMAGE_DIR=$CURRENT_DIR/../originalImages
  7.  
  8. # path that game proj use
  9. GAME_IMAGE_PATH=$CURRENT_DIR/../res/images
  10.  
  11. # temporary path to place the sprite sheets
  12. OUTPUT_PATH=$CURRENT_DIR/../spriteSheets
  13. OUTPUT_PATH_PVR=$OUTPUT_PATH/packagedPVR
  14. OUTPUT_PATH_PNG=$OUTPUT_PATH/packagedPNG
  15.  
  16. # path of the texture packer command line tool
  17. TP=/usr/local/bin/TexturePacker
  18.  
  19. # $: Source Directory where the assets are located
  20. # $: Output File Name without extension
  21. # $: RGB Quality factor
  22. # $: Scale factor
  23. # $: Max-Size factor
  24. # $: Texture Type (PNG, PVR.CCZ)
  25. # $: Texture format
  26. pack_textures() {
  27.  
  28. ${TP} --smart-update \
  29. --texture-format $ \
  30. --format cocos2d \
  31. --data "$2".plist \
  32. --sheet "$2".$ \
  33. --maxrects-heuristics best \
  34. --enable-rotation \
  35. --scale $ \
  36. --shape-padding \
  37. --max-size $ \
  38. --opt "$3" \
  39. --trim \
  40. $/*.png
  41.  
  42. }
  43.  
  44. # check the output path
  45.  
  46. if [ -d $OUTPUT_PATH ];then
  47. :
  48. else
  49. mkdir $OUTPUT_PATH
  50. fi
  51.  
  52. if [ -d $OUTPUT_PATH_PVR ]
  53. then
  54. :
  55. else
  56. mkdir $OUTPUT_PATH_PVR
  57. fi
  58.  
  59. if [ -d $OUTPUT_PATH_PNG ]
  60. then
  61. :
  62. else
  63. mkdir $OUTPUT_PATH_PNG
  64. fi
  65.  
  66. # do the job
  67. for i in $IMAGE_DIR/*
  68. do
  69. if [ -d $i ]
  70. then
  71. spriteSheetName=`basename $i`
  72. pack_textures $i $OUTPUT_PATH_PNG/$spriteSheetName 'RGBA8888' 1 2048 'png' "png"
  73. pack_textures $i $OUTPUT_PATH_PVR/$spriteSheetName 'RGBA8888' 1 2048 'pvr.ccz' "pvr2ccz"
  74. fi
  75. done
  76.  
  77. # cp them to the game proj image path
  78.  
  79. cp -f $OUTPUT_PATH_PVR/* $GAME_IMAGE_PATH

将脚本的内容保存到一个文件中,命名后把后缀改为command,比如我是这个样子的:

然后记得在命令行里改一下脚本的权限,最后双击一下脚本,新鲜的sprite sheets就打包出来了,如果有什么图片的改动,只需要修改originalImages这个目录下的图片,然后双击一下脚本,新的sprite sheet就生成好了,再也没有了无聊烦人的手工劳动,向TP的GUI说再见吧!是不是很爽?:)

----------------------------------------最后的分割线-----------------------------------------

最后简单说一下在脚本里我们做的事情:

在脚本中我们针对originalImages里面每一个文件夹中的图,生成了两份sprite sheet,这两份唯一的区别是一份是pvr2ccz格式的,一份是png格式的,其他的属性都相同:像素格式RGBA8888,scale为1,最大尺寸为2048*2048。在生成完成后,将所有的sprite sheet拷贝到了spriteSheets这个文件夹,并把其中pvr格式的sprite sheet拷贝到了我们工程使用的图片目录里。

OK,大概就是这样子,那个脚本可以根据项目具体需求去改,我写的很简单,也没加什么log,这个其实完全可以写得更智能话写,这就留给各位去发挥了。

----------------------------------一些更新和补充----------------------------------------

最近有园子里的朋友和我交流了几个问题,我觉得其中有2个挺不错的,具体交流的内容在本文的留言里面有,不过为了方便大家查阅,我把它们整理(其实主要是截图,我是有多懒=。=)了一下,整合到这个篇文章中:

问题1:来自园友 tanyongdahaoren

答案:

这个问题回答的比较明确,我就不过多解释了:)

(这里忍不住吐槽一下博客园的插入代码功能,在回复里面没有bash的选项不说,在文章中bash的代码明显没有按照bash的脚本着色,“/*”竟然按照注释理解了,真心汗一个)

问题2:来自园友sousou123

这个园友主要的想法是考虑如何用TexturePacker把单张的png图片转换成pvr格式的图片。我一开始建议它用苹果官方的工具texturetool,但后来我意识到,这个texturetool相对TexturePacker有很多不方便的地方,比如它对原始图片的格式有硬性要求,必须至少满足:

  • Height and width must be at least 8.
  • Height and width must be a power of 2.
  • Must be square (height==width)

而TexturePacker虽然可以做png到pvr转换的事情,但是毕竟设计目的是打包sprite sheet用的。

不过经过和他的讨论,最终我给出了TexturePacker的解决方案:

这段脚本所做的事情是遍历images这个文件夹下的所有png图片,然后对每一张小图片都做一次打包操作,打包后的图片格式为pvr,这就相当于对每一张图片做了一次格式的转换:从png到pvr。这个做法虽然不同于TexturePacker的设计初衷,但毕竟是可行的,而且很方便。

这里要注意一点,我们相对于之前打包的脚本多增加了一个参数:--size-constraints

这个参数非常关键,它决定了最终生成的sprite sheet的尺寸是否会受POT(Power Of Two)格式的限制。一般情况下我们生成sprite sheet的尺寸都是宽高相等,并且都是2的N次方。而对我们现在这个转换图片格式的需求,这个限制就多余了,因为我们肯定希望原始图片多大尺寸,最终转换得到的图片就是多大尺寸,所以这里我们设置这个参数的值为AnySize。

  1. --size-constraints AnySize

不得不说TexturePacker这个工具的功能真的很强大,作者考虑问题非常得全面~

这个参数在GUI里面在这里:

还有一点小问题是,对于每一个sprite sheet,都会需要生成一个data文件,这里我们不需要这个data文件,所以在参数里面我们就随便叫了一个dummy.plist:)其他的参数你们可以按需修改。

好了,更新部分就是这么多,最后感谢一下园友sousou123和tanyongdahaoren,通过解决他们的问题也让我学到了新的东西:)

感谢大家的收看~ 如果有问题可以留言或者私信我,我会尽量回覆大家。

最近刚开始专门写博客,如果表达的不好,或者有其他方面问题,也请大家多提宝贵意见:)

最最后,原创文章,转载请注明出处,谢谢:)

[原创]使用命令行工具提升cocos2d-x开发效率(一)之TexturePacker篇的更多相关文章

  1. [原创]使用命令行工具提升cocos2d-x开发效率(二)之CocosBuilder篇

    如果你正在使用CocosBuilder或者是其他基于CocosBuilder源码改装而成的工具为你的游戏搭建场景或者UI,那你一定要看看这篇文章:)   你是否已经厌倦了无聊的手工publish操作? ...

  2. 使用命令行工具提升cocos2d-x开发效率 之CocosBuilder篇

    http://www.cnblogs.com/flyFreeZn/p/3617983.html 假设你正在使用CocosBuilder或者是其它基于CocosBuilder源代码改装而成的工具为你的游 ...

  3. [原创]用命令行工具删除TFS2010服务器上的工作区信息

    下面的示例显示有关所有计算机上的所有用户已在地址 http://myserver:8080/tfs/DefaultCollection 上的以下团队项目集合中创建的所有工作区的列表. c:\proje ...

  4. Wireshark命令行工具tshark

    Wireshark命令行工具tshark 1.目的 写这篇博客的目的主要是为了方便查阅,使用wireshark可以分析数据包,可以通过编辑过滤表达式来达到对数据的分析:但我的需求是,怎么样把Data部 ...

  5. 如何用node编写命令行工具,附上一个ginit示例,并推荐好用的命令行工具

    原文 手把手教你写一个 Node.js CLI 强大的 Node.js 除了能写传统的 Web 应用,其实还有更广泛的用途.微服务.REST API.各种工具……甚至还能开发物联网和桌面应用.Java ...

  6. [易学易懂系列|rustlang语言|零基础|快速入门|(25)|实战2:命令行工具minigrep(2)]

    [易学易懂系列|rustlang语言|零基础|快速入门|(25)|实战2:命令行工具minigrep(2)] 项目实战 实战2:命令行工具minigrep 我们继续开发我们的minigrep. 我们现 ...

  7. JDK的命令行工具

    Jcmd:综合工具 jcmd -l  列出当前运行的所有虚拟机 参数-l表示列出所有java虚拟机,针对每一个虚拟机,可以使用help命令列出该虚拟机支持的所有命令 jcmd [pid] help j ...

  8. 显示器 Linux 性能 18 (一个命令行工具传递)

    对于系统和网络管理员来说每天监控和调试Linux系统的性能问题是一项繁重的工作.在IT领域作为一名Linux系统的管理员工作5年后,我逐渐认识到监控和保持系统启动并执行是多么的不easy.基于此原因. ...

  9. MSSQL-Scripter,一个新的生成T-SQL脚本的SQL Server命令行工具

    这里向大家介绍一个新的生成T-SQL脚本的SQL Server命令行工具:mssql-scripter.它支持在SQL Server.Azure SQL DB以及Azure SQL DW中为数据库生成 ...

随机推荐

  1. mvvm结构中数据的关联----wpf

    1.在视图中PlotView.xaml <Button Content="<<" Height="23" HorizontalAlignmen ...

  2. 博主教你制作类似9patch效果的iOS图片拉伸

    下面张图片,本来是设计来做按钮背景的:   button.png,尺寸为:24x60 现在我们把它用作为按钮背景,按钮尺寸是150x50: // 得到view的尺寸 CGSize viewSize = ...

  3. LintCode-Fast Power

    Calculate the an % b where a, b and n are all 32bit integers. Example For 231 % 3 = 2 For 1001000 % ...

  4. adb 选择设备

    在adb中有多个设备时,可以先adb devices列举出设备,然后可以通过adb -s <设备名>  [其他参数] 对某个设备进行操作. 例如: adb -s 0123456789ABC ...

  5. android studio 中设置apk的版本号

    今天在mainfest.xml中设置版本号为2,(代码获取到的版本号无效) android:versionCode="2" android:versionName="2. ...

  6. 一个完整openlayer的例子,包括marker,popup等

    整理转自:http://www.blogjava.net/siriusfx/archive/2007/11/26/163104.html openlayers提供了几十个示例,虽然每个示例都很简单,但 ...

  7. Java多线程——<四>让线程有返回值

    一.概述 到目前为止,我们已经能够声明并使一个线程任务运行起来了.但是遇到一个问题:现在定义的任务都没有任何返回值,那么加入我们希望一个任务运行结束后告诉我一个结果,该结果表名任务执行成功或失败,此时 ...

  8. OD鲜为人知的小技巧--搜索通配符(关键字)

    我看过一些OD教程,关于通配符这一点很少有人讲解(大概是我看的教程少吧)  近日通过看<黑客反汇编揭秘(第二版)>第165页了解到,原来OD还有这样方便的功能,那就是搜索通配符: Olly ...

  9. [转载]C# winform登陆框验证码的实现

    验证码技术已愈来愈成熟,从最初的数字.字母.字符.汉字已经到目前的语言,其应用也甚广,之前大多数只有在网站上可以看到,现在在一些客户端软件也经常可见(比如证券相关软件).之前做的一个基于 C# 客户端 ...

  10. dll 入口函数

    http://support.microsoft.com/kb/815065/zh-cn // SampleDLL.cpp // #include "stdafx.h" #defi ...