├── ScreenShot.png ├── Assets.xcassets ├── Contents.json ├── Particle Sprite Atlas.spriteatlas │ ├── Contents.json │ ├── snow.imageset │ │ ├── snow.png │ │ └── Contents.json │ ├── star.imageset │ │ ├── star.png │ │ └── Contents.json │ ├── bokeh.imageset │ │ ├── bokeh.png │ │ └── Contents.json │ ├── spark.imageset │ │ ├── spark.png │ │ └── Contents.json │ ├── circle.imageset │ │ ├── circle.png │ │ └── Contents.json │ ├── tspark.imageset │ │ ├── tspark.png │ │ └── Contents.json │ └── confetti.imageset │ │ ├── confetti.png │ │ └── Contents.json ├── seattle.imageset │ ├── seattle.png │ └── Contents.json ├── birthday-cake.imageset │ ├── birthday-cake.png │ └── Contents.json └── AppIcon.appiconset │ └── Contents.json ├── FunWithParticleEmitters ├── Fire.sks ├── Rain.sks ├── Smoke.sks ├── Spark.sks ├── snow.png ├── Assets.xcassets │ ├── Contents.json │ └── Particle Sprite Atlas.spriteatlas │ │ ├── Contents.json │ │ ├── bokeh.imageset │ │ ├── bokeh.png │ │ └── Contents.json │ │ └── spark.imageset │ │ ├── spark.png │ │ └── Contents.json ├── tspark.png ├── confetti.png ├── Custom Views │ ├── GradientView.swift │ ├── ConfettiParticleView.swift │ ├── SnowParticleView.swift │ └── FireworksParticleView.swift ├── Extensions │ ├── NSLayoutConstraints+Extentsions.swift │ └── UIViewController+Extensions.swift ├── View Controllers │ ├── ContainerViewController.swift │ ├── ConfettiViewController.swift │ ├── FireworksViewController.swift │ └── SnowViewController.swift ├── Info.plist ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard └── AppDelegate.swift ├── README.MD ├── FunWithParticleEmitters.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── project.pbxproj └── .gitignore /ScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/ScreenShot.png -------------------------------------------------------------------------------- /Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /FunWithParticleEmitters/Fire.sks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/Fire.sks -------------------------------------------------------------------------------- /FunWithParticleEmitters/Rain.sks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/Rain.sks -------------------------------------------------------------------------------- /FunWithParticleEmitters/Smoke.sks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/Smoke.sks -------------------------------------------------------------------------------- /FunWithParticleEmitters/Spark.sks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/Spark.sks -------------------------------------------------------------------------------- /FunWithParticleEmitters/snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/snow.png -------------------------------------------------------------------------------- /FunWithParticleEmitters/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /FunWithParticleEmitters/tspark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/tspark.png -------------------------------------------------------------------------------- /FunWithParticleEmitters/confetti.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/confetti.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Assets.xcassets/seattle.imageset/seattle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/seattle.imageset/seattle.png -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # FunWithParticleEmitters 2 | Example of Particle Emitter in iOS using Swift 3 | 4 | ![Fireworks](ScreenShot.png) -------------------------------------------------------------------------------- /FunWithParticleEmitters/Assets.xcassets/Particle Sprite Atlas.spriteatlas/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Assets.xcassets/birthday-cake.imageset/birthday-cake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/birthday-cake.imageset/birthday-cake.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/snow.imageset/snow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/Particle Sprite Atlas.spriteatlas/snow.imageset/snow.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/star.imageset/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/Particle Sprite Atlas.spriteatlas/star.imageset/star.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/bokeh.imageset/bokeh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/Particle Sprite Atlas.spriteatlas/bokeh.imageset/bokeh.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/spark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/spark.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/circle.imageset/circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/Particle Sprite Atlas.spriteatlas/circle.imageset/circle.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/tspark.imageset/tspark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/Particle Sprite Atlas.spriteatlas/tspark.imageset/tspark.png -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/confetti.imageset/confetti.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/Assets.xcassets/Particle Sprite Atlas.spriteatlas/confetti.imageset/confetti.png -------------------------------------------------------------------------------- /FunWithParticleEmitters/Assets.xcassets/Particle Sprite Atlas.spriteatlas/bokeh.imageset/bokeh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/Assets.xcassets/Particle Sprite Atlas.spriteatlas/bokeh.imageset/bokeh.png -------------------------------------------------------------------------------- /FunWithParticleEmitters/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/spark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkw5877/FunWithParticleEmitters/HEAD/FunWithParticleEmitters/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/spark.png -------------------------------------------------------------------------------- /FunWithParticleEmitters.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FunWithParticleEmitters.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Assets.xcassets/seattle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "seattle.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/birthday-cake.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "birthday-cake.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/bokeh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bokeh.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/circle.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "circle.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/snow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "snow.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "spark.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/star.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "star.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/tspark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tspark.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Assets.xcassets/Particle Sprite Atlas.spriteatlas/confetti.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "confetti.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /FunWithParticleEmitters/Custom Views/GradientView.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | class GradientView:UIView { 5 | 6 | var startColor:UIColor = .white 7 | var endColor:UIColor = .white 8 | 9 | override class var layerClass:AnyClass{ 10 | return CAGradientLayer.self 11 | } 12 | 13 | override func layoutSubviews() { 14 | (layer as! CAGradientLayer).colors = [startColor.cgColor, endColor.cgColor] 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/Assets.xcassets/Particle Sprite Atlas.spriteatlas/bokeh.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "bokeh.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /FunWithParticleEmitters/Assets.xcassets/Particle Sprite Atlas.spriteatlas/spark.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "spark.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /FunWithParticleEmitters/Extensions/NSLayoutConstraints+Extentsions.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit.NSLayoutConstraint 3 | 4 | extension NSLayoutConstraint { 5 | 6 | class func pin(view:UIView, to superview:UIView) { 7 | view.translatesAutoresizingMaskIntoConstraints = false 8 | NSLayoutConstraint.activate([ 9 | view.topAnchor.constraint(equalTo: superview.topAnchor), 10 | view.trailingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.trailingAnchor), 11 | view.leadingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.leadingAnchor), 12 | view.bottomAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.bottomAnchor) 13 | ]) 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/View Controllers/ContainerViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | class ContainerViewController: UIViewController { 5 | 6 | let scrollView :UIScrollView = { 7 | let scrollView = UIScrollView() 8 | scrollView.translatesAutoresizingMaskIntoConstraints = false 9 | scrollView.isPagingEnabled = true 10 | scrollView.backgroundColor = .gray 11 | return scrollView 12 | }() 13 | 14 | let content = [SnowViewController(), ConfettiViewController(), FireworksViewController()] 15 | 16 | override var preferredStatusBarStyle: UIStatusBarStyle { 17 | return .lightContent 18 | } 19 | 20 | override func loadView() { 21 | view = UIView(frame: UIScreen.main.bounds) 22 | scrollView.frame = view.frame 23 | view.addSubview(scrollView) 24 | NSLayoutConstraint.pin(view: scrollView, to: view) 25 | } 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | configureChildren() 30 | } 31 | 32 | private func configureChildren() { 33 | for controller in content { 34 | add(child: controller, in: scrollView) 35 | controller.view.frame = view.frame 36 | controller.view.frame.origin.x = scrollView.contentSize.width 37 | scrollView.contentSize.width += view.frame.size.width 38 | } 39 | } 40 | } 41 | 42 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/Custom Views/ConfettiParticleView.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | class ConfettiParticleView: UIView { 5 | 6 | var particleImage:UIImage? 7 | 8 | override class var layerClass:AnyClass { 9 | return CAEmitterLayer.self 10 | } 11 | 12 | func makeEmitterCell(color: UIColor) -> CAEmitterCell { 13 | let cell = CAEmitterCell() 14 | cell.birthRate = 3 15 | cell.lifetime = 7.0 16 | cell.lifetimeRange = 0 17 | cell.color = color.cgColor 18 | cell.velocity = 200 19 | cell.velocityRange = 50 20 | cell.emissionLongitude = .pi 21 | cell.emissionRange = .pi / 4 22 | cell.spin = 2 23 | cell.spinRange = 3 24 | cell.scale = 0.75 25 | cell.scaleRange = 0.5 26 | cell.scaleSpeed = -0.05 27 | cell.contents = particleImage?.cgImage 28 | return cell 29 | } 30 | 31 | override func layoutSubviews() { 32 | super.layoutSubviews() 33 | let emitter = self.layer as! CAEmitterLayer 34 | emitter.masksToBounds = true 35 | emitter.emitterShape = .line 36 | emitter.emitterPosition = CGPoint(x: bounds.midX, y: 0) 37 | emitter.emitterSize = CGSize(width: bounds.size.width, height: 1) 38 | 39 | let red = makeEmitterCell(color: UIColor.red) 40 | let green = makeEmitterCell(color: UIColor.green) 41 | let blue = makeEmitterCell(color: UIColor.blue) 42 | emitter.emitterCells = [red, green, blue] 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/Custom Views/SnowParticleView.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | class SnowParticleView:UIView { 5 | 6 | var particleImage:UIImage? 7 | 8 | override class var layerClass:AnyClass { 9 | return CAEmitterLayer.self 10 | } 11 | 12 | func makeEmmiterCell(color:UIColor, velocity:CGFloat, scale:CGFloat)-> CAEmitterCell { 13 | let cell = CAEmitterCell() 14 | cell.birthRate = 10 15 | cell.lifetime = 20.0 16 | cell.lifetimeRange = 0 17 | cell.velocity = velocity 18 | cell.velocityRange = velocity / 4 19 | cell.emissionLongitude = .pi 20 | cell.emissionRange = .pi / 8 21 | cell.scale = scale 22 | cell.scaleRange = scale / 3 23 | cell.contents = particleImage?.cgImage 24 | return cell 25 | } 26 | 27 | override func layoutSubviews() { 28 | let emitter = self.layer as! CAEmitterLayer 29 | emitter.masksToBounds = true 30 | emitter.emitterShape = .line 31 | emitter.emitterPosition = CGPoint(x: bounds.midX, y: 0) 32 | emitter.emitterSize = CGSize(width: bounds.size.width, height: 1) 33 | 34 | let near = makeEmmiterCell(color: UIColor(white: 1, alpha: 1), velocity: 100, scale: 0.3) 35 | let middle = makeEmmiterCell(color: UIColor(white: 1, alpha: 0.66), velocity: 80, scale: 0.2) 36 | let far = makeEmmiterCell(color: UIColor(white: 1, alpha: 0.33), velocity: 60, scale: 0.1) 37 | 38 | emitter.emitterCells = [near, middle, far] 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | UIStatusBarStyle 30 | UIStatusBarStyleLightContent 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /FunWithParticleEmitters/Extensions/UIViewController+Extensions.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit.UIViewController 3 | 4 | extension UIViewController { 5 | 6 | /* remove child controller */ 7 | func add(child childViewController: UIViewController) { 8 | beginAddChild(child: childViewController) 9 | view.addSubview(childViewController.view) 10 | endAddChild(child: childViewController) 11 | } 12 | 13 | /* add child controller in a specific view */ 14 | func add(child childViewController: UIViewController, in view: UIView) { 15 | beginAddChild(child: childViewController) 16 | view.addSubview(childViewController.view) 17 | endAddChild(child: childViewController) 18 | } 19 | 20 | /* add child controller in a specific view with a set frame */ 21 | func add(child childViewController: UIViewController, in view: UIView, with frame:CGRect) { 22 | beginAddChild(child: childViewController) 23 | childViewController.view.frame = frame 24 | view.addSubview(childViewController.view) 25 | endAddChild(child: childViewController) 26 | } 27 | 28 | /* remove child controller */ 29 | func remove(child childViewController:UIViewController){ 30 | childViewController.beginAppearanceTransition(false, animated: false) 31 | childViewController.willMove(toParent: nil) 32 | childViewController.view.removeFromSuperview() 33 | childViewController.removeFromParent() 34 | childViewController.endAppearanceTransition() 35 | } 36 | 37 | /* extract these common methods out to avoid code duplication */ 38 | private func beginAddChild(child childViewController:UIViewController){ 39 | childViewController.beginAppearanceTransition(true, animated: false) 40 | self.addChild(childViewController) 41 | } 42 | 43 | private func endAddChild(child childViewController:UIViewController){ 44 | childViewController.didMove(toParent: self) 45 | childViewController.endAppearanceTransition() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/View Controllers/ConfettiViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | class ConfettiViewController : UIViewController { 5 | 6 | override func viewDidLoad() { 7 | super.viewDidLoad() 8 | let gradient = GradientView() 9 | gradient.startColor = UIColor(red: 0.53, green: 0.80, blue: 1.0, alpha: 1) 10 | gradient.endColor = UIColor(red: 0.8, green: 0.96, blue: 1.0, alpha: 1) 11 | gradient.translatesAutoresizingMaskIntoConstraints = false 12 | view.addSubview(gradient) 13 | 14 | 15 | let image = UIImage(named: "birthday-cake") 16 | let imageView = UIImageView(image: image) 17 | imageView.contentMode = .scaleAspectFit 18 | imageView.layer.masksToBounds = true 19 | imageView.translatesAutoresizingMaskIntoConstraints = false 20 | view.addSubview(imageView) 21 | 22 | let confetti = ConfettiParticleView() 23 | confetti.particleImage = UIImage(named: "confetti") 24 | confetti.translatesAutoresizingMaskIntoConstraints = false 25 | view.addSubview(confetti) 26 | 27 | NSLayoutConstraint.pin(view: gradient, to: view) 28 | NSLayoutConstraint.pin(view: confetti, to: view) 29 | 30 | NSLayoutConstraint.activate([ 31 | imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor), 32 | imageView.heightAnchor.constraint(equalToConstant:200), 33 | imageView.widthAnchor.constraint(equalToConstant:200), 34 | imageView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant:-16)]) 35 | 36 | let label = UILabel() 37 | label.translatesAutoresizingMaskIntoConstraints = false 38 | label.font = UIFont(name: "Menlo-Regular", size: 35) 39 | label.text = "Happy Birthday!" 40 | label.textAlignment = .center 41 | label.textColor = .blue 42 | label.sizeToFit() 43 | view.addSubview(label) 44 | 45 | NSLayoutConstraint.activate([ 46 | label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), 47 | label.centerXAnchor.constraint(equalTo: view.centerXAnchor), 48 | ]) 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // FunWithParticleEmitters 4 | // 5 | // Created by user on 2/21/19. 6 | // Copyright © 2019 user. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | window = UIWindow(frame: UIScreen.main.bounds) 19 | window?.rootViewController = ContainerViewController() 20 | window?.makeKeyAndVisible() 21 | return true 22 | } 23 | 24 | func applicationWillResignActive(_ application: UIApplication) { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | func applicationDidEnterBackground(_ application: UIApplication) { 30 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | func applicationWillEnterForeground(_ application: UIApplication) { 35 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 36 | } 37 | 38 | func applicationDidBecomeActive(_ application: UIApplication) { 39 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 40 | } 41 | 42 | func applicationWillTerminate(_ application: UIApplication) { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | 47 | } 48 | 49 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/View Controllers/FireworksViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit.UIViewController 3 | 4 | class FireworksViewController : UIViewController { 5 | 6 | var timer:Timer? 7 | let fireworks = FireworksParticleView() 8 | 9 | override func loadView() { 10 | let view = UIView() 11 | self.view = view 12 | } 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | let sky = GradientView() 18 | sky.startColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1) 19 | sky.endColor = UIColor(red: 0.07, green: 0.04, blue: 0.66, alpha: 1) 20 | sky.translatesAutoresizingMaskIntoConstraints = false 21 | view.addSubview(sky) 22 | 23 | let image = UIImage(named: "seattle") 24 | let imageView = UIImageView(image: image) 25 | imageView.translatesAutoresizingMaskIntoConstraints = false 26 | imageView.contentMode = .scaleAspectFill 27 | imageView.layer.masksToBounds = true 28 | 29 | view.addSubview(imageView) 30 | 31 | NSLayoutConstraint.activate([ 32 | imageView.heightAnchor.constraint(equalToConstant:300), imageView.leadingAnchor.constraint(equalTo:view.leadingAnchor), imageView.trailingAnchor.constraint(equalTo:view.trailingAnchor), 33 | imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor) 34 | ]) 35 | 36 | NSLayoutConstraint.activate([ 37 | sky.leadingAnchor.constraint(equalTo: view.leadingAnchor), 38 | sky.trailingAnchor.constraint(equalTo: view.trailingAnchor), 39 | sky.topAnchor.constraint(equalTo: view.topAnchor), 40 | sky.bottomAnchor.constraint(equalTo: imageView.topAnchor)]) 41 | 42 | fireworks.particleImage = UIImage(named: "tspark") 43 | fireworks.flareImage = UIImage(named: "tspark") 44 | fireworks.translatesAutoresizingMaskIntoConstraints = false 45 | view.addSubview(fireworks) 46 | 47 | NSLayoutConstraint.activate([ 48 | fireworks.leadingAnchor.constraint(equalTo: view.leadingAnchor), 49 | fireworks.trailingAnchor.constraint(equalTo: view.trailingAnchor), 50 | fireworks.topAnchor.constraint(equalTo: view.topAnchor), 51 | fireworks.bottomAnchor.constraint(equalTo: imageView.centerYAnchor)]) 52 | } 53 | 54 | override func viewWillDisappear(_ animated: Bool) { 55 | super.viewWillDisappear(animated) 56 | timer?.invalidate() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/View Controllers/SnowViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit 3 | 4 | class SnowViewController : UIViewController { 5 | 6 | let snow = SnowParticleView() 7 | let button = UIButton() 8 | 9 | override func viewDidLoad() { 10 | super.viewDidLoad() 11 | let sky = GradientView() 12 | sky.translatesAutoresizingMaskIntoConstraints = false 13 | sky.startColor = UIColor(red: 0.1, green: 0.25, blue: 0.5, alpha: 1) 14 | sky.endColor = UIColor(red: 0.75, green: 0.8, blue: 0.9, alpha: 1) 15 | view.addSubview(sky) 16 | 17 | snow.translatesAutoresizingMaskIntoConstraints = false 18 | snow.isHidden = true 19 | snow.particleImage = UIImage(named: "snow") 20 | view.addSubview(snow) 21 | 22 | 23 | button.translatesAutoresizingMaskIntoConstraints = false 24 | button.backgroundColor = .white 25 | button.layer.cornerRadius = 10 26 | button.setTitle("Make it snow", for: .normal) 27 | button.setTitleColor(.blue, for: .normal) 28 | button.addTarget(self, action: #selector(makeItSnow(sender:)), for: .touchUpInside) 29 | view.addSubview(button) 30 | 31 | NSLayoutConstraint.activate([ 32 | sky.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), 33 | sky.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), 34 | sky.topAnchor.constraint(equalTo: view.topAnchor), 35 | sky.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)]) 36 | 37 | NSLayoutConstraint.activate([ 38 | snow.leadingAnchor.constraint(equalTo: view.leadingAnchor), 39 | snow.trailingAnchor.constraint(equalTo: view.trailingAnchor), 40 | snow.topAnchor.constraint(equalTo: view.topAnchor), 41 | snow.bottomAnchor.constraint(equalTo: view.bottomAnchor)]) 42 | 43 | NSLayoutConstraint.activate([ 44 | button.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), 45 | button.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant:16), 46 | button.widthAnchor.constraint(equalToConstant: 150) 47 | ]) 48 | } 49 | 50 | @objc private func makeItSnow(sender:UIButton) { 51 | snow.isHidden.toggle() 52 | toggleButtonState() 53 | } 54 | 55 | private func toggleButtonState() { 56 | if button.title(for: .normal) == "Make it snow"{ 57 | button.setTitle("Make it stop", for: .normal) 58 | button.setTitleColor(.red, for: .normal) 59 | } else{ 60 | button.setTitle("Make it snow", for: .normal) 61 | button.setTitleColor(.blue, for: .normal) 62 | } 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /FunWithParticleEmitters/Custom Views/FireworksParticleView.swift: -------------------------------------------------------------------------------- 1 | 2 | import UIKit.UIView 3 | 4 | class FireworksParticleView:UIView { 5 | 6 | var particleImage:UIImage? 7 | var flareImage:UIImage? 8 | 9 | override class var layerClass:AnyClass { 10 | return CAEmitterLayer.self 11 | } 12 | 13 | /* 14 | * Invisible particle representing the rocket before the explosion 15 | * The particle is invisible because we do not assign an image to the 16 | * contents property of the cell 17 | */ 18 | func makeEmiterCellRocket() -> CAEmitterCell { 19 | let cell = CAEmitterCell() 20 | /* -pi/2 = up */ 21 | cell.emissionLongitude = -.pi/2 22 | cell.emissionLatitude = 0 23 | cell.emissionRange = .pi/4 24 | cell.lifetime = 1.6 25 | cell.birthRate = 1 26 | 27 | /* 28 | * @note velocity - determines the speed of the particle, the higher the volicity 29 | * the further it travels on the screen. This is effected by yAcceleration 30 | * 31 | * @note yAcceleration - simulates gravity 32 | * a postive value applys gravity while negative value simulates a 33 | * lack or reduction of gravity allowing particles to "fly". 34 | * the combination of velocity & yAcceleration determines distance 35 | */ 36 | cell.velocity = 50 37 | cell.velocityRange = cell.velocity/4 38 | cell.yAcceleration = -150 39 | /* 40 | * @note color will get inherited by the cells in emttierCells array 41 | * @note red/green/blue ranges are the amount by which the color component 42 | * of the cell can vary 43 | * +/- 0.5 for a range between 0 to 1, giving a random color 44 | */ 45 | let color = UIColor.init(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0) 46 | cell.color = color.cgColor 47 | cell.redRange = 0.5 48 | cell.greenRange = 0.5 49 | cell.blueRange = 0.5 50 | cell.name = "rocket" 51 | return cell 52 | } 53 | 54 | func makeEmiterCellFlare() -> CAEmitterCell { 55 | let cell = CAEmitterCell() 56 | cell.color = UIColor.white.cgColor 57 | cell.contents = flareImage?.cgImage 58 | /* 59 | * the direction of emission, we need to rotate from the rocket's direction, 60 | * of -pi/2 (upward directions) 180 degrees, so pi radians is 180 degrees 61 | */ 62 | cell.emissionLongitude = (2 * .pi) 63 | cell.birthRate = 45 64 | cell.lifetime = 1.5 65 | cell.velocity = 100 66 | cell.scale = 0.3 67 | /* 68 | * simulates gravity, positive gravity pulls the emitter particles down 69 | */ 70 | cell.yAcceleration = 350 71 | /* 72 | * 2pi = 360 degress, particles disperse in all directions 73 | */ 74 | cell.emissionRange = .pi/7 75 | cell.alphaSpeed = -0.7 76 | cell.scaleSpeed = -0.1 77 | cell.scaleRange = 0.1 78 | cell.beginTime = 0.01 79 | /* needs to be long enough to stay with rocket */ 80 | cell.duration = 2.0 81 | cell.name = "flare" 82 | return cell 83 | } 84 | 85 | func makeEmiterCellFirework() -> CAEmitterCell { 86 | let cell = CAEmitterCell() 87 | cell.contents = particleImage?.cgImage 88 | cell.birthRate = 8000 89 | cell.velocity = 130 90 | cell.lifetime = 1.0 91 | cell.emissionRange = (2 * .pi) 92 | /* determines size of explosion */ 93 | cell.scale = 0.1 94 | cell.alphaSpeed = -0.2 95 | cell.yAcceleration = 80 96 | cell.beginTime = 1.5 97 | cell.duration = 0.1 98 | cell.scaleSpeed = -0.015 99 | cell.spin = 2 100 | cell.name = "firework" 101 | return cell 102 | } 103 | 104 | /* 105 | * preSpark is an invisible particle used to later emit the sparkle 106 | **/ 107 | func makeEmitterCellPrespark(firework:CAEmitterCell) -> CAEmitterCell { 108 | let cell = CAEmitterCell() 109 | cell.birthRate = 80 110 | cell.velocity = firework.velocity * 0.70 111 | cell.lifetime = 1.2 112 | cell.yAcceleration = firework.yAcceleration * 0.85 113 | cell.beginTime = firework.beginTime - 0.2 114 | cell.emissionRange = firework.emissionRange 115 | cell.greenSpeed = 100 116 | cell.blueSpeed = 100 117 | cell.redSpeed = 100 118 | cell.name = "preSpark" 119 | return cell 120 | } 121 | 122 | /* The 'sparkle' at the end of a firework */ 123 | func makeSparkle() -> CAEmitterCell { 124 | let cell = CAEmitterCell() 125 | cell.contents = particleImage?.cgImage 126 | cell.birthRate = 10 127 | cell.lifetime = 0.05 128 | cell.yAcceleration = 150 129 | cell.beginTime = 0.8 130 | cell.scale = 0.05 131 | return cell 132 | } 133 | 134 | override func layoutSubviews() { 135 | let emitter = self.layer as! CAEmitterLayer 136 | emitter.emitterPosition = CGPoint(x: bounds.midX, y: bounds.maxY) 137 | emitter.emitterSize = CGSize(width: bounds.size.width * 0.50, height: 1.0) 138 | emitter.renderMode = .additive 139 | let rocket = makeEmiterCellRocket() 140 | let flare = makeEmiterCellFlare() 141 | let firework = makeEmiterCellFirework() 142 | let sparkle = makeSparkle() 143 | let prespark = makeEmitterCellPrespark(firework:firework) 144 | prespark.emitterCells = [sparkle] 145 | rocket.emitterCells = [flare, firework, prespark] 146 | emitter.emitterCells = [rocket] 147 | } 148 | 149 | /* 150 | * Simple firework example 151 | */ 152 | // func makeEmiterCell(color:UIColor, velocity:CGFloat, scale:CGFloat)-> CAEmitterCell { 153 | // let cell = CAEmitterCell() 154 | // cell.birthRate = 50 155 | // cell.lifetime = 0.35 156 | // cell.lifetimeRange = 0.75 157 | // cell.emissionRange = 5.0 158 | // /* pi/2 = circle */ 159 | // cell.emissionLatitude = .pi/2 160 | // cell.velocity = velocity 161 | // cell.velocityRange = velocity/3 162 | // cell.color = color.cgColor 163 | // cell.scale = 0.3 164 | // cell.contents = particleImage?.cgImage 165 | // return cell 166 | // } 167 | 168 | // override func layoutSubviews() { 169 | // let emitter = self.layer as! CAEmitterLayer 170 | // emitter.emitterShape = .sphere 171 | // emitter.emitterMode = .volume 172 | // emitter.emitterPosition = CGPoint(x: bounds.midX, y: bounds.maxY) 173 | // emitter.emitterSize = CGSize(width: bounds.size.width * 0.40, height: 1.0) 174 | // 175 | //// emitter.emitterShape = .circle 176 | //// emitter.emitterMode = .outline 177 | // emitter.renderMode = .additive 178 | // emitter.emitterPosition = CGPoint(x: bounds.midX, y: bounds.maxY) 179 | // emitter.emitterSize = CGSize(width: 100.0 * 0.25, height: 0) 180 | // 181 | // let red = UIColor(red: 154/255.0, green: 52/255.0, blue: 48/255.0, alpha: 1.0) 182 | // let green = UIColor(red: 126/255.0, green: 204/255.0, blue: 70/255.0, alpha: 1.0) 183 | // let orange = UIColor(red: 212/255.0, green: 134/255.0, blue: 74/255.0, alpha: 1.0) 184 | // 185 | // let em1 = makeEmiterCell(color: red, velocity: 100, scale: 0.3) 186 | // let em2 = makeEmiterCell(color: green, velocity: 100, scale: 0.3) 187 | // let em3 = makeEmiterCell(color: orange, velocity: 200, scale: 0.3) 188 | // emitter.emitterCells = [em1, em2, em3] 189 | // } 190 | } 191 | -------------------------------------------------------------------------------- /FunWithParticleEmitters.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | CE099E6A2226256400B8A20E /* Smoke.sks in Resources */ = {isa = PBXBuildFile; fileRef = CE099E692226256400B8A20E /* Smoke.sks */; }; 11 | CE196FE1223079FE00117313 /* Spark.sks in Resources */ = {isa = PBXBuildFile; fileRef = CE196FE0223079FE00117313 /* Spark.sks */; }; 12 | CE4C5AE822207A1F00A4D989 /* ContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4C5AE722207A1F00A4D989 /* ContainerViewController.swift */; }; 13 | CE4C5AEA22207A4700A4D989 /* UIViewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4C5AE922207A4700A4D989 /* UIViewController+Extensions.swift */; }; 14 | CE4C5AEC22207B2E00A4D989 /* NSLayoutConstraints+Extentsions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE4C5AEB22207B2E00A4D989 /* NSLayoutConstraints+Extentsions.swift */; }; 15 | CE6CF31E221F83600001E3EA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6CF31D221F83600001E3EA /* AppDelegate.swift */; }; 16 | CE6CF323221F83600001E3EA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE6CF321221F83600001E3EA /* Main.storyboard */; }; 17 | CE6CF328221F83690001E3EA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CE6CF326221F83690001E3EA /* LaunchScreen.storyboard */; }; 18 | CE6CF330221F83800001E3EA /* SnowViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6CF32F221F83800001E3EA /* SnowViewController.swift */; }; 19 | CE6CF332221F83B90001E3EA /* GradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6CF331221F83B90001E3EA /* GradientView.swift */; }; 20 | CE6CF334221F83CD0001E3EA /* SnowParticleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6CF333221F83CD0001E3EA /* SnowParticleView.swift */; }; 21 | CE6CF336221F84170001E3EA /* ConfettiParticleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6CF335221F84170001E3EA /* ConfettiParticleView.swift */; }; 22 | CE6CF338221F85430001E3EA /* ConfettiViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE6CF337221F85430001E3EA /* ConfettiViewController.swift */; }; 23 | CE9EA5E52220B76E002D8DA7 /* Rain.sks in Resources */ = {isa = PBXBuildFile; fileRef = CE9EA5E32220B76E002D8DA7 /* Rain.sks */; }; 24 | CE9EA5E62220B76E002D8DA7 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE9EA5E42220B76E002D8DA7 /* Assets.xcassets */; }; 25 | CE9EA5E82220C3CB002D8DA7 /* FireworksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA5E72220C3CB002D8DA7 /* FireworksViewController.swift */; }; 26 | CE9EA5EA2220C3F3002D8DA7 /* FireworksParticleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE9EA5E92220C3F3002D8DA7 /* FireworksParticleView.swift */; }; 27 | CEE3C6B7223727B6006C8C35 /* Fire.sks in Resources */ = {isa = PBXBuildFile; fileRef = CEE3C6B6223727B6006C8C35 /* Fire.sks */; }; 28 | /* End PBXBuildFile section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | CE099E692226256400B8A20E /* Smoke.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Smoke.sks; sourceTree = ""; }; 32 | CE196FE0223079FE00117313 /* Spark.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Spark.sks; sourceTree = ""; }; 33 | CE4C5AE722207A1F00A4D989 /* ContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerViewController.swift; sourceTree = ""; }; 34 | CE4C5AE922207A4700A4D989 /* UIViewController+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Extensions.swift"; sourceTree = ""; }; 35 | CE4C5AEB22207B2E00A4D989 /* NSLayoutConstraints+Extentsions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSLayoutConstraints+Extentsions.swift"; sourceTree = ""; }; 36 | CE6CF31A221F83600001E3EA /* FunWithParticleEmitters.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FunWithParticleEmitters.app; sourceTree = BUILT_PRODUCTS_DIR; }; 37 | CE6CF31D221F83600001E3EA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 38 | CE6CF322221F83600001E3EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 39 | CE6CF327221F83690001E3EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 40 | CE6CF329221F83690001E3EA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 41 | CE6CF32F221F83800001E3EA /* SnowViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnowViewController.swift; sourceTree = ""; }; 42 | CE6CF331221F83B90001E3EA /* GradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GradientView.swift; sourceTree = ""; }; 43 | CE6CF333221F83CD0001E3EA /* SnowParticleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnowParticleView.swift; sourceTree = ""; }; 44 | CE6CF335221F84170001E3EA /* ConfettiParticleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfettiParticleView.swift; sourceTree = ""; }; 45 | CE6CF337221F85430001E3EA /* ConfettiViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfettiViewController.swift; sourceTree = ""; }; 46 | CE9EA5E32220B76E002D8DA7 /* Rain.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Rain.sks; sourceTree = ""; }; 47 | CE9EA5E42220B76E002D8DA7 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = ../Assets.xcassets; sourceTree = ""; }; 48 | CE9EA5E72220C3CB002D8DA7 /* FireworksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FireworksViewController.swift; sourceTree = ""; }; 49 | CE9EA5E92220C3F3002D8DA7 /* FireworksParticleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FireworksParticleView.swift; sourceTree = ""; }; 50 | CEE3C6B6223727B6006C8C35 /* Fire.sks */ = {isa = PBXFileReference; lastKnownFileType = file.sks; path = Fire.sks; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | CE6CF317221F83600001E3EA /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | CE6CF311221F83600001E3EA = { 65 | isa = PBXGroup; 66 | children = ( 67 | CE6CF31C221F83600001E3EA /* FunWithParticleEmitters */, 68 | CE6CF31B221F83600001E3EA /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | CE6CF31B221F83600001E3EA /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | CE6CF31A221F83600001E3EA /* FunWithParticleEmitters.app */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | CE6CF31C221F83600001E3EA /* FunWithParticleEmitters */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | CE6CF31D221F83600001E3EA /* AppDelegate.swift */, 84 | CEFF1C04222853F900DCE9E8 /* View Controllers */, 85 | CEFF1C052228540300DCE9E8 /* Extensions */, 86 | CEFF1C03222853E000DCE9E8 /* Custom Views */, 87 | CE6CF321221F83600001E3EA /* Main.storyboard */, 88 | CE9EA5E42220B76E002D8DA7 /* Assets.xcassets */, 89 | CE6CF326221F83690001E3EA /* LaunchScreen.storyboard */, 90 | CE099E692226256400B8A20E /* Smoke.sks */, 91 | CE9EA5E32220B76E002D8DA7 /* Rain.sks */, 92 | CEE3C6B6223727B6006C8C35 /* Fire.sks */, 93 | CE196FE0223079FE00117313 /* Spark.sks */, 94 | CE6CF329221F83690001E3EA /* Info.plist */, 95 | ); 96 | path = FunWithParticleEmitters; 97 | sourceTree = ""; 98 | }; 99 | CEFF1C03222853E000DCE9E8 /* Custom Views */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | CE6CF331221F83B90001E3EA /* GradientView.swift */, 103 | CE9EA5E92220C3F3002D8DA7 /* FireworksParticleView.swift */, 104 | CE6CF333221F83CD0001E3EA /* SnowParticleView.swift */, 105 | CE6CF335221F84170001E3EA /* ConfettiParticleView.swift */, 106 | ); 107 | path = "Custom Views"; 108 | sourceTree = ""; 109 | }; 110 | CEFF1C04222853F900DCE9E8 /* View Controllers */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | CE4C5AE722207A1F00A4D989 /* ContainerViewController.swift */, 114 | CE6CF32F221F83800001E3EA /* SnowViewController.swift */, 115 | CE9EA5E72220C3CB002D8DA7 /* FireworksViewController.swift */, 116 | CE6CF337221F85430001E3EA /* ConfettiViewController.swift */, 117 | ); 118 | path = "View Controllers"; 119 | sourceTree = ""; 120 | }; 121 | CEFF1C052228540300DCE9E8 /* Extensions */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | CE4C5AE922207A4700A4D989 /* UIViewController+Extensions.swift */, 125 | CE4C5AEB22207B2E00A4D989 /* NSLayoutConstraints+Extentsions.swift */, 126 | ); 127 | path = Extensions; 128 | sourceTree = ""; 129 | }; 130 | /* End PBXGroup section */ 131 | 132 | /* Begin PBXNativeTarget section */ 133 | CE6CF319221F83600001E3EA /* FunWithParticleEmitters */ = { 134 | isa = PBXNativeTarget; 135 | buildConfigurationList = CE6CF32C221F83690001E3EA /* Build configuration list for PBXNativeTarget "FunWithParticleEmitters" */; 136 | buildPhases = ( 137 | CE6CF316221F83600001E3EA /* Sources */, 138 | CE6CF317221F83600001E3EA /* Frameworks */, 139 | CE6CF318221F83600001E3EA /* Resources */, 140 | ); 141 | buildRules = ( 142 | ); 143 | dependencies = ( 144 | ); 145 | name = FunWithParticleEmitters; 146 | productName = FunWithParticleEmitters; 147 | productReference = CE6CF31A221F83600001E3EA /* FunWithParticleEmitters.app */; 148 | productType = "com.apple.product-type.application"; 149 | }; 150 | /* End PBXNativeTarget section */ 151 | 152 | /* Begin PBXProject section */ 153 | CE6CF312221F83600001E3EA /* Project object */ = { 154 | isa = PBXProject; 155 | attributes = { 156 | LastSwiftUpdateCheck = 1010; 157 | LastUpgradeCheck = 1010; 158 | ORGANIZATIONNAME = user; 159 | TargetAttributes = { 160 | CE6CF319221F83600001E3EA = { 161 | CreatedOnToolsVersion = 10.1; 162 | }; 163 | }; 164 | }; 165 | buildConfigurationList = CE6CF315221F83600001E3EA /* Build configuration list for PBXProject "FunWithParticleEmitters" */; 166 | compatibilityVersion = "Xcode 9.3"; 167 | developmentRegion = en; 168 | hasScannedForEncodings = 0; 169 | knownRegions = ( 170 | en, 171 | Base, 172 | ); 173 | mainGroup = CE6CF311221F83600001E3EA; 174 | productRefGroup = CE6CF31B221F83600001E3EA /* Products */; 175 | projectDirPath = ""; 176 | projectRoot = ""; 177 | targets = ( 178 | CE6CF319221F83600001E3EA /* FunWithParticleEmitters */, 179 | ); 180 | }; 181 | /* End PBXProject section */ 182 | 183 | /* Begin PBXResourcesBuildPhase section */ 184 | CE6CF318221F83600001E3EA /* Resources */ = { 185 | isa = PBXResourcesBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | CEE3C6B7223727B6006C8C35 /* Fire.sks in Resources */, 189 | CE6CF328221F83690001E3EA /* LaunchScreen.storyboard in Resources */, 190 | CE9EA5E52220B76E002D8DA7 /* Rain.sks in Resources */, 191 | CE6CF323221F83600001E3EA /* Main.storyboard in Resources */, 192 | CE9EA5E62220B76E002D8DA7 /* Assets.xcassets in Resources */, 193 | CE099E6A2226256400B8A20E /* Smoke.sks in Resources */, 194 | CE196FE1223079FE00117313 /* Spark.sks in Resources */, 195 | ); 196 | runOnlyForDeploymentPostprocessing = 0; 197 | }; 198 | /* End PBXResourcesBuildPhase section */ 199 | 200 | /* Begin PBXSourcesBuildPhase section */ 201 | CE6CF316221F83600001E3EA /* Sources */ = { 202 | isa = PBXSourcesBuildPhase; 203 | buildActionMask = 2147483647; 204 | files = ( 205 | CE4C5AEC22207B2E00A4D989 /* NSLayoutConstraints+Extentsions.swift in Sources */, 206 | CE6CF31E221F83600001E3EA /* AppDelegate.swift in Sources */, 207 | CE4C5AE822207A1F00A4D989 /* ContainerViewController.swift in Sources */, 208 | CE9EA5EA2220C3F3002D8DA7 /* FireworksParticleView.swift in Sources */, 209 | CE9EA5E82220C3CB002D8DA7 /* FireworksViewController.swift in Sources */, 210 | CE6CF332221F83B90001E3EA /* GradientView.swift in Sources */, 211 | CE4C5AEA22207A4700A4D989 /* UIViewController+Extensions.swift in Sources */, 212 | CE6CF338221F85430001E3EA /* ConfettiViewController.swift in Sources */, 213 | CE6CF334221F83CD0001E3EA /* SnowParticleView.swift in Sources */, 214 | CE6CF336221F84170001E3EA /* ConfettiParticleView.swift in Sources */, 215 | CE6CF330221F83800001E3EA /* SnowViewController.swift in Sources */, 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | }; 219 | /* End PBXSourcesBuildPhase section */ 220 | 221 | /* Begin PBXVariantGroup section */ 222 | CE6CF321221F83600001E3EA /* Main.storyboard */ = { 223 | isa = PBXVariantGroup; 224 | children = ( 225 | CE6CF322221F83600001E3EA /* Base */, 226 | ); 227 | name = Main.storyboard; 228 | sourceTree = ""; 229 | }; 230 | CE6CF326221F83690001E3EA /* LaunchScreen.storyboard */ = { 231 | isa = PBXVariantGroup; 232 | children = ( 233 | CE6CF327221F83690001E3EA /* Base */, 234 | ); 235 | name = LaunchScreen.storyboard; 236 | sourceTree = ""; 237 | }; 238 | /* End PBXVariantGroup section */ 239 | 240 | /* Begin XCBuildConfiguration section */ 241 | CE6CF32A221F83690001E3EA /* Debug */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | ALWAYS_SEARCH_USER_PATHS = NO; 245 | CLANG_ANALYZER_NONNULL = YES; 246 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 248 | CLANG_CXX_LIBRARY = "libc++"; 249 | CLANG_ENABLE_MODULES = YES; 250 | CLANG_ENABLE_OBJC_ARC = YES; 251 | CLANG_ENABLE_OBJC_WEAK = YES; 252 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 253 | CLANG_WARN_BOOL_CONVERSION = YES; 254 | CLANG_WARN_COMMA = YES; 255 | CLANG_WARN_CONSTANT_CONVERSION = YES; 256 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 258 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 259 | CLANG_WARN_EMPTY_BODY = YES; 260 | CLANG_WARN_ENUM_CONVERSION = YES; 261 | CLANG_WARN_INFINITE_RECURSION = YES; 262 | CLANG_WARN_INT_CONVERSION = YES; 263 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 264 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 265 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 266 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 267 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 268 | CLANG_WARN_STRICT_PROTOTYPES = YES; 269 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 270 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 271 | CLANG_WARN_UNREACHABLE_CODE = YES; 272 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 273 | CODE_SIGN_IDENTITY = "iPhone Developer"; 274 | COPY_PHASE_STRIP = NO; 275 | DEBUG_INFORMATION_FORMAT = dwarf; 276 | ENABLE_STRICT_OBJC_MSGSEND = YES; 277 | ENABLE_TESTABILITY = YES; 278 | GCC_C_LANGUAGE_STANDARD = gnu11; 279 | GCC_DYNAMIC_NO_PIC = NO; 280 | GCC_NO_COMMON_BLOCKS = YES; 281 | GCC_OPTIMIZATION_LEVEL = 0; 282 | GCC_PREPROCESSOR_DEFINITIONS = ( 283 | "DEBUG=1", 284 | "$(inherited)", 285 | ); 286 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 287 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 288 | GCC_WARN_UNDECLARED_SELECTOR = YES; 289 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 290 | GCC_WARN_UNUSED_FUNCTION = YES; 291 | GCC_WARN_UNUSED_VARIABLE = YES; 292 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 293 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 294 | MTL_FAST_MATH = YES; 295 | ONLY_ACTIVE_ARCH = YES; 296 | SDKROOT = iphoneos; 297 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 298 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 299 | }; 300 | name = Debug; 301 | }; 302 | CE6CF32B221F83690001E3EA /* Release */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ALWAYS_SEARCH_USER_PATHS = NO; 306 | CLANG_ANALYZER_NONNULL = YES; 307 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 308 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 309 | CLANG_CXX_LIBRARY = "libc++"; 310 | CLANG_ENABLE_MODULES = YES; 311 | CLANG_ENABLE_OBJC_ARC = YES; 312 | CLANG_ENABLE_OBJC_WEAK = YES; 313 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 314 | CLANG_WARN_BOOL_CONVERSION = YES; 315 | CLANG_WARN_COMMA = YES; 316 | CLANG_WARN_CONSTANT_CONVERSION = YES; 317 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 318 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 319 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 320 | CLANG_WARN_EMPTY_BODY = YES; 321 | CLANG_WARN_ENUM_CONVERSION = YES; 322 | CLANG_WARN_INFINITE_RECURSION = YES; 323 | CLANG_WARN_INT_CONVERSION = YES; 324 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 325 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 326 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 327 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 328 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 329 | CLANG_WARN_STRICT_PROTOTYPES = YES; 330 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 331 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 332 | CLANG_WARN_UNREACHABLE_CODE = YES; 333 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 334 | CODE_SIGN_IDENTITY = "iPhone Developer"; 335 | COPY_PHASE_STRIP = NO; 336 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 337 | ENABLE_NS_ASSERTIONS = NO; 338 | ENABLE_STRICT_OBJC_MSGSEND = YES; 339 | GCC_C_LANGUAGE_STANDARD = gnu11; 340 | GCC_NO_COMMON_BLOCKS = YES; 341 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 342 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 343 | GCC_WARN_UNDECLARED_SELECTOR = YES; 344 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 345 | GCC_WARN_UNUSED_FUNCTION = YES; 346 | GCC_WARN_UNUSED_VARIABLE = YES; 347 | IPHONEOS_DEPLOYMENT_TARGET = 12.1; 348 | MTL_ENABLE_DEBUG_INFO = NO; 349 | MTL_FAST_MATH = YES; 350 | SDKROOT = iphoneos; 351 | SWIFT_COMPILATION_MODE = wholemodule; 352 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 353 | VALIDATE_PRODUCT = YES; 354 | }; 355 | name = Release; 356 | }; 357 | CE6CF32D221F83690001E3EA /* Debug */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 361 | CODE_SIGN_STYLE = Automatic; 362 | DEVELOPMENT_TEAM = S264RF7436; 363 | INFOPLIST_FILE = FunWithParticleEmitters/Info.plist; 364 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 365 | LD_RUNPATH_SEARCH_PATHS = ( 366 | "$(inherited)", 367 | "@executable_path/Frameworks", 368 | ); 369 | PRODUCT_BUNDLE_IDENTIFIER = com.example.FunWithParticleEmitters; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | SWIFT_VERSION = 5.0; 372 | TARGETED_DEVICE_FAMILY = "1,2"; 373 | }; 374 | name = Debug; 375 | }; 376 | CE6CF32E221F83690001E3EA /* Release */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 380 | CODE_SIGN_STYLE = Automatic; 381 | DEVELOPMENT_TEAM = S264RF7436; 382 | INFOPLIST_FILE = FunWithParticleEmitters/Info.plist; 383 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 384 | LD_RUNPATH_SEARCH_PATHS = ( 385 | "$(inherited)", 386 | "@executable_path/Frameworks", 387 | ); 388 | PRODUCT_BUNDLE_IDENTIFIER = com.example.FunWithParticleEmitters; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | SWIFT_VERSION = 5.0; 391 | TARGETED_DEVICE_FAMILY = "1,2"; 392 | }; 393 | name = Release; 394 | }; 395 | /* End XCBuildConfiguration section */ 396 | 397 | /* Begin XCConfigurationList section */ 398 | CE6CF315221F83600001E3EA /* Build configuration list for PBXProject "FunWithParticleEmitters" */ = { 399 | isa = XCConfigurationList; 400 | buildConfigurations = ( 401 | CE6CF32A221F83690001E3EA /* Debug */, 402 | CE6CF32B221F83690001E3EA /* Release */, 403 | ); 404 | defaultConfigurationIsVisible = 0; 405 | defaultConfigurationName = Release; 406 | }; 407 | CE6CF32C221F83690001E3EA /* Build configuration list for PBXNativeTarget "FunWithParticleEmitters" */ = { 408 | isa = XCConfigurationList; 409 | buildConfigurations = ( 410 | CE6CF32D221F83690001E3EA /* Debug */, 411 | CE6CF32E221F83690001E3EA /* Release */, 412 | ); 413 | defaultConfigurationIsVisible = 0; 414 | defaultConfigurationName = Release; 415 | }; 416 | /* End XCConfigurationList section */ 417 | }; 418 | rootObject = CE6CF312221F83600001E3EA /* Project object */; 419 | } 420 | --------------------------------------------------------------------------------