在iOS上制作爆炸动画主要涉及Core Animation框架和UIKit的动画系统。爆炸动画本质上是一系列粒子从中心点向外扩散的视觉效果,可以模拟真实爆炸或创造风格化的爆炸效果。
这是最接近真实爆炸效果的方法,适合需要逼真效果的场景。
import UIKit
class ExplosionView: UIView {
private var emitter: CAEmitterLayer!
override init(frame: CGRect) {
super.init(frame: frame)
setupEmitter()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupEmitter()
}
private func setupEmitter() {
emitter = CAEmitterLayer()
emitter.emitterPosition = CGPoint(x: bounds.midX, y: bounds.midY)
emitter.emitterSize = CGSize(width: 20, height: 20)
emitter.emitterShape = .sphere
emitter.renderMode = .additive
emitter.emitterCells = [createExplosionCell()]
layer.addSublayer(emitter)
}
private func createExplosionCell() -> CAEmitterCell {
let cell = CAEmitterCell()
cell.birthRate = 8000
cell.lifetime = 0.5
cell.lifetimeRange = 0.3
cell.velocity = 200
cell.velocityRange = 50
cell.emissionRange = .pi * 2
cell.scale = 0.1
cell.scaleRange = 0.05
cell.scaleSpeed = -0.05
cell.contents = UIImage(named: "particle")?.cgImage
cell.color = UIColor.orange.cgColor
cell.alphaSpeed = -0.5
return cell
}
func explode() {
emitter.beginTime = CACurrentMediaTime()
emitter.setValue(0, forKeyPath: "emitterCells.explosion.birthRate")
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.removeFromSuperview()
}
}
}
适合简单的UI元素爆炸效果:
func simpleExplosionAnimation(view: UIView, completion: (() -> Void)? = nil) {
let pieces = 8
let pieceSize = view.bounds.size.width / CGFloat(pieces)
// 创建碎片
var fragments = [UIView]()
for i in 0..<pieces {
for j in 0..<pieces {
let fragment = UIView(frame: CGRect(
x: CGFloat(i) * pieceSize,
y: CGFloat(j) * pieceSize,
width: pieceSize,
height: pieceSize
))
fragment.backgroundColor = UIColor(
patternImage: view.snapshotImage()?.cropped(to: fragment.frame) ?? UIImage()
)
fragments.append(fragment)
view.superview?.addSubview(fragment)
}
}
view.isHidden = true
// 动画
UIView.animate(withDuration: 0.7, animations: {
for fragment in fragments {
let direction = CGVector(
dx: CGFloat.random(in: -1...1),
dy: CGFloat.random(in: -1...1)
)
let distance = CGFloat.random(in: 100...200)
fragment.center = CGPoint(
x: fragment.center.x + direction.dx * distance,
y: fragment.center.y + direction.dy * distance
)
fragment.alpha = 0
fragment.transform = CGAffineTransform(
rotationAngle: CGFloat.random(in: -CGFloat.pi...CGFloat.pi)
).scaledBy(
x: CGFloat.random(in: 0.1...0.5),
y: CGFloat.random(in: 0.1...0.5)
)
}
}) { _ in
fragments.forEach { $0.removeFromSuperview() }
completion?()
}
}
extension UIView {
func snapshotImage() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)
drawHierarchy(in: bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
}
extension UIImage {
func cropped(to rect: CGRect) -> UIImage? {
guard let cgImage = cgImage?.cropping(to: rect) else { return nil }
return UIImage(cgImage: cgImage)
}
}
适合游戏中的爆炸效果:
import SpriteKit
func createExplosion(at position: CGPoint, in scene: SKScene) {
let emitter = SKEmitterNode(fileNamed: "Explosion.sks")!
emitter.position = position
scene.addChild(emitter)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
emitter.removeFromParent()
}
}
问题1:粒子动画卡顿
问题2:爆炸后内存泄漏
问题3:爆炸效果不自然
以上方法可以根据具体需求进行组合和调整,以达到最佳的爆炸动画效果。
没有搜到相关的文章