LayerSprites是一个库,旨在简化在不使用OpenGL或第三方游戏库的情况下,在UIKit应用程序中使用精灵表(包含多个子图像的图像映射)的过程。
注意:“支持”意味着库已经测试过这个版本。“兼容”意味着库应该在iOS版本上工作(即它不依赖于任何不可用的SDK功能),但不再对其兼容性进行测试,可能需要调整或修复错误才能正常运行。
LayerSprites需要ARC。如果您希望在非ARC项目中使用LayerSprites,只需将-fobjc-arc编译器标志添加到所有LayerSprites类文件中。为此,请转到目标设置中的构建阶段选项卡,打开编译源代码组,双击列表中每个相关的LayerSprites .m文件,并在弹出菜单中键入-fobjc-arc。
如果您希望将整个项目转换为ARC,请在每个LayerSprites相关的.m文件中注释掉#error行,然后在Xcode中运行编辑 > 重构 > 转换为Objective-C ARC...工具,并确保所有希望使用ARC的文件(包括所有的LayerSprites文件)都已被勾选。
要使用LayerSprites,只需将类文件拖入您的项目,并添加QuartzCore框架。
LayerSprites库目前包括以下类
LSImage - 这是一个用于表示具有相关裁剪和转换数据的图像文件的类。它支持与UIImage相同的图像格式和大多数相同的方法。
LSImageMap - 这是一个用于加载图像映射的类,也称为图像图集或精灵图。
LSImageView - 这是一个UIView子类,旨在使在您的应用程序中显示LSImage精灵变得更容易。
LSImage类有以下属性
@property (nonatomic, readonly) CGSize size;
图像大小,以点为单位。与 UIImage 相同,在视网膜显示设备上,实际像素维度可能是大小的两倍,具体取决于缩放属性。
@property (nonatomic, readonly) CGFloat scale;
图像缩放。对于 Retina 显示设备上的 @2x 图像,此值将为 2.0。
@property (nonatomic, readonly) CGRect contentsRect;
用于裁剪和调整原始图像以适应 LSImage 大小的裁剪矩形。此矩形以单位坐标衡量,因此对于未经裁剪的图像,contentsRect 的大小将为企业{0, 0, 1, 1}。
@property (nonatomic, readonly) CGPoint anchorPoint;
用于定位精灵的中心点,相对于精灵边界以单位坐标衡量。通常这将为企业{0.5, 0.5},但如果精灵已被裁剪,则此值将调整以补偿。
@property (nonatomic, readonly) CGAffineTransform transform;
当图像显示时应应用的转换。通常这将是企业恒等变换或 90 度旋转,用于在精灵旋转以适合图像地图时。
@property (nonatomic, readonly) CGImageRef CGImage;
LSImage 使用的底层 CGImage。您可以使用它将图像绘制到 CGContext 中,或直接设置 CALayer 的 contents 属性(而不是使用 setContentsWithLSImage: 类方法。
LSImage 类具有以下方法
+ (LSImage *)imageWithUIImage:(UIImage *)image
contentsRect:(CGRect)contentsRect
anchorPoint:(CGPoint)anchorPoint
rotated:(BOOL)rotated;
- (LSImage *)initWithUIImage:(UIImage *)image
contentsRect:(CGRect)contentsRect
anchorPoint:(CGPoint)anchorPoint
rotated:(BOOL)rotated;
这些方法创建具有指定 contentsRect、anchorPoint 和可选 90 度旋转的 LSImage。这当手动从现有图像创建精灵时很有用。请注意,LSImage 保留原始源图像但不复制它。
- (void)drawAtPoint:(CGPoint)point;
此方法在指定点绘制图像并应用正确的裁剪和方向。与等价的 UIImage 相比,此方法将在点中心绘制精灵图像,而不是从点向下和向左绘制。中心化将取决于 anchorPoint,并且可能不是图像的实际中心。
- (void)drawInRect:(CGRect)rect;
此方法在指定矩形内绘制图像并应用正确的裁剪和方向。请注意,如果矩形的纵横比与 size 属性不匹配,图像将出现拉伸。anchorPoint 和 size 被忽略。
- (CGRect)rectWhenDrawnAtPoint:(CGPoint)point;
此方法在指定点绘制图像时返回图像的边界矩形。将此方法的输出传递给 drawInRect:
方法等价于调用 drawAtPoint:
的相同点。
LSImage 通过以下方法扩展 CALayer
- (void)setContentsWithLSImage:(LSImage *)image;
此方法设置层内容图像和关联属性(contentsRect、contentsScale、affineTransform),以正确显示 LSImage。此方法不设置 anchorPoint 或层边界。
- (void)setDimensionsWithLSImage:(LSImage *)image;
此方法设置精灵的边界和锚点。如果精灵没有被裁剪,则这不是必需的,但如果精灵已被从原始大小裁剪,则必须正确显示精灵。
LSImageMap 类具有以下方法
+ (LSImageMap *)imageMapWithContentsOfFile:(NSString *)nameOrPath;
- (LSImageMap *)initWithContentsOfFile:(NSString *)nameOrPath;
这些方法用于从文件中创建LSImageMap。参数可以是一个绝对或相对文件路径(假定相对路径位于应用程序包内部)。如果省略了文件扩展名,则假定是一个Xcode 5 .atlasc文件(见下文"使用Xcode 5 / SpriteKit纹理图集"),或一个.plist。目前支持的唯一图像映射文件格式是Xcode 5 / SpriteKit纹理图集格式,以及Cocos2D精灵图格式,这些格式可以通过Zwoptex或TexturePacker等工具导出。LSImageMap完全支持旋转和裁剪的图像,以及图像别名。它将自动检测@2x Retina图像映射文件和具有~ipad后缀的文件。
+ (LSImageMap *)imageMapWithUIImage:(UIImage *)image data:(NSData *)data;
- (LSImageMap *)initWithUIImage:(UIImage *)image data:(NSData *)data;
这些方法用于从数据中创建LSImageMap。数据应表示图像映射文件的内容,该内容是imageMapWithContentsOfFile:
方法支持的一种格式。如果图像参数为nil,LSImageMap将尝试从数据中指定的文件名定位图像文件,但如果图像文件不在应用程序包的根目录中,则可能无法找到它。在这种情况下,您可以提供用作图像映射图像的UIImage,而数据中指定的图像文件将被忽略。
- (NSInteger)imageCount;
此方法返回图像映射中的图像数量。
- (NSString *)imageNameAtIndex:(NSInteger)index;
此方法返回指定的索引处的图像名称。图像名称按字母顺序排序,不一定反映它们在精灵表文件中出现的顺序。
- (LSImage *)imageAtIndex:(NSInteger)index;
- (LSImage *)objectAtIndexedSubscript:(NSInteger)index;
这些方法返回指定的索引处的图像映射图像。这两种方法的行为方式相同,但第二种方法包括以支持对象下标,允许使用spritemap[index]
语法访问精灵。图像映射图像按字母顺序排序,不一定反映它们在精灵表文件中的出现顺序。如果您希望按特定顺序访问图像,最好将它们的名称命名为数字,并用零填充相同长度的长度。
- (LSImage *)imageNamed:(NSString *)name;
- (LSImage *)objectForKeyedSubscript:(NSString *)name;
这些方法返回具有指定名称的图像映射图像。这两种方法的行为方式相同,但第二种方法包括以支持对象下标,允许使用spritemap[@"spriteName"]
语法访问精灵。根据生成图像映射数据文件的工具,名称可能包含文件扩展名。如果未在名称参数中包含文件扩展名,则假定png。
- (instancetype)initWithImage:(LSImage *)image;
使用指定图像创建一个新的LSImageView。内容模式设置为UIViewContentModeCenter。框架设置为在不裁剪的情况下显示整个图像所需的最小大小(如果启用了clipsToBounds),这可能比精灵本身的大小还要大,如果精灵的锚点不在中心。
@property (nonatomic, strong) LSImage *image;
此属性可以用来设置图像。它不会调整视图的大小。
LSImageMap支持快速枚举,因此您可以轻松地使用以下语法遍历映射中的精灵
LSImageMap *imageMap = [LSImageMap imageMapWithContentsOfFile:@"foo.plist"];
for (NSString *name in imageMap)
{
LSImageSprite *sprite = imageMap[name];
//do something with sprite
}
使用LayerSprites加载的精灵图像有多种显示方式。最简单的方法是使用LSImageView,它的工作方式类似于常见的UIImageView。要么通过代码或Interface Builder创建LSImageView的实例,并使用LSImage设置图像属性,例如
//create image view
LSImageView *view = [[LSImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
//set the image
view.image = image;
或者,您可以直接创建LSImageView并使用LSImage,这将自动设置大小以适应精灵
//create image view
LSImageView *view = [[LSImageView alloc] initWithImage:image];
或者,您可以在 CALayer 内显示一个 LSImage。为此,请使用以下代码:
//create layer
CALayer *layer = [CALLayer layer];
//set sprite image and dimensions
[layer setContentsWithLSImage:image];
[layer setDimensionsWithLSImage:image];
//set position and add to screen
layer.position = CGPointMake(..., ...)
[someView.layer addSublayer:layer];
查看 LayersDemo 了解此操作的示例。如果您正在更新已在屏幕上添加的精灵图像,您可能希望禁用隐式动画,如下所示:
//disable animation
[CATransaction transaction];
[CATransaction setDisableActions:YES];
//set sprite image and dimensions
[layer setContentsWithLSImage:image];
[layer setDimensionsWithLSImage:image];
//re-enable animation
[CATransaction commit];
CATransaction 代码在设置层内容和设置其他属性时需要禁用隐式动画。您可以在同一事务中设置许多精灵,因此事务代码不包括在设置器方法中。您还可以通过指定自定义操作字典等其它方式禁用隐式动画。您不必禁用动画,但切换精灵间的默认动画效果可能不是您期望的。
注意1:因为 setContentsWithLSImage: 方法设置了层的 affineTransform,您需要在设置精灵后重新应用该层上的任何转换/affineTransform。确保保留现有转换,否则精灵可能会定位不当。您可以这样操作:
//create a new transform
CATransform3D transform = //some transform
//set sprite transform without affecting sprite orientation
layer.transform = CATransform3DConcat(layer.transform, transform);
注意2:如果精灵已被裁剪和旋转,则似乎不可能在带有视图支持层的场景下可靠地使用 setDimensionsWithLSImage: 方法。当锚点不是 {0.5, 0.5} 时,支持层不会正确旋转。如果您希望在视图中放置精灵,则可以使用嵌套子层,或者在导出精灵图集时禁用裁剪和/或旋转。
尽管将精灵设置为 CALayer 的内容可以获得最佳性能和内存使用,但您也可以使用 drawAtPoint: 或 drawInRect: 方法将精灵直接绘制到一个 CGContext 中。请参阅 DrawingDemo 了解示例。
LayerSprites 可以加载存储在 Xcode 5 / SpriteKit 纹理图集格式的精灵。要使用纹理图集,首先创建一个包含所有精灵图像(包括标准版本和 @2x 变种的图像)的文件夹,并附加扩展名 .atlas 到项目中。
然后,在您项目的构建设置中,搜索“SpriteKit”,并将“启用纹理图集生成”选项设置为(如果您尚未导入图集,则可能显示为 SPRITEKIT_TEXTURE_ATLAS_OUTPUT),默认的“输出纹理图集格式”为“RGBA8888_PNG”。
无需导入 SpriteKit 框架。当使用 LSImageMap +imageMapWithContentsOfFile 方法导入精灵图集时,请指定文件扩展名“atlasc”(注意“c”),或省略路径扩展名。如果可行,LSImageMap 将自动找到图集文件。
您需要使用 Xcode 5 或更高版本来生成图集文件,但它们可以被 LayerSprites 加载和使用,适用于运行 iOS 4.3 和以上版本的 APP - 它们不仅限于 iOS 7。
请查看 TextureAtlasDemo 了解使用 Xcode 5 纹理图集的示例。