iOS、SpriteKit 将 SKTextureAtlas/SKTexture 转换为 UIImage

Posted

技术标签:

【中文标题】iOS、SpriteKit 将 SKTextureAtlas/SKTexture 转换为 UIImage【英文标题】:iOS, SpriteKit convert SKTextureAtlas/SKTexture into UIImage 【发布时间】:2020-03-09 02:08:13 【问题描述】:

我正在尝试从 SKTexture 检索 UIImage,其中 SKTexture 来自 SKTextureAtlas。 由于 .cgImage() 不适用于 Atlases,因此这更难。

无论如何,我想出了使用 CoreGraphic 的解决方案,但是,这似乎也不起作用。 也许你能帮助我在这里做错了什么?

func image(with view: SKView) -> UIImage 
    let format = UIGraphicsImageRendererFormat.default()
    format.scale = UIScreen.main.scale
    format.opaque = false
    let renderer = UIGraphicsImageRenderer(size: view.bounds.size, format: format)
    let image = renderer.image  ctx in
        view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
    
    return image


func image(texture: SKTexture) -> UIImage 
    let view = SKView(frame:CGRect(x: 0, y: 0, width: texture.size().width, height: texture.size().height))
    let scene = SKScene(size: texture.size())
    let sprite  = SKSpriteNode(texture: texture)
    sprite.position = CGPoint(x: view.frame.midX, y: view.frame.midY)
    scene.addChild(sprite)
    view.presentScene(scene)
    return image(with: view)


let uiImage = image(texture: SKTexture(imageNamed: "HeavyCrossbow.png"))[!

[]

此解决方案不适用于 SKTextureAtlas 和 SKTextureAtlas 知道我错过了什么,如何实现它?

干杯, 西门

【问题讨论】:

为什么 cgimage 不能用于地图集? @Knight0fDragon 来自 SKTextureAtlas 的 SKTexture 不支持 mipmapping。 ***.com/a/22066288/2308303 这是一个已有 6 年历史的答案,现在甚至可能不适用 此外,mip 映射和 cgImage 是两个不同的东西。我使用 cgImage 临时修复了最近引入的 skphysics 错误,所以最后我知道,它正在工作。 从 13.3.1 开始,用于图集中纹理的 cgImage 已损坏,至少在某些设备上是这样。 github.com/bg2b/bugtest 渲染到新纹理是我发现的唯一可行的解​​决方法。 【参考方案1】:

好的,周末后我终于开始工作了。 重要的部分是

guard let render = view.texture(from: sprite) else  return UIImage() 
return UIImage(cgImage: render.cgImage())

感谢answer

完整的工作代码:

func image(texture: SKTexture) -> UIImage 
    let view = SKView(frame:CGRect(x: 0, y: 0, width: texture.size().width, height: texture.size().height))
    let scene = SKScene(size: texture.size())
    let sprite  = SKSpriteNode(texture: texture)
    sprite.position = CGPoint(x: view.frame.midX, y: view.frame.midY)
    scene.addChild(sprite)
    view.presentScene(scene)

    guard let render = view.texture(from: sprite) else  return UIImage() 
    return UIImage(cgImage: render.cgImage())

我想让它工作的原因是我正在使用 SpriteKit 编写游戏,但是 UI 是使用 SwiftUI 完成的。

【讨论】:

如果您正在这样做,那为什么还要首先使用地图集......您将失去地图集提供的所有好处。 @Knight0fDragon atlas 用于游戏,我只是不会为 UI 创建单独的对象。我现在正在开发关卡编辑器,您可以在其中从 SwiftUI 切换画笔等。这个 UI 我基于 SKScene 内容和 SKTileGroups @Knight0fDragon 看看这里:github.com/shial4/SpriteKit-SwiftUI-Template 我已经为 SpriteKit + SwiftUI 创建了模板。这就是我处理我的项目的方式:)

以上是关于iOS、SpriteKit 将 SKTextureAtlas/SKTexture 转换为 UIImage的主要内容,如果未能解决你的问题,请参考以下文章

SpriteKit SKTexture.preloadTextures 高内存使用 Swift

如何将带有 alpha 的 PNG 转换为 RGBA4444 以便在 SpriteKit SKTexture 中使用它?

SpriteKit SKTexture mipmap 不起作用

UIImage 中的 SKTexture 看起来不同

如何在 SKSpriteNode 中“居中”SKTexture

Swift SpriteKit - 防止精灵节点角旋转