6 炫酷的粒子效果

炫酷的动画效果是一款游戏必不可少的组成部分。前面向读者介绍了CoreAnimation框架中提供给开发者的一些动画方式,然而那些动画方式都是宏观上的、有序的、轨迹确定的规则的动画,对于微观的、无序的、轨迹无法预测的随机的动画,前边介绍的所有方法都无法满足需求,但是CoreAnimation框架不会令人失望,CAEmitterLayer类可以创建出效果炫酷的粒子动画,有了这个类,将使创建一些十分复杂的动画效果变得容易而轻松。

6.1 粒子发射器——CAEmitterLayer

粒子效果的创建基于两个部分,一个部分是粒子发射器,用于配置粒子的整体效果,另一部分是粒子单元,用于配置粒子的具体属性。CAEmitterLayer继承自CALayer。 CAEmitterLayer中常用的属性及意义如下所示。

//粒子单元数组,例如你在绘制火焰的效果时,你可以创建两个单元,一个单元负责烟雾,一个单元负责火苗。
open var emitterCells: [CAEmitterCell]?
//粒子的创建速率,默认为1/s。
open var birthRate: Float
//粒子的存活时间。默认为1S。
open var lifetime: Float
//发射器在xy平面的中心位置
open var emitterPosition: CGPoint
//发射器在Z轴的位置
open var emitterZPosition: CGFloat
//发射器的尺寸大小
open var emitterSize: CGSize
//发射器的深度,在某些模式下会产生立体效果
open var emitterDepth: CGFloat
//发射器的形状
open var emitterShape: String
//发射器的发射模式
open var emitterMode: String
//发射器渲染模式
open var renderMode: String
//是否开启景深效果
open var preservesDepth: Bool
//粒子的运动速度
open var velocity: Float
//粒子的缩放大小
open var scale: Float
//粒子的旋转位置
open var spin: Float

上面属性中,emitterShape属性决定粒子发射器的形状,可选参数如下所示。 //点形状,粒子从一个点发出 public let kCAEmitterLayerPoint: String //线形状,粒子从一条线出发 public let kCAEmitterLayerLine: String //矩形形状,粒子从一个矩形中发出 public let kCAEmitterLayerRectangle: String //立方体形状,会影响Z平面的效果 public let kCAEmitterLayerCuboid: String //圆形,粒子会在圆形范围发射 public let kCAEmitterLayerCircle: String //球形 public let kCAEmitterLayerSphere: String emitterMode属性决定粒子在粒子发射器中发射的位置,可选参数如下所示。 //从发射器中发出 public let kCAEmitterLayerPoints: String //从发射器边缘发出 public let kCAEmitterLayerOutline: String //从发射器表面发出 public let kCAEmitterLayerSurface: String //从发射器中点发出 public let kCAEmitterLayerVolume: String renderMode属性设置发射器的粒子渲染模式,可选参数如下所示。 //粒子无需出现,多个发射源混合 public let kCAEmitterLayerUnordered: String //声明久的粒子会被渲染在最上层 public let kCAEmitterLayerOldestFirst: String //年轻的粒子会被渲染在最上层 public let kCAEmitterLayerOldestLast: String //粒子的渲染按照z轴的前后顺序进行 public let kCAEmitterLayerBackToFront: String //这种模式会进行粒子混合 public let kCAEmitterLayerAdditive: String

6.6.2 粒子单元——CAEmitterCell

CAEmitterLayer中的属性主要对粒子的创建周期,发射速度等整体属性进行设置,而具体粒子的UI展现,颜色速度以及各种随机选项等是由粒子单元CAEmitterCell来进行设置与维护的。 CAEmitterCell中常用属性及意义如下所示。

//设置发射单元的名称
open var name: String?
//粒子的创建速率
open var birthRate: Float
//粒子的生存时间
open var lifetime: Float
//粒子的生存时间容差
open var lifetimeRange: Float
//粒子在Z轴方向的发射角度
open var emissionLatitude: CGFloat
//粒子在xy平面的发射角度
open var emissionLongitude: CGFloat
//粒子发射角度的容差
open var emissionRange: CGFloat
//粒子的速度
open var velocity: CGFloat
//粒子速度的容差
open var velocityRange: CGFloat
//粒子x,y,z三个方向的加速度
open var xAcceleration: CGFloat
open var yAcceleration: CGFloat
open var zAcceleration: CGFloat
//粒子的缩放大小,缩放容差和缩放速度
open var scale: CGFloat
open var scaleRange: CGFloat
open var scaleSpeed: CGFloat
//粒子的旋转度与旋转容差
open var spin: CGFloat
open var spinRange: CGFloat
//粒子的颜色
open var color: CGColor?
//粒子在R.G,B三个色相上的容差和透明度的容差
open var redRange: Float
open var greenRange: Float
open var blueRange: Float
open var alphaRange: Float
//粒子在RGB三个色相上的变化速度和透明度的变化速度
open var redSpeed: Float
open var greenSpeed: Float
open var blueSpeed: Float
open var alphaSpeed: Float
//粒子的渲染对象,可以设置为一个CGImage的对象
open var contents: Any?

6.3 创建粒子火焰动画

6.1与6.2小节介绍了一些iOS中创建粒子效果相关类的基础知识,本节将通过实战演练创建一个火焰效果的粒子动画来使读者更加深刻的理解粒子效果的创建方法,更加熟练的应用粒子效果相关方法来完成复杂的粒子动画。

使用Xcode开发工具创建一个名为MyFire的工程,在ViewController类中声明如下属性。

private var fireEmitter:CAEmitterLayer?//粒子发射器

在viewDidLoad方法中添加如下代码。

    super.viewDidLoad()
        self.view.backgroundColor = UIColor.black
        //设置发射器
        fireEmitter = CAEmitterLayer()
        fireEmitter?.emitterPosition = CGPoint(x: self.view.frame.width/2, y: self.view.frame.height-20)
        fireEmitter?.emitterSize = CGSize(width: self.view.frame.width-100, height: 20)
        fireEmitter?.renderMode = kCAEmitterLayerAdditive
        //设置发射单元
        let fire = CAEmitterCell()
        fire.birthRate = 1600
        fire.lifetime = 4.0
        fire.lifetimeRange = 1.5
        fire.color = UIColor(red: 0.8, green: 0.4, blue: 0.2, alpha: 0.1).cgColor
        fire.contents = UIImage(named:Particles_fire).cgImage
        fire.name = "fire"
        fire.velocity = 160
        fire.velocityRange = 80
        fire.emissionLongitude = CGFloat(M_PI+M_PI_2)
        fire.emissionRange = CGFloat(M_PI_2)
        fire.scaleSpeed = 0.3
        fire.spin = 0.2
        //烟雾
        let smoke = CAEmitterCell()
        smoke.birthRate = 800
        smoke.lifetime = 6.0
        smoke.lifetimeRange = 1.5
        smoke.color = UIColor(red: 1, green: 1, blue: 1, alpha: 0.05).cgColor
        smoke.contents = UIImage(named:Particles_fire).cgImage
        smoke.name = "smoke"
        smoke.velocity = 250
        smoke.velocityRange = 100
        smoke.emissionLongitude = CGFloat(M_PI_2+M_PI)
        smoke.emissionRange = CGFloat(M_PI_2)
        fireEmitter?.emitterCells = [fire,smoke]
        self.view.layer.addSublayer(fireEmitter!)
    }

上面代码中的Particles_fire图片只是一个白色的小色块,运行工程,效果如图6-20所示。

图6-20 粒子火焰效果