简体   繁体   中英

Is it possible to animate SKTexture with images?

I created a SKEmitterNode and I want the particleTexture property to animate images.

This is what I'm trying, but it is only showing the first image:

let animationImages = [UIImage(named: "image1")!, UIImage(named: "image2")!]

  let imageView = UIImageView()
  imageView.image = UIImage.animatedImage(with: animationImages, duration: 1)
  imageView.startAnimating()

  emitter.particleTexture = SKTexture(image: imageView.image!)

Your last line will always return the same "main" image, regardless of the animation. This was confirmed elsewhere on this site already, but see also Apple's documentation of UIImageView.image .

But even if you did manage to obtain the current image, it would still be a one-time assignment, and the texture wouldn't update automatically; that's something you will need to do yourself; as Apple puts it in Animating a Sprite by Changing its Texture in Apple's SpriteKit reference:

A sprite's texture property points to its current texture. You can change this property to point to a new texture.

Supposed solution: particle action (doesn't seem to work since iOS 9)

Luckily, there's an SKAction to do just that (see the last link for some details), and it can theoretically even be applied to SKEmitterNode particles (something I just found out as I was about to tell you the opposite):

let animationTextures = [SKTexture(imageNamed: "image1"),
                         SKTexture(imageNamed: "image2"),
                         SKTexture(imageNamed: "image3")]
let animationAction = SKAction.repeatForever(SKAction.animate(with: textures, timePerFrame: 0.1))
emitter.particleAction = animationAction

EDIT: It doesn't work, and hasn't worked for years: particleAction s are simply being ignored. It's quite incredible that Apple wouldn't fix such an obvious bug for half a decade, but this seems to be the case.

Workaround: implement your own emitter

SKEmitterNode s have a lot going for them (this bug notwithstanding):

  • Particles are lightweight, stripped-down SKSpriteNode -like thingies that are optimized for being thrown around in huge numbers without all the overhead associated with full-blown sprite nodes.
  • Emitters can be built in a visual designer in XCode, which saves a lot of time compared to programmatically creating everything.

However, I already found myself in a situation once where I was forced to implement my own "emitter." In my case, it involved little more than writing a method creating a fixed number of sprite nodes, and attaching a complex action (three levels of hierarchy of multiple groups and sequences) to each of them that controlled their movement, scale, alpha, and eventual disappearance (removal from parent). It was not a huge amount of work, and it gave me the precise control I needed over the particle animations that an emitter node couldn't provide – but I was lucky in that I only needed to emit a few dozen particles at a time.

I'd say implementing your own emitter would make the most sense if all of the following conditions are true:

  • You really need texture animation and can't wait for Apple to fix that bug, and/or you need some other particle behaviors that SKEmitterNode doesn't provide; and
  • you don't need a huge number of particles, especially concurrent particles (so that performance remains acceptable); and
  • you don't mind doing all the emitter design work programmatically, without the visual designer – although you can still prototype your emitter as an SKEmitterNode in Xcode, and re-use the parameters of your prototype in your final implementation; and
  • your particle animations (ie all changes in position, scale, alpha, rotation, tint, texture (the reason why you'd do this in the first place)) are not too overwhelming to specify all: in my case, I only had to implement one special case (whose complexity I could still manage), but if I'd had a need to design multiple emitters like this, I would have probably ended up creating a class with an API comparable to that of SKEmitterNode , which may not be a trivial task.

Once again, good luck: SpriteKit could be a fantastic framework if only Apple got around to fixing some of its pretty outrageous bugs. (I'm having issues with custom shaders… Maybe you will see a question or two from me in the near future.)

  let image1 = SKAction.run( { emitter.particleTexture = SKTexture(imageNamed: "image1") } )
  let image2 = SKAction.run( { emitter.particleTexture = SKTexture(imageNamed: "image2") } )
  let image3 = SKAction.run( { emitter.particleTexture = SKTexture(imageNamed: "image3") } )
  
  let seq = SKAction.sequence([image1, wait, image2, wait, image3, wait])
  let repeater = SKAction.repeatForever(seq)
  emitter.run(repeater)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM