2

I'm developing an ios app. I have a SKSpriteNode on screen and I'm getting a drawing from the user that I'm storing as SKTexture. I would like to combine these two and introduce them as a new SKSpriteNode.

THE PROBLEM: I cannot find documentation about how to merge SKSpriteNode into SKTexture. I'm sure there's a way to do this. Would someone have example code for this?

user594883
  • 1,329
  • 2
  • 17
  • 36

4 Answers4

3

You can use a container that will hold two sprites, and create a texture from it, using SKView's texture(from:) method, like this:

override func didMove(to view: SKView) {

        backgroundColor = .black

        let container = SKNode()

        let left = SKSpriteNode(color: .purple, size: CGSize(width: 100, height: 100))
        let right = SKSpriteNode(color: .yellow, size: CGSize(width: 100, height: 100))

        container.addChild(left)
        container.addChild(right)

        left.position.x = 50
        right.position.x = -50

        addChild(container)

        if let texture = view.texture(from: container) {
            let sprite = SKSpriteNode(texture:texture)
            addChild(sprite)
            sprite.run(SKAction.moveTo(y: 300, duration: 5))
        }

    }

If you want create a texture from a portion of node's content, then you can do some cropping using SKView's texture(from:crop:) method.

Whirlwind
  • 14,286
  • 11
  • 68
  • 157
  • If I understand correctly I have to add this to scene before it can work? I don't think I want to do that. – user594883 Apr 16 '17 at 05:16
  • @user594883 If you are already using sprites, I thought they are already added to the scene. Why do you use them if they are not part of the scene? – Whirlwind Apr 16 '17 at 15:37
0

Not sure what you mean by "merge". If you want to create a new SKSpriteNode using an existing SKTexture then this may be the code you're looking for:

    let newSprite = SKSpriteNode(texture: yourSKTexture)
JohnV
  • 981
  • 2
  • 8
  • 18
  • I want to combine new `SKTexture` with an existing `SKSpriteNode` so I guess I basically need to combine two textures into one. – user594883 Apr 15 '17 at 06:17
  • Maybe create a new SKSpriteNode with the new SKTexture and add that sprite node as a child of the existing sprite node. Depending on how you want to combine the two texutures, you may need to set z positions, alpha, blending factors, etc. Not sure if this will be the effect you're looking for. Maybe someone else can suggest something better. – JohnV Apr 15 '17 at 07:04
  • The effect would be the same but I'm iterating my nodetree multiple times during a game scene. If I add the textures as separate SKSpriteNodes, It'll be expensive. Thanks for your suggestion though! – user594883 Apr 15 '17 at 07:27
  • Maybe this will be of help: http://stackoverflow.com/questions/23091001/how-to-combine-sktextures. It's objective c, but should be easy to translate into Swift. What they do there is merge images into a UIImage, and then use that UIImage as a texture for the sprite node. – JohnV Apr 15 '17 at 07:38
0

You will probably have to use CoreGraphics to do this. Convert both SKTextures to CGImage using SKTexture.cgImage() method, combine them using CoreGraphics and then create a new texture from the result. SKTexture.init(cgImage:) method let you use a CGImage object to construct the texture.

I haven't used Core Graphics much, but here are a few links to related reads. I think you will want to use the CGLayer class to tell CoreGraphics how to stack the textures and reuse the sprite texture over time so CoreGraphics can cache it to make things faster.

Core Graphics uses Quartz 2D to do fast 2D graphics operations. I haven't played much with it, but I think it should be what you are looking for.

References :

Keep me posted, I think it's very interesting!

EDIT 1: You will also have to use an SKMutableTexture on the sprite. That class allows for the texture data to be changed dynamically.

BadgerBadger
  • 696
  • 3
  • 12
0

Problem: You have two or more SKSpriteNodes and want them combined into a single new SKSpriteNode.

Why?: It is used to reduce the amount of Nodes to increase performance. If you're using massive amounts of static sprites, you can benefit from this method.

Solution: Instance an SKView object and use it to render a container SKSpriteNode with multiple child SKSpriteNodes.

let mergedTexture = SKView().texture(from: containerNode)

let newNode = SKSpriteNode(texture: mergedTexture)

Whereby containerNode is the SKNode container with multiple SKSpriteNode children. This is what user Whirlwind suggested, but he used an existing SKView instance, that may not be available in your context. I successfully use this method in my project (macOS) to achieve OPs goal "to merge SKSpriteNode into SKTexture".

Using Xcode 13.4.1 on macOS 12.4

M.S.
  • 1
  • 1