在 Sprite Kit iOS 中使用一个图像精灵表

Posted

技术标签:

【中文标题】在 Sprite Kit iOS 中使用一个图像精灵表【英文标题】:Use a one image sprite sheet in Sprite Kit iOS 【发布时间】:2013-12-14 19:50:49 【问题描述】:

我有一张包含我的精灵动画图像的精灵表。 如何在不拆分单个文件的情况下将这些图像放入 SKTextureAtlas(以便我可以在 SKAction 中制作动画)?我以前见过并做过,但是不使用 SpriteKit 和/或 SKTextures。

这甚至可以在不拆分文件的情况下实现吗? 最坏的情况:我需要将工作表分开图像。

过去我只是做了一个方法,其中包含精灵大小和精灵总数,这些精灵在代码中分离图像,然后通过动画处理。

提前感谢您的帮助!

附:我是 SpriteKit 新手,但对游戏编程或 ios 不熟悉

【问题讨论】:

感谢您提出这个问题并发布您的结果代码。这正是我所需要的。 【参考方案1】:

感谢@LearnCocos2D 的家伙指出我使用textureWithRect:inTexture: 我在我的自定义Entity : SKSpriteNode 类中创建了一个自定义init 方法,它允许使用一个包含所有图像的精灵表。我试图包含一些 cmets 来解释代码。我有这个版本扫描 x,因为我的动画是水平的。 Y 只能通过调用的方法更改。不在此版本的方法中。

一定要放在界面里!

分配初始化时的示例:

Entity *cookie = [[Entity alloc] initWithSpriteSheetNamed:@"cookie_sheet" withinNode:map sourceRect:CGRectMake(0, 0, 32, 32) andNumberOfSprites:6];

Entity中的方法:SKSpriteNode

- (id) initWithSpriteSheetNamed: (NSString *) spriteSheet withinNode: (SKSpriteNode *) scene sourceRect: (CGRect) source andNumberOfSprites: (int) numberOfSprites 

    // @param numberOfSprites - the number of sprite images to the left
    // @param scene - I add my sprite to a map node. Change it to a SKScene
    // if [self addChild:] is used.

    NSMutableArray *mAnimatingFrames = [NSMutableArray array];

    SKTexture  *ssTexture = [SKTexture textureWithImageNamed:spriteSheet];
    // Makes the sprite (ssTexture) stay pixelated:
    ssTexture.filteringMode = SKTextureFilteringNearest;

    float sx = source.origin.x;
    float sy = source.origin.y;
    float sWidth = source.size.width;
    float sHeight = source.size.height;

    // IMPORTANT: textureWithRect: uses 1 as 100% of the sprite.
    // This is why division from the original sprite is necessary.
    // Also why sx is incremented by a fraction.

    for (int i = 0; i < numberOfSprites; i++) 
        CGRect cutter = CGRectMake(sx, sy/ssTexture.size.width, sWidth/ssTexture.size.width, sHeight/ssTexture.size.height);
        SKTexture *temp = [SKTexture textureWithRect:cutter inTexture:ssTexture];
        [mAnimatingFrames addObject:temp];
        sx+=sWidth/ssTexture.size.width;
    

    self = [Entity spriteNodeWithTexture:mAnimatingFrames[0]];

    animatingFrames = mAnimatingFrames;

    [scene addChild:self];

    return self;

【讨论】:

酷,我会试试这段代码。但是,我主要是想避免不得不手动切碎一些精灵表。 Shoebox 解决了我的问题,因为我现在可以使用提取的精灵制作纹理图集。 textureWithRect 很快吗?我相信 TextureAtlas 也会优化绘图,因为它从同一个纹理中提取所有内容。所以对我来说似乎更可取。 我不确定速度,但据我所知,.atlas 所做的只是将多个图像放在一起。我相信所有图像仍然需要存储在一个数组中以供以后使用,因为 [SKAction animateWithTextures:] 需要一个数组。我将来也可能会使用该程序。好消息是 textureWithRect 每次启动只需要发生一次。但如果它是由 Apple 编写的,它可能会更好。 在参考资料中它说“Sprite Kit 使用纹理图集来提高渲染性能。”另外——“如果每个纹理都被视为一个单独的对象,那么 Sprite Kit 和图形硬件必须更加努力地渲染场景——你的游戏性能可能会受到影响。具体来说,Sprite Kit 必须为每个纹理至少进行一次绘制。” 因此,由于纹理图集只有 1 个纹理,并且可能只是在该纹理上存储给定帧的位置和尺寸,因此它可能会明显更快,尤其是在您有大量纹理的情况下. ShoeBox 解决方案是一次非常少的一次提取,它允许我对单个纹理进行渲染优化。 我也在浏览那个文档。见清单 2-8。地图集使一个图像存储在内存中。然后查看它并将图集中的每个纹理存储到一个数组中。 (供以后使用)。紧接着:“如果你已经有一个 SKTexture 对象,你可以创建引用它的一部分的新纹理。这种方法很有效,因为新的纹理对象引用内存中的相同纹理数据。(这种行为类似于纹理图集。)”实际上,对我来说,这归结为艺术家和程序员的个人工作流程。【参考方案2】:

您需要将每个动画帧作为单独的图像。然后,您可以使用 SKAction 对图像进行动画处理,也可以选择使用 SKTextureAtlas。

所以是的,除非您编写自定义动画处理程序来手动更改动画精灵的纹理矩形,否则您必须拆分现有工作表。您可以使用 textureWithRect:inTexture: 从 spritesheet 纹理创建更小的纹理。

【讨论】:

谢谢,正是我需要知道的。 @Keely 如果您为此目的创建一个类,我会对它非常感兴趣。我的清单上有这个问题要在下周解决。正在考虑可能已经有解决方案。我有一些我想使用的精灵表,而不必将它们分开。虽然也可能有一个工具!前往谷歌... renderhjs.net/shoebox/extractSprites.htm - 非常酷,如果您需要从 spritesheet 转到单个图像。 @prototypical 很酷的链接。但我决定先上课。无论如何,它运作良好。我认为代码比较干净。我愿意接受任何建议。 (是新的“接受的答案”)

以上是关于在 Sprite Kit iOS 中使用一个图像精灵表的主要内容,如果未能解决你的问题,请参考以下文章

如何在 iOS Sprite Kit 中裁剪两张图像并拼接成一张?

背景图像大小 Sprite Kit 游戏

在 Sprite-Kit 中更改精灵图像

iOS Sprite Kit didBeginContact 无法正常工作

使用 Touch iOS Sprite Kit 画线

iOS 7 Sprite Kit 动画速度变化