Search code examples
iosswiftanimationparticlescaemitterlayer

iOS create falling leaves animations using CAEmitterLayer


I want to create a leaves falling animation this is my code :

 private func setupEmitter() {


    let size = self.bounds.size

    let emitter             = CAEmitterLayer()
    emitter.emitterSize     = CGSize(width: size.width, height: 1)
    emitter.emitterPosition = CGPoint(x: size.width / 2, y: -100)
    emitter.emitterShape    = kCAEmitterLayerLine
    self.layer.addSublayer(emitter)

    //SHAPE 1
    let shape1 = CAEmitterCell()
    shape1.birthRate = 10
    shape1.lifetime = 7
    shape1.lifetimeRange = 2
    shape1.velocity = 110
    shape1.velocityRange = 10
    shape1.emissionLongitude = CGFloat(M_PI)
    shape1.emissionRange = CGFloat(M_PI_4)
    shape1.spin = 0.2
    shape1.spinRange = 0
    shape1.scaleSpeed = -0.05
    shape1.scale  = -0.3
    shape1.scaleRange = -0.1
    shape1.contents = UIImage(named: "shape1")?.cgImage


    //SHAPE 2
    let shape2 = CAEmitterCell()
    shape2.birthRate = 10
    shape2.lifetime = 7
    shape2.lifetimeRange = 2
    shape2.velocity = 110
    shape2.velocityRange = 90
    shape2.emissionLongitude = CGFloat(M_PI)
    shape2.emissionRange = CGFloat(M_PI_4)
    shape2.spin = 0.2
    shape2.spinRange = 0.5
    shape2.scaleSpeed = -0.05
    shape2.scale  = -0.35
    shape2.scaleRange = 0
    shape2.contents = UIImage(named: "shape2")?.cgImage

    emitter.emitterCells = [shape1, shape2]


}

What I get from the above code:

Drawing of what I want to achieve:

So how could I update my code to achieve what I want (Objective-C code are accepted )?


Solution

  • Unfortunately this isn't easy, or simple, nor can I can simply say "here's the code that does this!"

    There are multiple ways to achieve the goal, none of them ideal, all of them tricky in different ways.

    These motions of leaves, as they float down, is them reaching a velocity at which they become aerodynamically efficient, stalling and then falling again... it's either a physics system you need, or behaviours coded as responses to rates of falling.

    Physics:

    Core Animation particles don't have enough physics responsiveness to do this, so you'll need to use SKSpriteNodes impacted by a combination of forces and fields, or CALayers influenced by UIKit Dynamics variations on forces and fields.

    These two things are pretty much the same: CALayers are a more powerful and fun variation of SKSpriteNodes, and UIKit Dynamics is much the same as SKPhysics.

    However... if you want to go this route, of building your own 'particle' system that responds to forces and fields, I'd strongly suggesting using SceneKit's particles, as they have rotational (in 3D) abilities for the particles, built in, and it's a system very efficient when handling MANY different particle emitters, each with their own fields they're responding to.

    Algorithmically:

    This is something that involves creating randomisation of arcs to stalls, and then acceleration into another arc downward, aerodynamic influence, and subsequent stall, over and over again.

    This would also need to be custom particles, as I don't think there's a way to sufficiently directly influence CAEmitter Particles, nor those of SpriteKit or SceneKit.

    Which means you have to create quads in OpenGL, CALayers that are simple images of leaves, SKSpriteNodes that are leaves, or Quads in SceneKit that have a leaf texture.

    In each case, you need as many layers or objects as you need leaves.

    The advantage of CALayers is that they have 3D rotation built in, and you already seem to have some grasp of Core Animation.