Swiftpack.co - MichaelKucinski/EmitterFireworksAndExplosionsPackage as Swift Package

Swiftpack.co is a collection of thousands of indexed Swift packages. Search packages.
See all packages published by MichaelKucinski.
MichaelKucinski/EmitterFireworksAndExplosionsPackage 1.0.0
Provides APIs to create fireworks and explosions effects for Apple mobile apps using IOS.
โญ๏ธ 1
๐Ÿ•“ 3 years ago
.package(url: "https://github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage.git", from: "1.0.0")

EmojiFireworksAndExplosionsPackage

EmojiFireworksAndExplosionsPackage can be used to provide uniquely artistic and highly tailorable animation effects that your users will enjoy. These effects might be used in gaming, social media, advertising, or in any app with artistic content.

See the example 4 minute video at the below link. Please recognize that the animations will be much smoother and of higher quality when running on an actual device.

https://drive.google.com/file/d/1sYh_W4oFAmnAb3FehbXk4OtA3nEexqxF/view

A variety of fireworks and explosion like effects are supported where the emitted cells are any sized emoji, or short text, or a desired image. You can control the size/scale of the emitted cells.

We have exposed control of many cell properties in the visible APIs, which makes these fireworks and explosion effects highly tailorable and uniquely artistic.

You can command accelerations, spin, and much more! Many of the cell property parameters have a sensible default value in case you don't want to specify it. X and Y accelerations are defaulted to zero, and so is spin. Just examine the API for detonate( ). It's mostly self documenting.

In our terminology below, where we generally say emoji, note that if you chose text, or provided your own image for the cell contents, it's all still applicable. We anticipate many designs will use emoji.

Very small emoji look like colorful sparks. Large emoji will show as much detail as desired such that the fireworks and explosion effects are a form of emoji art.

Fireworks and Explosion Effects are generated by placing emitters on developer specified paths / shapes. The paths can easily be assigned to cover the frame of any UI object! Or you can specify a point source, lines, circles, rectangles, heart shapes, or even elliptical shapes.

Emitted cell velocities, cell scales, and cell birth rates are controlled to simulate a firework or explosion effect. Developers can control the initial cell velocity, velocity range, cell scale, scale range, spin, spin range, and cell birth rate at the start of the explosion. Developers can specify a different ending scale such that the emitted cells can grow over time, or shrink to a zero size if desired, thereby becoming invisible.

Similarly, you can control X and Y acceleration to simulate wind, or gravity, or anti-gravity.

Further below, please find the complete parameter list for detonate( )

Note that you may need to consider whether your app runs on older and slower devices or faster and newer devices, and how many other animations are being drawn to the screen at the same time. Emitter animations can use a lot of CPU and GPU processing. The larger your specified pool is and your chosen parameters may effect performance and produce lag. At first try using these effects with screens that are mostly static. A design that shows an effect, then hides the emitters for a long enough time period to allow all the prior emitted cells to reach the end of their lifetimes may improve performance. Hiding the emitters helps free up resources. When an explosion / firework has reached the end of it's duration, we automatically hide those emitters.

Installation with Swift Package Manager

To implement in an Xcode project, select File, Swift Packages, Add Package Dependency, and supply this GitHub link : https://github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage. Then follow the below instructions.

Usage

To create an effect, you must create a pool of emitters that will handle the largest numbers of emitters that you intend on using. We suggest anywhere from 50 to 1000 emitters, depending on your desired density.

Below are code snippets that you can use to quickly get the Fireworks and Explosions Effect working in your project.

First import the EmojiFireworksAndExplosionsPackage

import EmojiFireworksAndExplosionsPackage

Declare a EmojiFireworksAndExplosionsPackage object


let fireworksAndExplosionsEngine = EmojiFireworksAndExplosionsPackage()

It is convenient to define these global objects, explained in the comments :


let countOfObjectsInExplosions = 125 // used when creating the pool of emitters
let useAllObjectsInExplosions = -1
//  A default that indicates the code will try to use every object in the emitter pool in the detonations of the explosions / fireworks.
//  If this default value is used when placing sparks on circles, lines, or rectangles it indicates how many emitters to place on those object paths.
//  Note that you can specify smaller detonations that use only a fraction of the available emitter pool.
//  When placing circles, lines, and rectangles for detonation, you can also specify that a smaller count that is less than the size of the emitter pool is to be used.

If your design could benefit from having multiple emoji fireworks and explosion objects, you can make several of them, like follows. But note you need to call the viewDidLoad for each, call createPoolOfEmitters for each, etc.

let fireworksAndExplosionsEngine2 = EmojiFireworksAndExplosionsPackage()
let fireworksAndExplosionsEngine3 = EmojiFireworksAndExplosionsPackage()

Make sure you call the fireworksAndExplosionsEngine.viewDidLoad() from the viewDidLoad of your parent view.

Create your pool of emitters right after calling the viewDidLoad. Don't worry about the default emoji character passed to someEmojiCharacter. You can specify and change it on the fly. But if your design always uses the same emoji character then specify it in the call. Note the emoji character is specified as a string. We take care of converting that string into an image under the covers.

If you are supplying your own image, we have an API that will overwrite the emoji character. We document that below.

In the viewDidLoad, you will also need to add a sublayer for each element in the pool of emitters.

fireworksAndExplosionsEngine.viewDidLoad()

fireworksAndExplosionsEngine.createPoolOfEmitters(maxCountOfEmitters: countOfObjectsInExplosions, someEmojiCharacter: "๐Ÿคฏ") // or use any count of objects desired.  We used 125 from above

for thisEmitter in fireworksAndExplosionsEngine.arrayOfEmitters { view.layer.addSublayer(thisEmitter) }


That completes the initialization needed in viewDidLoad

The rest of the code can get called later, based on any desired event.

To display an effect, you may want to set an emoji pattern first.

Here we show how to use a single emoji for all the emitters :


var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿคฏ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

Here we show how to use a variety of emoji for all the emitters :


var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿฆ„")
thisArrayAsText.append("๐Ÿ")
thisArrayAsText.append("๐Ÿž")
thisArrayAsText.append("๐Ÿ‘€")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

Next, specify where your emitters are to be placed on the screen. Here is an example that starts the explosion from a rectangular frame of an object already showing in our demo video.

readMeTextView.frame is a UITextView object in our example that was declared as var readMeTextView = UITextView()

Note that the chosen scaleFactor of 1.25 increases the starting placement for the explosion by 25 percent. If you want your explosion to start exactly on the frame border, specify scaleFactor : 1.0 Note that scaleFactor is an optional parameter that defaults to 1.0

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, scaleFactor: 1.25, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)


If you want to specify your own rectangle, just declare a CGRect object and initialize it.

var tempRect : CGRect = CGRect(
x: 100,
y: 300,
width: 300,
height: 300)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(thisRectangle: tempRect, scaleFactor: 1.25, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)


Finally, make a call to fireworksAndExplosionsEngine.detonate to produce your firework or explosion effect.

Note that there are some optional parameters that this example doesn't use so you have more flexibility if desired.


fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 120,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.3,
thisEndingScale: 0,
thisCellBirthrate: 15,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.5)

Please note that explosions should effectively hide themselves once their duration has expired.

At some point, you may want to hide the effect while it is still in the process of exploding. Simply call


fireworksAndExplosionsEngine.hideAllEmitters()

The above should get you going!

You can change the fireworks or explosion placement whenever you desire, but it may look best to do that while the emitters are hidden.

You can change the emoji whenever you desire, but it may look best to do that while the emitters are hidden.

You can call detonate whenever you desire, but it may look best to do that while the emitters are hidden.

Here is the complete parameter list for the API which does the actual explosion detonation which includes acceleration, spin, tint color, and more :


public func detonate(
thisCountOfEmittersGeneratingSparks : Int,
thisVelocity : CGFloat,
thisVelocityRange : CGFloat,
thisSpin : CGFloat,
thisSpinRange : CGFloat,
thisStartingScale : CGFloat,
thisStartingScaleRange : CGFloat = 0,
thisEndingScale : CGFloat,
thisAccelerationIn_X : CGFloat = 0,
thisAccelerationIn_Y : CGFloat = 0,
thisCellBirthrate: CGFloat,
thisCellLifetime: CGFloat,
thisCellLifetimeRange: CGFloat,
thisExplosionDuration : CGFloat,
thisTint              : UIColor = .white )

If you desire to specify a more complex emoji pattern for your fireworks and explosion effect, you can build any desired array of emoji using for loops, decisions, etc.

Instead of using emoji, you can specify a short string of text, such as "Love".


var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("Love")

You can specify a single text word / phrase, or you specify and array of words and phrases for a more fun effect.


var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("Love")
thisArrayAsText.append("You")
thisArrayAsText.append("Baby")

The text color can be adjusted by specifying the tint parameter in detonate . To get yellow text or yellow tinted emoji, see the last line of the parameters below :


fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 8,
thisStartingScale: 0,
thisEndingScale: 3,
thisAccelerationIn_X : -180,
thisCellBirthrate: 10,
thisCellLifetime: 7.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4,
thisTint : .yellow)

Or, you can specify an array of multiple colors to be used. You need to call alternateImageTintWithGivenArray( ) just after the call to detonate( ) and pass your array of colors as shown below.


fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 8,
thisStartingScale: 0,
thisEndingScale: 3,
thisAccelerationIn_X : -180,
thisCellBirthrate: 10,
thisCellLifetime: 7.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4)

var thisArrayOfColors = [UIColor](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayOfColors.append(.red)
thisArrayOfColors.append(.blue)
thisArrayOfColors.append(.green)
thisArrayOfColors.append(.yellow)

fireworksAndExplosionsEngine.alternateImageTintWithGivenArray(desiredArray: thisArrayOfColors)

If you want to supply your own image, you might want to scale that image before you pass it to our API. About 100 pixels across (or less) is a good size to start with. Here is an example call to our API :


fireworksAndExplosionsEngine.useSpecifiedImageAsContentsForAllEmitters(specifiedImage: tempImageToUseWhenChangingCellImages)

where tempImageToUseWhenChangingCellImages is a UIImage.

If you want to place your explosion to cover a line, here is some sample code :


let pointOne = CGPoint(x: 0, y: 0)
let pointTwo = CGPoint(x: 432, y: 234)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

If you want to place your explosion to cover a circle, here is some sample code :


fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 300), thisCircleRadius: 400, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

Note thisCircleArcFactor as 1 drawns a complete circle. A value of 0.5 would draw an arc for half a circle. The offsetAngleInDegrees would then control at which angle the half circle is shown on the screen.

Using a value of 3 for thisCircleArcFactor would wrap the explosions placement around the circle 3 times.

If you want a point source for your emitters, just use placeEmittersOnSpecifiedCircleOrArc and supply a value of 0.0 for thisCircleRadius.

If you want to place your explosion to cover an ellipse, here is some sample code :


fireworksAndExplosionsEngine.placeEmittersOnSpecifiedEllipse(thisCenter: CGPoint(x: 500, y: 700), thisMajorRadius: 300, thisMinorRadius: 200, alphaAngleInDegrees: 0, omegaAngleInDegreesUsedForRotation: -40, thisScaleFactor: 1, thisCountOfEmittersGeneratingSparks: -1)

If you want to place your explosion to cover a heart shape, here is some sample code :


fireworksAndExplosionsEngine.placeEmittersOnSpecifiedHeart(thisHeartCenter: CGPoint(x: 500, y: 500), thisHeartScaleFactor: 20, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

You can place emitters randomly inside of any specified circle. Here is sample code :


fireworksAndExplosionsEngine.placeEmittersRandomlyInsideSpecifiedCircle(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 300, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

You can place emitters exactly on any side of a specified rectangle. This example code shows them being placed on the top side :


fireworksAndExplosionsEngine.placeEmittersOnSpecifiedSideOfRectangle(thisSide: EmojiFireworksAndExplosionsPackage.Sides.Top, thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

To comb the emitters such that their path radiates from a circle, here's some sample code. Note that you should have already called placeEmittersOnSpecifiedCircleOrArc and then you will need to call detonate after the below example code. Some of the parameters below are for advanced use cases, but those values shown should work fine for the basic case.


fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 0,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

You can comb all emitters to point in any general direction such as up, to the left, right, etc.

To achieve a fountain like effect, it involves combing the emitters to the up direction, and specifying a cone of randomness, with a little gravity from an acceleration in Y. Here is sample code :

// a radius of zero will effectively make this a point source for our fountain

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 800), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combAllEmittersToPointInDesiredDirectionWithDesiredCone(directionAngleForCellFlow: 270, coneWideningFactorNormallyZero: 0.10)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 900,
thisVelocityRange: 420,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.85,
thisStartingScaleRange: 0,
thisEndingScale: 0,
thisAccelerationIn_Y : 900,
thisCellBirthrate: 11,
thisCellLifetime: 2,
thisCellLifetimeRange: 0,
thisExplosionDuration: 3.5)

You can comb emitters for the rectangle case, where each side can get a unique direction assigned, and a unique cone of randomness. Here is sample code :


fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(
thisRectangle: readMeTextView.frame,
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
combEmittersDesired: true,
topDesiredCombingRelativeAngle: 0,
topConeWideningFactorNormallyZero: 0.05,
bottomDesiredCombingRelativeAngle: 75,
bottomConeWideningFactorNormallyZero: 0.1,
leftDesiredCombingRelativeAngle: 30,
leftConeWideningFactorNormallyZero: 0.15,
rightDesiredCombingRelativeAngle: -30,
rightConeWideningFactorNormallyZero: 0.2)

To comb emitters for the ellipse case, here is sample code :


fireworksAndExplosionsEngine.combEllipticalEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow: 45, coneWideningFactorNormallyZero: 0.0)

To comb emitters for the heart shape case, here is sample code. Note that a value of 180 degrees flows the cells outwards away from the heart. A value of zero will flow the cells inwards towards the heart center. If you want to specify any other offset angle, you can.


// 180 below will offset them to flow outwards and away from the center.
fireworksAndExplosionsEngine.combHeartEmittersTowardsHeartCenter(desiredOffsetAngleForCellFlowInDegrees : 180,
coneWideningFactorNormallyZero: 0.05)

You can comb any explosion to flow towards (or away from any specified point), with any offsetting angle. Sample code here :


// Using a 0 for the angle will offset them to flow towards the point.
// Using a 180 for the angle will offset them to flow away from the point.

fireworksAndExplosionsEngine.combEmittersTowardsOrAwayFromSpecifiedPoint(thisPoint: CGPoint(x: 0, y: 500), desiredOffsetAngleForCellFlowInDegrees : 0,  coneWideningFactorNormallyZero: 0, thisCountOfEmittersGeneratingSparks : pointsOnShape)

If you choose to comb any detonation, you will need to call stopCombingTheEmitters or all future detonations will have the combing applied.

If you want to stop the combing effect and get back to randomly directed cells, you need to call this API :


fireworksAndExplosionsEngine.stopCombingTheEmitters()

And hey, in general, don't try to use multiple combing effects for the same detonation. The last one applied to an emitter will be the one you get.

License

No license is specified yet for this project. It's kind of experimental. I'm sharing it with some groups and giving them permission to experiment in order to get feedback. This project may be shared under the MIT license at some point in the future. If you have found this repository, you can experiment at will. If you want to consider releasing code using it, please email me early on at [email protected] for approval. If you a small operation that approval should be fine with no considerations. But any large organizations should make an agreement with me, hire me as a direct employee or consultant, etc. It might make sense to go for patents, build a team, etc. Feel free to contact me about improvements or with requests and with any feedback at all. I take criticism well and I would welcome good suggestions.

Email : [email protected]

If any students or developers want to experiment and make improvements or fork the design, I would consider a collaboration.

Please note that it is possible to overwhelm the GPU and experience lag if you specify very high birth rates (in the thousands) for the cells, or specify a large pool of emitters (again, in the thousands), or you specify long cell lifetimes, or you have many explosions displayed at once. Even cell scale may come into play, as the GPU tries to handle the increased workload associated with larger cell images. So you might try to be conservative at first.

With that being said, I think you will easily be able to find reasonable values for those properties in order to achieve some fun and artistic effects. There are potential use cases for gaming, advertising, social media, and any app that presents art to their users.

It might be interesting to try to couple these effects to user touches on the screen.

โ€” Mike

P.S. If you want to run my driver code, below is a copy and paste of my whole ViewController.swift.

Note that everything is scaled for an iPad Pro so if you only have an iPhone to experiment with you need to change some values. You can correlate the counter shown on the screen in the lower left corner to find the driving code for each explosion. Just examine touchesBegan and correlate to the variable countOfTouches. If you want to duplicate an effect from the video, just use the same parameters that correlate to the counter shown.

//
//  ViewController.swift
//  EmojiFireworksAndExplosionsDriver
//
//  Created by Michael Kucinski on 8/1/20.
//  Copyright ยฉ 2020 Michael Kucinski. All rights reserved.
//

import UIKit
import EmojiFireworksAndExplosionsPackage

class ViewController: UIViewController {

let fireworksAndExplosionsEngine = EmojiFireworksAndExplosionsPackage()
let fireworksAndExplosionsEngine2 = EmojiFireworksAndExplosionsPackage()
let fireworksAndExplosionsEngine3 = EmojiFireworksAndExplosionsPackage()

var countView = UITextView()
var readMeTextView = UITextView()

let countOfObjectsInExplosions = 125
let useAllObjectsInExplosions = -1
//  A default that indicates the code will try to use every object in the emitter pool in the detonations of the explosions / fireworks.
//  If this default value is used when placing sparks on circles, lines, or rectangles it indicates how many emitters to place on those object paths.
//  Note that you can specify smaller detonations that use only a fraction of the available emitter pool.
//  When placing circles, lines, and rectangles for detonation, you can also specify that a smaller count that is less than the size of the emitter pool is to be used.

override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 800)
readMeTextView.textAlignment = NSTextAlignment.justified
readMeTextView.backgroundColor = UIColor.white
readMeTextView.layer.borderColor = UIColor.blue.cgColor
readMeTextView.layer.borderWidth = 10.0
readMeTextView.font = UIFont.systemFont(ofSize: 32.0)
readMeTextView.textContainerInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
readMeTextView.textColor = .black
readMeTextView.isEditable = false
readMeTextView.allowsEditingTextAttributes = true // allows memoji
readMeTextView.isUserInteractionEnabled = false
readMeTextView.alpha = 0

countView.frame = CGRect(x: 20, y:  1300, width: 550, height: 50)
countView.textAlignment = NSTextAlignment.center
countView.backgroundColor = UIColor.blue
countView.layer.borderColor = UIColor.orange.cgColor
countView.layer.borderWidth = 5.0
countView.font = UIFont.systemFont(ofSize: 24.0)
countView.textContainerInset = UIEdgeInsets(top: 10, left: 4, bottom: 4, right: 4)
countView.textColor = .white
countView.text = "Tap screen to walk through examples."
countView.isEditable = false
countView.allowsEditingTextAttributes = true // allows memoji
countView.isUserInteractionEnabled = false

fireworksAndExplosionsEngine.viewDidLoad()

fireworksAndExplosionsEngine.createPoolOfEmitters(maxCountOfEmitters: countOfObjectsInExplosions, someEmojiCharacter: "๐Ÿคฏ")

for thisEmitter in fireworksAndExplosionsEngine.arrayOfEmitters { view.layer.addSublayer(thisEmitter) }

fireworksAndExplosionsEngine2.viewDidLoad()

fireworksAndExplosionsEngine2.createPoolOfEmitters(maxCountOfEmitters: countOfObjectsInExplosions, someEmojiCharacter: "๐Ÿคฏ")

for thisEmitter in fireworksAndExplosionsEngine2.arrayOfEmitters { view.layer.addSublayer(thisEmitter) }

fireworksAndExplosionsEngine3.viewDidLoad()

fireworksAndExplosionsEngine3.createPoolOfEmitters(maxCountOfEmitters: countOfObjectsInExplosions, someEmojiCharacter: "๐Ÿคฏ")

for thisEmitter in fireworksAndExplosionsEngine3.arrayOfEmitters { view.layer.addSublayer(thisEmitter) }

self.view.addSubview(readMeTextView)
self.view.addSubview(countView)

var localTimer = Timer()

if localTimer.isValid
{
// This blank if statement gets rid of a nuisance warning about never reading the timer.
}

// start the timer
localTimer = Timer.scheduledTimer(timeInterval: 1.0/60.0, target: self, selector: #selector(handleTimerEvent), userInfo: nil, repeats: true)

} // ends viewDidLoad

var totalFramesSinceStarting = 0
var timerRunning : Bool = false

// starts handleTimer...
@objc func handleTimerEvent()
{
totalFramesSinceStarting += 1

if timerRunning
{
if totalFramesSinceStarting % 40 == 0
{
fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 300), thisCircleRadius: 10, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 2450,
thisVelocityRange: 500,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.25,
thisEndingScale: 0,
thisCellBirthrate: 31,
thisCellLifetime: 0.3,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.25)
}
if totalFramesSinceStarting % 60 == 0
{
fireworksAndExplosionsEngine2.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 600), thisCircleRadius: 400, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine2.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 500,
thisVelocityRange: 200,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 0.2,
thisEndingScale: 0.1,
thisCellBirthrate: 31,
thisCellLifetime: 0.4,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.45)
}
if totalFramesSinceStarting % 80 == 0
{
fireworksAndExplosionsEngine3.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 900), thisCircleRadius: 10, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine3.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 450,
thisVelocityRange: 500,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 3,
thisEndingScale: 0,
thisCellBirthrate: 31,
thisCellLifetime: 0.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.5)
}
}

} // ends handleTimerEvent

var countOfTouches = 0
// stub
//var countOfTouches = 36

var thisTouchPoint : CGPoint = CGPoint(x:-4100,y:-4100)

// Detect touch
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
let touch = touches.first!
thisTouchPoint = touch.location(in: self.view)

if thisTouchPoint.y > 1200 && thisTouchPoint.x > 700
{
// provides a way to repeat the last explosion for my testing purposes
countOfTouches = previousCountOfTouches
}

if countOfTouches == 0
{
// Stop the combing from the end of the last pass through the count.
fireworksAndExplosionsEngine.stopCombingTheEmitters()
fireworksAndExplosionsEngine2.hideAllEmitters()

readMeTextView.alpha = 1
readMeTextView.frame = CGRect(x: 100, y:  1100, width: 845, height: 160)
readMeTextView.text = "This Swift Package lets you produce an explosion or fireworks like effect where emoji, text, or a specified image is used as the sparks."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿฆ„")
thisArrayAsText.append("๐Ÿ")
thisArrayAsText.append("๐Ÿž")
thisArrayAsText.append("๐Ÿ‘€")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let pointOne = CGPoint(x: 0, y: 0)
let pointTwo = CGPoint(x: 0, y: 1240)

// below lines helps to test the call to useSpecifiedImageAsContentsForAllEmitters which is commented out

//let textOrEmojiToUIImage = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 100))

//textOrEmojiToUIImage.text = "๐Ÿ‡ฒ๐Ÿ‡พ"
//textOrEmojiToUIImage.sizeToFit()

//let tempImageToUseWhenChangingCellImages  =  UIImage.imageWithLabel(label: textOrEmojiToUIImage)

//fireworksAndExplosionsEngine.useSpecifiedImageAsContentsForAllEmitters(specifiedImage: tempImageToUseWhenChangingCellImages)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 1400,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 3,
thisEndingScale: 0,
thisCellBirthrate: 55,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.4)
}
if countOfTouches == 1
{
readMeTextView.text = "The sparks are emitters where developers can control the starting size, ending size, spin, tint, accelerations in X and Y, birthrate, lifetime, etc."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿคฏ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 700,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 0.1,
thisEndingScale: 1.3,
thisCellBirthrate: 125,
thisCellLifetime: 3.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.4,
thisTint : .green)
}
if countOfTouches == 2
{
readMeTextView.text = "Your explosions/fireworks can consist of as many different emoji as desired (22 shown now)!\nJust append your emoji like this : \nthisArrayAsText.append(โšก๏ธ)\nthisArrayAsText.append(๐Ÿงจ) \nthisArrayAsText.append(๐Ÿ€) \nthisArrayAsText.append(๐Ÿฆ„) \nthisArrayAsText.append(๐ŸŸ)"
readMeTextView.frame = CGRect(x: 100, y:  900, width: 845, height: 340)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โšก๏ธ")
thisArrayAsText.append("๐Ÿงจ")
thisArrayAsText.append("๐Ÿž")
thisArrayAsText.append("๐Ÿฆ„")
thisArrayAsText.append("๐Ÿ’˜")
thisArrayAsText.append("๐Ÿฅ")
thisArrayAsText.append("๐ŸŒž")
thisArrayAsText.append("๐Ÿ€")
thisArrayAsText.append("๐ŸŸ")
thisArrayAsText.append("๐Ÿ”")
thisArrayAsText.append("๐Ÿ’")
thisArrayAsText.append("๐Ÿ•")
thisArrayAsText.append("๐Ÿ‹")
thisArrayAsText.append("๐Ÿซ")
thisArrayAsText.append("๐Ÿฐ")
thisArrayAsText.append("๐Ÿง")
thisArrayAsText.append("๐ŸŽฏ")
thisArrayAsText.append("๐Ÿงฒ")
thisArrayAsText.append("๐Ÿ’ฐ")
thisArrayAsText.append("๐Ÿ’Ž")
thisArrayAsText.append("๐Ÿ“†")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 50, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 400,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 1.15,
thisEndingScale: 1.25,
thisCellBirthrate: 25,
thisCellLifetime: 4.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4)
}

if countOfTouches == 3
{
readMeTextView.text = "Your explosions / fireworks can come from a point source."
readMeTextView.frame = CGRect(x: 100, y:  1100, width: 845, height: 160)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โœ…")
thisArrayAsText.append("๐Ÿ…ฐ๏ธ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 120,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.3,
thisEndingScale: 0,
thisCellBirthrate: 15,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.5)
}
if countOfTouches == 4
{
readMeTextView.text = "Your explosions / fireworks can come from sources evenly spaced out around a circle."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โœ…")
thisArrayAsText.append("๐Ÿ…ฐ๏ธ")
thisArrayAsText.append("โ˜ฎ๏ธ")
thisArrayAsText.append("๐Ÿ†š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 400, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 20,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.1,
thisEndingScale: 0.2,
thisCellBirthrate: 15,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 1.4)
}
if countOfTouches == 5
{
readMeTextView.text = "Your explosions / fireworks can cover any fraction of a circles arc and any offset angle."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โœ…")
thisArrayAsText.append("๐Ÿ…ฐ๏ธ")
thisArrayAsText.append("โ˜ฎ๏ธ")
thisArrayAsText.append("๐Ÿ†š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 400, thisCircleArcFactor: 0.5, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 20,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.1,
thisEndingScale: 0.2,
thisCellBirthrate: 15,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 1.4)
}
if countOfTouches == 6
{
readMeTextView.text = "Your explosions / fireworks can cover any fraction of a circles arc and any offset angle."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โœ…")
thisArrayAsText.append("๐Ÿ…ฐ๏ธ")
thisArrayAsText.append("โ˜ฎ๏ธ")
thisArrayAsText.append("๐Ÿ†š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 400, thisCircleArcFactor: 0.25, offsetAngleInDegrees: 160, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 20,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.1,
thisEndingScale: 0.2,
thisCellBirthrate: 15,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 1.4)
}
if countOfTouches == 7
{
readMeTextView.text = "Your explosions / fireworks can cover any fraction of a circles arc and any offset angle."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โœ…")
thisArrayAsText.append("๐Ÿ…ฐ๏ธ")
thisArrayAsText.append("โ˜ฎ๏ธ")
thisArrayAsText.append("๐Ÿ†š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 400, thisCircleArcFactor: 0.25, offsetAngleInDegrees: -25, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 20,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.1,
thisEndingScale: 0.2,
thisCellBirthrate: 15,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 1.4)
}
if countOfTouches == 8
{
readMeTextView.text = "Your explosions / fireworks can pick any side of a rectangle as the effects source.\n\n\n                               Top : "

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ˜ฑ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedSideOfRectangle(thisSide: EmojiFireworksAndExplosionsPackage.Sides.Top, thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 250,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 3,
thisEndingScale: 0,
thisAccelerationIn_Y : -100,
thisCellBirthrate: 85,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 9
{
readMeTextView.text = "Your explosions / fireworks can pick any side of a rectangle as the effects source.\n\n\n                               Bottom : "

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ˜ค")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedSideOfRectangle(thisSide: EmojiFireworksAndExplosionsPackage.Sides.Bottom, thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 250,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 3,
thisEndingScale: 0,
thisAccelerationIn_Y : 100,
thisCellBirthrate: 85,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 10
{
readMeTextView.text = "Your explosions / fireworks can pick any side of a rectangle as the effects source.\n\n\n                               Left : "

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿง")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedSideOfRectangle(thisSide: EmojiFireworksAndExplosionsPackage.Sides.Left, thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 250,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 3,
thisEndingScale: 0,
thisAccelerationIn_X : -1000,
thisCellBirthrate: 85,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 11
{
readMeTextView.text = "Your explosions / fireworks can pick any side of a rectangle as the effects source.\n\n\n                               Right : "

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ˜Ž")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedSideOfRectangle(thisSide: EmojiFireworksAndExplosionsPackage.Sides.Right, thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 250,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 3,
thisEndingScale: 0,
thisAccelerationIn_X : 1000,
thisCellBirthrate: 85,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 12
{
readMeTextView.text = "Setting an X acceleration can simulate a wind."

readMeTextView.frame = CGRect(x: 100, y:  1100, width: 845, height: 160)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("Love")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let desiredSubsetOfPool : Int = 10

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 200, y: 600), thisCircleRadius: 200, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 8,
thisStartingScale: 0,
thisEndingScale: 3,
thisAccelerationIn_X : 400,
thisCellBirthrate: 10,
thisCellLifetime: 4,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4,
thisTint : .magenta)

}
if countOfTouches == 13
{
readMeTextView.text = "Note that text / sparks can be tinted with any colors as defined by a simple array.\nJust append your colors like this : \nthisArrayOfColors.append(.red)\nthisArrayOfColors.append(.blue)\nthisArrayOfColors.append(.green)\nthisArrayOfColors.append(.yellow)"


readMeTextView.frame = CGRect(x: 100, y:  900, width: 845, height: 340)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("Love")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let desiredSubsetOfPool : Int = 10

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 200, y: 600), thisCircleRadius: 200, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 8,
thisStartingScale: 0,
thisEndingScale: 3,
thisAccelerationIn_X : 400,
thisCellBirthrate: 10,
thisCellLifetime: 4,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4,
thisTint : .magenta)

var thisArrayOfColors = [UIColor](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayOfColors.append(.red)
thisArrayOfColors.append(.blue)
thisArrayOfColors.append(.green)
thisArrayOfColors.append(.yellow)

fireworksAndExplosionsEngine.alternateImageTintWithGivenArray(desiredArray: thisArrayOfColors)
}

if countOfTouches == 14
{
readMeTextView.alpha = 0

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("Love")
thisArrayAsText.append("You")
thisArrayAsText.append("Baby")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let desiredSubsetOfPool : Int = 60

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 800, y: 600), thisCircleRadius: 200, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: desiredSubsetOfPool,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 8,
thisStartingScale: 0,
thisEndingScale: 3,
thisAccelerationIn_X : -180,
thisCellBirthrate: 10,
thisCellLifetime: 7.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4,
thisTint : .yellow)

var thisArrayOfColors = [UIColor](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayOfColors.append(.red)
thisArrayOfColors.append(.blue)
thisArrayOfColors.append(.green)
thisArrayOfColors.append(.yellow)

fireworksAndExplosionsEngine.alternateImageTintWithGivenArray(desiredArray: thisArrayOfColors)
}

if countOfTouches == 15
{
readMeTextView.text = "\nSetting a Y acceleration can simulate gravity."

readMeTextView.frame = CGRect(x: 100, y:  900, width: 845, height: 160)

readMeTextView.alpha = 1

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โค๏ธ")
thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’œ")
thisArrayAsText.append("๐Ÿงก")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 400), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 240,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 1,
thisEndingScale: 1,
thisAccelerationIn_Y : 200,
thisCellBirthrate: 5,
thisCellLifetime: 5.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 1.4)
}

if countOfTouches == 16
{
readMeTextView.text = "\nYou can control the explosion / fireworks duration down to the millisecond.\n\n\n                               0.3 seconds"

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)


var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ‘€")
thisArrayAsText.append("๐Ÿ‘")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(

thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 0.3,
thisEndingScale: 0.0,
thisCellBirthrate: 500,
thisCellLifetime: 0.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.3)
}

if countOfTouches == 17
{
readMeTextView.text = "\nYou can control the explosion / fireworks duration down to the millisecond.\n\n\n                               3.14 seconds"

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐ŸŒน")
thisArrayAsText.append("๐Ÿ’")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(

thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 0.3,
thisEndingScale: 0.2,
thisCellBirthrate: 500,
thisCellLifetime: 0.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 3.14)
}

if countOfTouches == 18
{
readMeTextView.text = "You can place the sparks randomly inside any specified circle."

readMeTextView.frame = CGRect(x: 100, y:  1100, width: 845, height: 160)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ€")
thisArrayAsText.append("๐Ÿ„")
thisArrayAsText.append("๐Ÿ’ฆ")
thisArrayAsText.append("๐Ÿ")
thisArrayAsText.append("๐ŸŒท")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersRandomlyInsideSpecifiedCircle(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 300, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 12,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 0.2,
thisEndingScale: 0.2,
thisCellBirthrate: 5,
thisCellLifetime: 2.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 1.14)
}
if countOfTouches == 19
{
readMeTextView.text = "You can easily program implosions!\nAnd the direction of the particles can be combed."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿคฏ")
thisArrayAsText.append("๐ŸŽ")
thisArrayAsText.append("๐Ÿฅถ")
thisArrayAsText.append("๐Ÿ‘ป")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 400, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 180,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 450,
thisVelocityRange: 250,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.25,
thisEndingScale: 0.0,
thisCellBirthrate: 31,
thisCellLifetime: 0.7,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 20
{
readMeTextView.text = "Explosions can sling cells from the edge of circles."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿคฏ")
thisArrayAsText.append("๐ŸŽ")
thisArrayAsText.append("๐Ÿฅถ")
thisArrayAsText.append("๐Ÿ‘ป")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)


fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 200, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 90,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 650,
thisVelocityRange: 250,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.25,
thisEndingScale: 0.0,
thisCellBirthrate: 31,
thisCellLifetime: 0.7,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 21
{
readMeTextView.text = "Explosions can comb the flow streams in any desired direction relative to the circle."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐ŸŽ")
thisArrayAsText.append("๐Ÿฅถ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 100, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 0,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 950,
thisVelocityRange: 250,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 0.5,
thisEndingScale: 0.5,
thisCellBirthrate: 31,
thisCellLifetime: 0.7,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 22
{
readMeTextView.text = "Combing the emitters is naturally designed for the circular explosion cases.  However, if you use the combing algorithm for other shapes like lines or rectangles, you can get some unique artistic displays."
readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 300)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ”ด")
thisArrayAsText.append("๐ŸŸก")
thisArrayAsText.append("๐Ÿ”ต")
thisArrayAsText.append("๐ŸŸข")
thisArrayAsText.append("๐ŸŸฃ")
thisArrayAsText.append("โšช๏ธ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, scaleFactor: 1.4, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 0,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 150,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 1,
thisEndingScale: 0.3,
thisCellBirthrate: 30,
thisCellLifetime: 0.4,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.2)
}
if countOfTouches == 23
{
readMeTextView.text = "Combing the emitters is naturally designed for the circular explosion cases.  However, if you use the combing algorithm for other shapes like lines or rectangles, you can get some unique artistic displays."
readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 300)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ”ด")
thisArrayAsText.append("๐ŸŸก")
thisArrayAsText.append("๐Ÿ”ต")
thisArrayAsText.append("๐ŸŸข")
thisArrayAsText.append("๐ŸŸฃ")
thisArrayAsText.append("โšช๏ธ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedSideOfRectangle(thisSide: EmojiFireworksAndExplosionsPackage.Sides.Top, thisRectangle: readMeTextView.frame, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 0,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1,overrideAngleIncrementWithThisManyDegrees: 12)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 250,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 1,
thisEndingScale: 0.3,
thisCellBirthrate: 30,
thisCellLifetime: 0.4,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.2)
}

if countOfTouches == 24
{
readMeTextView.frame = CGRect(x: 500, y:  150, width: 445, height: 150)
readMeTextView.text = "You get an amazing amount of animation and flexibility for about 10 lines of code ๐Ÿง"

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ”ด")
thisArrayAsText.append("๐ŸŸก")
thisArrayAsText.append("๐Ÿ”ต")
thisArrayAsText.append("๐ŸŸข")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let pointOne = CGPoint(x: 0, y: 0)
let pointTwo = CGPoint(x: 1024, y: 1360)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, thisCountOfEmittersGeneratingSparks : useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 0,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0.01,
combArcFactor: 1,overrideAngleIncrementWithThisManyDegrees: 12)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 150,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 0,
thisStartingScale: 1,
thisEndingScale: 0.3,
thisCellBirthrate: 30,
thisCellLifetime: 0.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2)
}
if countOfTouches == 25
{
readMeTextView.text = "Your can program two or more explosions at the same time and same place if you create two instances.\n\nThe possibilities do seem to approach endlessness.\nHere we show one implosion and one explosion together."
readMeTextView.frame = CGRect(x: 100, y:  1000, width: 845, height: 260)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โšก๏ธ")
thisArrayAsText.append("๐Ÿงจ")

fireworksAndExplosionsEngine.stopCombingTheEmitters()

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 120,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.8,
thisEndingScale: 0.3,
thisCellBirthrate: 15,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 1.5)

thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿคฏ")
thisArrayAsText.append("๐ŸŽ")
thisArrayAsText.append("๐Ÿฅถ")
thisArrayAsText.append("๐Ÿ‘ป")

fireworksAndExplosionsEngine2.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine2.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 500), thisCircleRadius: 400, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine2.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 180,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine2.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 750,
thisVelocityRange: 250,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.25,
thisEndingScale: 0.0,
thisCellBirthrate: 31,
thisCellLifetime: 0.7,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.2)
}
if countOfTouches == 26
{
readMeTextView.text = "Here are two explosions side by side."
readMeTextView.frame = CGRect(x: 100, y:  1000, width: 845, height: 160)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿคฏ")
thisArrayAsText.append("๐ŸŽ")
thisArrayAsText.append("๐Ÿฅถ")
thisArrayAsText.append("๐Ÿ‘ป")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 250, y: 500), thisCircleRadius: 100, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 90,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 950,
thisVelocityRange: 250,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.25,
thisEndingScale: 0.0,
thisCellBirthrate: 31,
thisCellLifetime: 1,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.3)

thisArrayAsText.append("๐ŸฆŠ")
thisArrayAsText.append("๐ŸŒบ")
thisArrayAsText.append("๐Ÿ“")
thisArrayAsText.append("๐Ÿช€")

fireworksAndExplosionsEngine2.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine2.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 750, y: 500), thisCircleRadius: 100, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine2.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 90,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine2.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 950,
thisVelocityRange: 250,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.25,
thisEndingScale: 0.0,
thisCellBirthrate: 31,
thisCellLifetime: 1,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.3)
}

if countOfTouches == 27
{
// see handleTimerEvent

// Stop the combing from the end of the last pass through the count.
fireworksAndExplosionsEngine.stopCombingTheEmitters()
fireworksAndExplosionsEngine2.stopCombingTheEmitters()
fireworksAndExplosionsEngine3.stopCombingTheEmitters()

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

readMeTextView.text = "Here are 3 explosions that repeat at different time intervals."
readMeTextView.frame = CGRect(x: 100, y:  1200, width: 845, height: 120)

timerRunning = true

thisArrayAsText.append("๐Ÿคฏ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

thisArrayAsText.removeAll()
thisArrayAsText.append("โŽ")
thisArrayAsText.append("๐Ÿ…พ๏ธ")

fireworksAndExplosionsEngine2.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 180,
desiredOffsetAngleForShape : 0,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1)

fireworksAndExplosionsEngine2.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

thisArrayAsText.removeAll()
thisArrayAsText.append("โค๏ธ")
thisArrayAsText.append("๐Ÿค")
thisArrayAsText.append("๐Ÿ’™")

fireworksAndExplosionsEngine3.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)
}
if countOfTouches == 28
{
timerRunning = false

// Stop the combing from above
fireworksAndExplosionsEngine.stopCombingTheEmitters()

readMeTextView.frame = CGRect(x: 100, y:  900, width: 845, height: 340)

readMeTextView.text = "You can specify a direction angle for the cells to flow towards and specify a spreading cone factor too.\n\n               direction angle = 90 degrees\n               cone factor     = 25 percent"

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿคฏ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 300), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combAllEmittersToPointInDesiredDirectionWithDesiredCone(directionAngleForCellFlow: 90, coneWideningFactorNormallyZero: 0.25)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 900,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 0.1,
thisEndingScale: 4,
thisCellBirthrate: 30,
thisCellLifetime: 1.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.75)
}

if countOfTouches == 29
{
timerRunning = false

// Stop the combing from above
fireworksAndExplosionsEngine.stopCombingTheEmitters()

readMeTextView.frame = CGRect(x: 100, y:  900, width: 845, height: 340)

readMeTextView.text = "You can specify a direction angle for the cells to flow towards and specify a spreading cone factor too.\n\n               direction angle = 180 degrees\n               cone factor     = 10 percent"

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿงš๐Ÿฝโ€โ™€๏ธ")
thisArrayAsText.append("๐Ÿงžโ€โ™‚๏ธ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 300), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combAllEmittersToPointInDesiredDirectionWithDesiredCone(directionAngleForCellFlow: 180, coneWideningFactorNormallyZero: 0.1)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 500,
thisVelocityRange: 220,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 0.1,
thisEndingScale: 0.4,
thisCellBirthrate: 30,
thisCellLifetime: 0.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 0.75)
}
if countOfTouches == 30
{
timerRunning = false

// Stop the combing from above
fireworksAndExplosionsEngine.stopCombingTheEmitters()

readMeTextView.frame = CGRect(x: 100, y:  900, width: 845, height: 340)

readMeTextView.text = "You can specify a direction angle for the cells to flow towards and specify a spreading cone factor too.\n\n               direction angle = 270 degrees\n               cone factor     = 10 percent\n\nAdd gravity to produce a fountain effect."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’œ")
thisArrayAsText.append("๐Ÿงก")
thisArrayAsText.append("โค๏ธ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 800), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combAllEmittersToPointInDesiredDirectionWithDesiredCone(directionAngleForCellFlow: 270, coneWideningFactorNormallyZero: 0.10)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 900,
thisVelocityRange: 420,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 1.85,
thisStartingScaleRange: 0,
thisEndingScale: 0,
thisAccelerationIn_Y : 900,
thisCellBirthrate: 11,
thisCellLifetime: 2,
thisCellLifetimeRange: 0,
thisExplosionDuration: 3.5)
}
if countOfTouches == 31
{
timerRunning = false

// Stop the combing from above
fireworksAndExplosionsEngine.stopCombingTheEmitters()

readMeTextView.frame = CGRect(x: 100, y:  1000, width: 845, height: 240)

readMeTextView.text = "We call this stream and splat.\n\nSeveral streams with more gravity could simulate a waterfall or cascade effect."

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’œ")
thisArrayAsText.append("๐Ÿงก")
thisArrayAsText.append("โค๏ธ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 20, y: 300), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

fireworksAndExplosionsEngine.combAllEmittersToPointInDesiredDirectionWithDesiredCone(directionAngleForCellFlow: 0, coneWideningFactorNormallyZero: 0.01)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 400,
thisVelocityRange: 20,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 0.1,
thisStartingScaleRange: 0,
thisEndingScale: 0.2,
thisAccelerationIn_Y : 100,
thisCellBirthrate: 23,
thisCellLifetime: 2,
thisCellLifetimeRange: 0,
thisExplosionDuration: 13.5)
}
if countOfTouches == 32
{
timerRunning = false

// Stop the combing from above
fireworksAndExplosionsEngine2.stopCombingTheEmitters()

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’œ")
thisArrayAsText.append("๐Ÿงก")
thisArrayAsText.append("โค๏ธ")

fireworksAndExplosionsEngine2.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine2.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 800, y: 480), thisCircleRadius: 0, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions)

//fireworksAndExplosionsEngine2.combAllEmittersToPointInDesiredDirectionWithDesiredCone(directionAngleForCellFlow: 0, coneWideningFactorNormallyZero: 0.01)

fireworksAndExplosionsEngine2.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 120,
thisVelocityRange: 20,
thisSpin: 0,
thisSpinRange: 4,
thisStartingScale: 0.1,
thisStartingScaleRange: 0,
thisEndingScale: 0.2,
thisCellBirthrate: 23,
thisCellLifetime: 1,
thisCellLifetimeRange: 0,
thisExplosionDuration: 13.5)
}
if countOfTouches == 33
{
// Stop the combing from the end of the last pass through the count.
fireworksAndExplosionsEngine.stopCombingTheEmitters()
fireworksAndExplosionsEngine2.hideAllEmitters()

readMeTextView.text = "\nYou can specify a relative direction for the emitters to flow away from any rectangle, and a cone for that direction.\n\n Each side can get it's own unique angle and cone values."

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ”ด")
thisArrayAsText.append("๐ŸŸก")
thisArrayAsText.append("๐Ÿ”ต")
thisArrayAsText.append("๐ŸŸข")
thisArrayAsText.append("๐ŸŸฃ")
fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(
thisRectangle: readMeTextView.frame,
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
combEmittersDesired: true,
topDesiredCombingRelativeAngle: 0,
topConeWideningFactorNormallyZero: 0.05,
bottomDesiredCombingRelativeAngle: 75,
bottomConeWideningFactorNormallyZero: 0.1,
leftDesiredCombingRelativeAngle: 30,
leftConeWideningFactorNormallyZero: 0.15,
rightDesiredCombingRelativeAngle: -30,
rightConeWideningFactorNormallyZero: 0.2)

fireworksAndExplosionsEngine.detonate(

thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 540,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 0.1,
thisEndingScale: 0.0,
thisCellBirthrate: 500,
thisCellLifetime: 0.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 3.14)
}
if countOfTouches == 34
{
// Stop the combing from the end of the last pass through the count.
fireworksAndExplosionsEngine.stopCombingTheEmitters()

readMeTextView.text = "\nYou can specify a relative direction for the emitters to flow away from a rectangle, and a cone for that direction.\n\n Each side can get it's own unique angle and cone values."

readMeTextView.frame = CGRect(x: 200, y:  500, width: 600, height: 400)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’œ")
thisArrayAsText.append("๐Ÿงก")
thisArrayAsText.append("โค๏ธ")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedRectangle(
thisRectangle: readMeTextView.frame,
scaleFactor : 1.25,
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
combEmittersDesired: true,
topDesiredCombingRelativeAngle: 180,
topConeWideningFactorNormallyZero: 0.05,
bottomDesiredCombingRelativeAngle: 180,
bottomConeWideningFactorNormallyZero: 0.05,
leftDesiredCombingRelativeAngle: 180,
leftConeWideningFactorNormallyZero: 0.05,
rightDesiredCombingRelativeAngle: 180,
rightConeWideningFactorNormallyZero: 0.05)

fireworksAndExplosionsEngine.detonate(

thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 80,
thisVelocityRange: 30,
thisSpin: 2,
thisSpinRange: 0,
thisStartingScale: 0.65,
thisEndingScale: 0.2,
thisCellBirthrate: 100,
thisCellLifetime: 1,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.14)
}
if countOfTouches == 35
{
// Stop the combing from the end of the last pass through the count.
fireworksAndExplosionsEngine.stopCombingTheEmitters()

readMeTextView.text = "Your can specify ellipse based shapes for the fireworks / explosions and choose to comb, or not to comb."
readMeTextView.frame = CGRect(x: 200, y:  1100, width: 600, height: 150)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โœ…")
thisArrayAsText.append("๐Ÿ…ฐ๏ธ")
thisArrayAsText.append("โ˜ฎ๏ธ")
thisArrayAsText.append("๐Ÿ†š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedEllipse(thisCenter: CGPoint(x: 500, y: 700), thisMajorRadius: 300, thisMinorRadius: 200, alphaAngleInDegrees: 0, omegaAngleInDegreesUsedForRotation: -40, thisScaleFactor: 1, thisCountOfEmittersGeneratingSparks: -1)

fireworksAndExplosionsEngine.combEllipticalEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow: 45, coneWideningFactorNormallyZero: 0.0)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: useAllObjectsInExplosions,
thisVelocity: 150,
thisVelocityRange: 0,
thisSpin: 1,
thisSpinRange: 2,
thisStartingScale: 0.6,
thisEndingScale: 0.1,
thisCellBirthrate: 29,
thisCellLifetime: 0.6,
thisCellLifetimeRange: 0,
thisExplosionDuration: 4.1)
}
if countOfTouches == 36
{
readMeTextView.text = "Your explosions / fireworks can come from a heart shape.  You can comb the flow towards the center, or comb it outwards, or comb it with any offsetting angle."
readMeTextView.alpha = 1
readMeTextView.frame = CGRect(x: 175, y:  1100, width: 740, height: 230)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โค๏ธ")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let pointsOnHeart : Int = 120

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedHeart(thisHeartCenter: CGPoint(x: 500, y: 500), thisHeartScaleFactor: 20, thisCountOfEmittersGeneratingSparks: pointsOnHeart)

// 180 below will offset them to flow outwards and away from the center.
fireworksAndExplosionsEngine.combHeartEmittersTowardsHeartCenter(desiredOffsetAngleForCellFlowInDegrees : 180,
coneWideningFactorNormallyZero: 0.05)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: pointsOnHeart,
thisVelocity: 200,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 0.6,
thisEndingScale: 0,
thisCellBirthrate: 70,
thisCellLifetime: 0.5,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4)
}
if countOfTouches == 37
{
readMeTextView.text = "You can comb any explosion to flow towards (or away from any specified point), with any offsetting angle.\n\nTowards shown here."
readMeTextView.alpha = 1
readMeTextView.frame = CGRect(x: 175, y:  1100, width: 740, height: 230)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โค๏ธ")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let pointsOnShape : Int = 120

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 500), thisCircleRadius: 300, thisCircleArcFactor: 1, offsetAngleInDegrees: 0, scaleFactor: 1, thisCountOfEmittersGeneratingSparks: pointsOnShape)

fireworksAndExplosionsEngine.combEmittersTowardsOrAwayFromSpecifiedPoint(thisPoint: CGPoint(x: 0, y: 500), desiredOffsetAngleForCellFlowInDegrees : 0,  coneWideningFactorNormallyZero: 0, thisCountOfEmittersGeneratingSparks : pointsOnShape)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: pointsOnShape,
thisVelocity: 200,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 2,
thisStartingScale: 0.6,
thisEndingScale: 0,
thisCellBirthrate: 70,
thisCellLifetime: 1,
thisCellLifetimeRange: 0,
thisExplosionDuration: 2.4)
}
if countOfTouches == 38
{
readMeTextView.text = "You can comb any explosion to flow towards (or away from any specified point), with any offsetting angle.\n\nAway shown here."
readMeTextView.alpha = 1
readMeTextView.frame = CGRect(x: 175, y:  1100, width: 740, height: 230)

var thisArrayAsText = [String](https://raw.github.com/MichaelKucinski/EmitterFireworksAndExplosionsPackage/master/)

thisArrayAsText.append("โค๏ธ")
thisArrayAsText.append("๐Ÿ’›")
thisArrayAsText.append("๐Ÿ’™")
thisArrayAsText.append("๐Ÿ’š")

fireworksAndExplosionsEngine.alternateImageContentsWithGivenArray(
desiredArrayAsText: thisArrayAsText)

let pointsOnShape : Int = 120

let pointOne = CGPoint(x: 200, y: 600)
let pointTwo = CGPoint(x: 500, y: 900)

fireworksAndExplosionsEngine.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, thisCountOfEmittersGeneratingSparks : pointsOnShape)

// 180 below will offset them to flow away from the point.
fireworksAndExplosionsEngine.combEmittersTowardsOrAwayFromSpecifiedPoint(thisPoint: CGPoint(x: 300, y: 750), desiredOffsetAngleForCellFlowInDegrees : 180,  coneWideningFactorNormallyZero: 0.1, thisCountOfEmittersGeneratingSparks : pointsOnShape)

fireworksAndExplosionsEngine.detonate(
thisCountOfEmittersGeneratingSparks: pointsOnShape,
thisVelocity: 555,
thisVelocityRange: 0,
thisSpin: 0,
thisSpinRange: 18,
thisStartingScale: 0,
thisEndingScale: 1.5,
thisCellBirthrate: 150,
thisCellLifetime: 2,
thisCellLifetimeRange: 0.1,
thisExplosionDuration: 0.1)
}


previousCountOfTouches = countOfTouches

countOfTouches += 1
if countOfTouches == touchesEndValue
{
countOfTouches = 0
}

countView.text = ("Counter : \(previousCountOfTouches)")
countView.frame = CGRect(x: 5, y:  1300, width: 160, height: 50)

} // ends touchesBegan

var previousCountOfTouches = 0
var touchesEndValue = 39
}


GitHub

link
Stars: 1
Last commit: 3 years ago
Advertisement: IndiePitcher.com - Cold Email Software for Startups

Release Notes

EmitterFireworksAndExplosionsPackage initial release
3 years ago

EmitterFireworksAndExplosionsPackage initial release

Swiftpack is being maintained by Petr Pavlik | @ptrpavlik | @swiftpackco | API | Analytics