LitFuseBasicPackage

1.0.0

MichaelKucinski/LitFuseBasicPackage

What's New

Initial release for LitFuseBasicPackage

2020-07-27T02:02:17Z

Initial release

LitFuseBasicPackage

Lit Fuse Effects can be used to provide uniquely artistic and highly tailorable animation effects that your users will enjoy. These effects can be used to provide eye catching animations to help your users notice a certain area of the screen. These effects might be used in gaming, social media, advertising, or in any app with artistic content.

See example 4 minute video at the below link, and please recognize that it will be higher quality when running on an actual device.

https://drive.google.com/file/d/11Lk8fn9NS93S8RDFDb_2iusyy36QO67K/view

A variety of lit fuse effects are supported where the fuse particles are any sized emoji, or even short text, or a desired image. You can control the size/scale of the emitted cells.

I have exposed control of many cell properties in the visible APIs, which makes these lit fuse effects highly tailorable and uniquely artistic. You can command accelerations, spin, and much more! Many of the cell property parameters have a 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 createLitFuseEffectForDesiredRangeOfEmitters. 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 emoji detail as desired such that the fuse effects are a form of emoji art.

Lit Fuse Effects are generated by placing a trail of emitters on developer specified paths / shapes. The paths can easily be assigned to follow the frame of any UI object! Paths can also follow any combination of circle, line, and rectangle shapes specified.

Emitted cell velocities, cell scales, and cell birth rates are controlled to simulate a burning fuze effect. Developers can control the initial cell velocity, cell scale, and cell birth rate during placement of the fuse. Developers can specify a different velocity, scale, and birth rate while the fuse is burning. And they can specify the ending velocity, scale, and birth rate after burning, thereby simulating a residue (or ash), or no residue or trail left behind at all by specifying an ending scale of zero.

Similarly, you can control X and Y acceleration, spin, and more. Further below, please find the complete parameter list for createLitFuseEffectForDesiredRangeOfEmitters Note most of the parameters have a sensible default value, zero for spin and X and Y accelerations, etc.

The initial fuse path itself can be either visible or invisible depending on the value for cellInitialScale.

There are 3 stages where you can control the scale of the fuse particles or cells. Size/scale can be specified for the initial fuse path placement, while the fuse is actually burning, and a ending scale for the emitter particles after the fuse has burnt.

If the initial scale is zero, the fuse itself is invisible prior to burning. While burning, the scale needs to be greater than zero to see the burning action. If the ending scale of the emitters after the burn is specified to be non zero, then the burnt path will remain on the screen.

It should be noted that the burnt path that remains on the screen still consists of emitters that constantly emit cells at the last specified birthrate. Those cells can be made to look stationary if the ending cell velocity is zero. There is a subtlety in that the ending cell birthrate multiplied by the ending cell lifetime needs to be greater than 1 for there to be no flicker or strobing effect.

You can specify the ending cell birthrate and the lifetime in the API that creates the lit fuse effect.

Lit fuse effects can be commanded to run continuously, or to run repetively with a time gap between burns, or run as a one shot one time display of the desired animation.

You can specify how quickly the fuse burns by specifying stepsPerFrame. The larger it is, the faster the fuse burns.

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 fuse parameters may effect performance and produce lag. At first try using these effects with screens that are mostly static. A design that shows a fuse 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 fuse performance. Hiding the emitters helps free up resources. Please remember that each emoji cell seen on the screen is there because of an emitter that has a birthrate, and a lifetime specified. Stationary and unchanging emoji are still being born and living lifetimes under the covers, but they just happen to be in the same location. If you want the appearance of stationary and unchanging emoji as the ending state, just make sure the ending birthrate times the ending lifetime is greater than 1. Allow a little overlap.

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/LitFuseBasicPackage. Then follow the below instructions.

Usage

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

Below are code snippets that you can use to quickly get the Lit Fuse Effect working in your project.

First import the LitFuseBasicPackage

import LitFuseBasicPackage

Declare a LitFuseBasicViewController object


let litFuse = LitFuseBasicViewController()

If your design could benefit from having multiple lit fuse 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 litFuse1 = LitFuseBasicViewController()
let litFuse2 = LitFuseBasicViewController()
let litFuse3 = LitFuseBasicViewController()
let litFuse4 = LitFuseBasicViewController()

Make sure you call the litFuse.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.

litFuse.viewDidLoad()

litFuse.createPoolOfEmitters(maxCountOfEmitters : 400, someEmojiCharacter: "๐Ÿง ")

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

for thisEmitter in litFuse.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 a lit fuse effect, you may want to set an emoji pattern first.


litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸก", startIndex: 1, endIndex: 300)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ”ต", startIndex: 301, endIndex: 400)

Next, specify where your emitters are to be placed on the screen. Here is an example that builds two rectangles, and uses them as the fuse path.

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

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: tempRect,
startIndex: 1,
endIndex: 200)

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

litFuse.placeEmittersOnSpecifiedRectangle(
thisRectangle: tempRect,
startIndex: 201,
endIndex: 400)

Note that it can be so much easier if you already have an object on the screen that has a frame. That frame is a rectangle and it can be passed. In our prototype, we have a UITextView called readMeTextView, and below it's frame is passed so that the fuse path will actually trace its border.

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, startIndex: 201, endIndex: 400)

Note the scaleFactor is an optional parameter. A scaleFactor of 1.0 is right on the border, but if you want a standOff distance so the emitters surround the border with a buffer space, make the scale factor as large as desired, maybe 1.25 or so to get a 25 percent larger fuse path.

For placeEmittersOnSpecifiedRectangle, there is an optional parameter that will cause the fuse to burn counterclockwise instead of clockwise.

public func placeEmittersOnSpecifiedRectangle( thisRectangle : CGRect, startIndex : Int, endIndex : Int, scaleFactor : CGFloat = 1.0, counterClockwiseDesired : Bool = false)

Finally, make a call to createLitFuseEffectForDesiredRangeOfEmitters. Note that there are some optional parameters that this example doesn't use so you have more flexibility if desired. The below code will display the fuse effect continuously.


litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 1,
fuseBurningVelocity : 150,
fuseBurningBirthRate : 2200,
fuseBurningScale : 0.08,
endingVelocity : 0,
endingBirthRate : 2,
endingScale : 0,
stepsPerFrame : 1,
initialCellLifetime: 0.5,
fuseBurningCellLifetime: 0.5,
endingCellLifetime: 0.5,
continuousFuseDesired: true)

At some point, you may want to hide the lit fuse effect. Simply call


litFuse.hideAllEmitters()

Hiding the fuse effect with hideAllEmitters sets all the lifetimes to zero, which should relieve the GPU of any/all fuse processing.

The above should get you going!

You can change the fuse 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 createLitFuseEffectForDesiredRangeOfEmitters 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 fuse burning which includes acceleration, spin, tint color, and more :


public func createLitFuseEffectForDesiredRangeOfEmitters(
startIndex                  : Int,
endIndex                    : Int,
initialVelocity             : CGFloat = 0,
initialVelocityRange        : CGFloat = 0,
initialBirthRate            : CGFloat = 1,
initialScale                : CGFloat = 0,
initialScaleSpeed           : CGFloat = 0,
initialScaleRange           : CGFloat = 0,
initialSpin                 : CGFloat = 0,
initialSpinRange            : CGFloat = 0,
initialAcceleration_X       : CGFloat = 0,
initialAcceleration_Y       : CGFloat = 0,
initialAlphaSpeed           : CGFloat = 0,
initialAlphaRange           : CGFloat = 0,
initialTint                 : UIColor = .white,
fuseBurningVelocity         : CGFloat = 300,
fuseBurningVelocityRange    : CGFloat = 0,
fuseBurningBirthRate        : CGFloat = 100,
fuseBurningScale            : CGFloat = 1,
fuseBurningScaleSpeed       : CGFloat = 0,
fuseBurningScaleRange       : CGFloat = 0,
fuseBurningSpin             : CGFloat = 0,
fuseBurningSpinRange        : CGFloat = 0,
fuseBurningAcceleration_X   : CGFloat = 0,
fuseBurningAcceleration_Y   : CGFloat = 0,
fuseBurningAlphaSpeed       : CGFloat = 0,
fuseBurningAlphaRange       : CGFloat = 0,
fuseBurningTint             : UIColor = .white,
endingVelocity              : CGFloat = 0,
endingVelocityRange         : CGFloat = 0,
endingBirthRate             : CGFloat = 1,
endingScale                 : CGFloat = 0,
endingScaleSpeed            : CGFloat = 0,
endingScaleRange            : CGFloat = 0,
endingSpin                  : CGFloat = 0,
endingSpinRange             : CGFloat = 0,
endingAcceleration_X        : CGFloat = 0,
endingAcceleration_Y        : CGFloat = 0,
endingAlphaRange            : CGFloat = 0,
endingAlphaSpeed            : CGFloat = 0,
endingTint                  : UIColor = .white,
stepsPerFrame               : Int = 1,
initialCellLifetime         : CGFloat, // all lifetimes expressed in seconds
initialCellLifetimeRange    : CGFloat = 0,
fuseBurningCellLifetime     : CGFloat,
fuseBurningCellLifetimeRange  : CGFloat = 0,
endingCellLifetime          : CGFloat ,
endingCellLifetimeRange     : CGFloat = 0,
continuousFuseDesired       : Bool = false,
repeatingFuseDesired        : Bool = false,
timeBetweenRepeatsInSeconds : CGFloat = 0.5)

If you desire to specify a more complex emoji pattern for your fuse effect, you can build an array of emoji. That pattern will get repeated for the specified range of indices. Typically, you will let the indices cover your whole pool.


var arrayOfEmoji = [String]()

arrayOfEmoji.removeAll() // removeAll just in case you already built the array with different emoji already

for _ in 1...4 { arrayOfEmoji.append("๐Ÿฆ„") }
for _ in 1...3 { arrayOfEmoji.append("๐Ÿ") }
for _ in 1...2 { arrayOfEmoji.append("๐Ÿž") }
for _ in 1...1 { arrayOfEmoji.append("๐Ÿฆ‹") }

litFuse.alternateCellImagesWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(
desiredArrayAsText: arrayOfEmoji,
startIndex: 1,
endIndex: 400)

Instead of using emoji, you can specify a short string of text, such as "Hi" but that's a feature that hasn't been thoroughly designed for. It's one font and one color, white. However, the color can be adjusted by specifying the tint parameter. To get red text for example, specify :

endingTint: .red,

Search this readme for "endingTint" to see how we used it.

If you want to supply your own image, you need 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 :


litFuse.useSpecifiedImageAsContentsForDesiredRangeOfEmitters(specifiedImage: tempImageToUseWhenChangingCellImages, startIndex: 1, endIndex: 400)

where tempImageToUseWhenChangingCellImages is a UIImage.

If you want to place your fuse path on a line, here is some sample code :


let pointOne = CGPoint(x: 100, y: 100) 
let pointTwo = CGPoint(x: 200, y: 200)

litFuse.placeEmittersOnSpecifiedLine(
startingPoint: pointOne,
endingPoint: pointTwo,
startIndex: 1,
endIndex: 400)

If you want to place your fuse path on a circle, here is some sample code :


litFuse.placeEmittersOnSpecifiedCircleOrArc(
thisCircleCenter: CGPoint(x: 500, y: 700),
thisCircleRadius: 400,
thisCircleArcFactor: 1.0,
startIndex : 1,
endIndex: 400,
offsetAngleInDegrees: 45)

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 fuse path around the circle 3 times.

To comb the emitters such that their path radiates from a circle, here's some sample code :


litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 800), thisCircleRadius: 600, thisCircleArcFactor: 1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 123, scaleFactor: 0.5)

litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: true)

litFuse.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 180,
desiredOffsetAngleForShape : 123,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1,
startIndex: 1,
endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 100,
initialVelocityRange : 100,
initialBirthRate : 50,
initialScale : 0.1,
fuseBurningVelocity : 100,
fuseBurningVelocityRange: 100,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.1,
endingVelocity : 100,
endingVelocityRange : 100,
endingBirthRate : 5,
endingScale : 0.1,
stepsPerFrame : 1,
initialCellLifetime: 1.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)

If you want to stop the combing effect, you need to call these APIs :


litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: false)

// And stop the actual combing.
litFuse.stopCombingTheEmitters(startIndex : 1, endIndex: 400)

We have included an API that lets your design automatically change the emoji at any specified timing period. Note that you can only have one these running at a time. Your emoji changes can be any length, and the emoji go into an array to pass as a parameter. Here's code :


var thisArrayAsText = [String]()

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

litFuse.cycleToNewCellImageFromTextStringForDesiredRangeOfEmittersAtDesiredRate(desiredArrayAsText: thisArrayAsText, startIndex: 1, endIndex: 400, timeBetweenChanges: 1.25)

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 is my 2nd Swift Package on GitHub and it's a learning experience for me. 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 release code using it, please email me early on at engineermichigan@gmail.com 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. 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 : engineermichigan@gmail.com

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 lit fuses 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.

Initial use cases might choose short time duration effects that are queued at desired events in an app.

If you want to hide a fuse, after it is displayed, just call hideAllEmitters which sets the lifetimes to zero, effectively hiding all the cells.


litFuse.hideAllEmitters()

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

And it might be interesting to let developers specify a true path for the emitters to follow instead of specified circles, lines, and rectangles.

There are a couple of APIs that are kind of experimental right now. They couple the alpha speed or scale speed to the specified lifetime of the cells such that the the cells will either fade to invisible, or the scale will shrink to zero over the specified lifetime of the cells.

Here are example calls to these experimantal APIs. The scale speed API is more solid than the alpha speed API.


litFuse.syncAlphaSpeedToFadeOverLifetimeDesired(syncDesired: true)
litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: true)

As time permits, I will try to publish some new packages that depend on LitFuseBasicPackage to coordinate mulitiple lit fuse effects from a Package libary . I've already experimented with one that will let you burn fuses at both ends, and it looks very artistic.

โ€” Mike

P.S. If you want to run my driver code, below is a copy and paste of my whole ViewController.swift. Don't worry about the photos being missing. The code should still build and run, but you won't have the photos displayed to you like they do in my video link. 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 drawn fuse. 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
//  LitFuseBasicPackageDriver
//
//  Created by Michael Kucinski on 7/22/20.
//  Copyright ยฉ 2020 Michael Kucinski. All rights reserved.
//

import UIKit
import LitFuseBasicPackage

class ViewController: UIViewController {

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

let litFuse = LitFuseBasicViewController()

var arrayOfEmoji = [String]()

var kidsImageView = UIImageView()
var kidsCircleImageView = UIImageView()

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

kidsImageView.image =  UIImage(named: "kids.jpg")
kidsCircleImageView.image =  UIImage(named: "kidsCircle.png")

kidsImageView.frame = CGRect(x: 270, y:  920, width: 520, height: 390)
kidsCircleImageView.frame = CGRect(x: 260, y:  300, width: 500, height: 500)
self.view.addSubview(kidsImageView)
self.view.addSubview(kidsCircleImageView)

kidsCircleImageView.alpha = 0

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 800)
readMeTextView.textAlignment = NSTextAlignment.justified
readMeTextView.backgroundColor = UIColor.purple
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 = .white
readMeTextView.text = "This library lets you trace a variety of shapes with any number of emitters.  The emitters are presented in a burning fuse like fashion.\n\nShapes currently supported are circles, rectangles, and lines.\n\nYou can specify the frame of a photo or the frame of any object to use with this lit fuse effect! ๐Ÿ˜Ž \n\nThe emitted cells are highly configurable.\n\nThe cells can contain any combination of emoji or short text strings.\n\nThe emitters starting size, fuse burning size, and ending size are specified in a call to a single API.\n\nSimilarly, the emitted cell velocities for starting, fuse burning, and ending state can be specified."
self.view.addSubview(readMeTextView)
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."
self.view.addSubview(countView)
countView.isEditable = false
countView.allowsEditingTextAttributes = true // allows memoji
countView.isUserInteractionEnabled = false

litFuse.viewDidLoad()

litFuse.createPoolOfEmitters(maxCountOfEmitters : 400, someEmojiCharacter: "๐Ÿง ")

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

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(
desiredImageAsText: "๐ŸŸก",
startIndex: 1,
endIndex: 300)

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(
desiredImageAsText: "๐Ÿ”ต",
startIndex: 301,
endIndex: 400)

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

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: tempRect,
startIndex: 1,
endIndex: 200)

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

litFuse.placeEmittersOnSpecifiedRectangle(
thisRectangle: tempRect,
startIndex: 201,
endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters( startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0,
fuseBurningVelocity : 500,
fuseBurningBirthRate : 4800,
fuseBurningScale : 0.15,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.5,
stepsPerFrame : 1,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 0.2,
endingCellLifetime: 0.2,
continuousFuseDesired : true)

arrayOfEmoji.removeAll()

for _ in 1...4 { arrayOfEmoji.append("๐Ÿฆ„") }
for _ in 1...3 { arrayOfEmoji.append("๐Ÿ") }
for _ in 1...2 { arrayOfEmoji.append("๐Ÿž") }
for _ in 1...1 { arrayOfEmoji.append("๐Ÿ‘€") }

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(
desiredArrayAsText: arrayOfEmoji,
startIndex: 1,
endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters( startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0,
fuseBurningVelocity : 100,
fuseBurningBirthRate : 800,
fuseBurningScale : 0.4,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.5,
stepsPerFrame : 1,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 2.8,
endingCellLifetime: 0.2,
continuousFuseDesired: true)

let pointOne = CGPoint(x: 100, y: 100)

let pointTwo = CGPoint(x: 800, y: 1200)

litFuse.placeEmittersOnSpecifiedLine(
startingPoint: pointOne,
endingPoint: pointTwo,
startIndex: 1,
endIndex: 400)

/*
litFuse.placeEmittersOnSpecifiedCircleOrArc(
thisCircleCenter: CGPoint(x: 500, y: 700),
thisCircleRadius: 200,
thisCircleArcFactor: 1,
startIndex : 1,
endIndex: 400,
offsetAngleInDegrees: 45)
*/

litFuse.createLitFuseEffectForDesiredRangeOfEmitters( startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 15,
initialScale : 0.7,
initialSpin: -1,

//initialAcceleration_Y: 0,
initialTint: .cyan,
fuseBurningVelocity : 100,
fuseBurningBirthRate : 200,
fuseBurningScale : 0.5,
fuseBurningSpin: 1,
fuseBurningTint: .green,
//fuseBurningAcceleration_Y: 135500,

endingVelocity : 80,
endingBirthRate : 5,
endingScale : 0.5,
endingSpin: -1,
endingTint: .red,
stepsPerFrame : 1,
initialCellLifetime: 1,
fuseBurningCellLifetime: 2,
endingCellLifetime: 1.2,
continuousFuseDesired: true)



//litFuse.syncAlphaSpeedToFadeOverLifetimeDesired(syncDesired: true)
//litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: true)

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

//textOrEmojiToUIImage.text = "๐Ÿท"
//textOrEmojiToUIImage.sizeToFit()

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

//litFuse.useSpecifiedImageAsContentsForDesiredRangeOfEmitters(specifiedImage: tempImageToUseWhenChangingCellImages, startIndex: 1, endIndex: 400)

kidsImageView.alpha = 0

} // ends viewDidLoad

var countOfTouches = -1

// stub
//var countOfTouches = 27

// Detect touch
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?)
{
if countOfTouches == -1
{
litFuse.hideAllEmitters()

readMeTextView.alpha = 0
kidsImageView.alpha = 0

}
if countOfTouches == 0
{
kidsImageView.alpha = 1
readMeTextView.alpha = 1
readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 800)
readMeTextView.text = "This library lets you trace a variety of shapes with any number of emitters.  The emitters are presented in a burning fuse like fashion.\n\nShapes currently supported are circles, rectangles, and lines.\n\nYou can specify the frame of a photo or the frame of any object to use with this lit fuse effect! ๐Ÿ˜Ž \n\nThe emitted cells are highly configurable.\n\nThe cells can contain any combination of emoji or short text strings.\n\nThe emitters starting size, fuse burning size, and ending size are specified in a call to a single API.\n\nThe emitted cell velocities for starting, fuse burning, and ending state can be specified."
kidsImageView.frame = CGRect(x: 270, y:  920, width: 520, height: 390)
kidsCircleImageView.frame = CGRect(x: 260, y:  300, width: 500, height: 500)

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸก", startIndex: 1, endIndex: 300)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ”ต", startIndex: 301, endIndex: 400)

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, startIndex: 1, endIndex: 300, scaleFactor: 1.0, counterClockwiseDesired: true)
litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: kidsImageView.frame, startIndex: 301, endIndex: 400, scaleFactor: 1.0)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0,
fuseBurningVelocity : 500,
fuseBurningBirthRate : 5800,
fuseBurningScale : 0.15,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.5,
stepsPerFrame : 1,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 0.2,
endingCellLifetime: 0.2)

var thisArrayAsText = [String]()

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

//litFuse.cycleToNewCellImageFromTextStringForDesiredRangeOfEmittersAtDesiredRate(desiredArrayAsText: thisArrayAsText, startIndex: 1, endIndex: 400, timeBetweenChanges: 1.25)

}

if countOfTouches == 1
{
litFuse.hideAllEmitters()
kidsImageView.alpha = 0

readMeTextView.alpha = 0

readMeTextView.frame = CGRect(x: 100, y:  30, width: 845, height: 190)
}
if countOfTouches == 2
{
kidsImageView.alpha = 1

readMeTextView.alpha = 1

readMeTextView.text = "The lit fuse effect works with both rectangular and circular photos and objects.  You can simply specify the frame of an object for any rectangle.  You can specify a radius and center point for a circle. "

kidsImageView.alpha = 1
kidsCircleImageView.alpha = 1

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: " ", startIndex: 1, endIndex: 70)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ‡บ๐Ÿ‡ธ", startIndex: 71, endIndex: 360)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "Hi", startIndex: 361, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: kidsCircleImageView.center, thisCircleRadius: kidsCircleImageView.frame.width/2, thisCircleArcFactor: 1, startIndex : 71, endIndex: 360, offsetAngleInDegrees: 90, scaleFactor: 1.0)

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: kidsImageView.frame, startIndex: 361, endIndex: 400, scaleFactor: 1.2)

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, startIndex: 1, endIndex: 70, scaleFactor: 1.2)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 1.3,
initialTint: .yellow,
fuseBurningVelocity : 500,
fuseBurningBirthRate : 800,
fuseBurningScale : 0.45,
fuseBurningTint: .white,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 1.3,
endingTint: .red,
stepsPerFrame : 1,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 0.2,
endingCellLifetime: 0.2,
repeatingFuseDesired   : true,
timeBetweenRepeatsInSeconds: 3.5)
}

if countOfTouches == 3
{
litFuse.hideAllEmitters()
kidsImageView.alpha = 0
kidsCircleImageView.alpha = 0
kidsCircleImageView.frame = CGRect(x: 260, y:  400, width: 500, height: 500)

readMeTextView.alpha = 0

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 150)
}
if countOfTouches == 4
{
readMeTextView.alpha = 1

readMeTextView.text = "Circular and rectangular based emitter shapes can be drawn with any desired scale factor.  Here we used 4 different scale factors on half sections of circles."

kidsImageView.alpha = 0
kidsCircleImageView.alpha = 1

//litFuse.desiredRangeOfVisibleEmitters(startIndex: 1, endIndex: 400)

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ˜Ž", startIndex: 1, endIndex: 100)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "โฐ", startIndex: 101, endIndex: 200)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿคฏ", startIndex: 201, endIndex: 300)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŒŽ", startIndex: 301, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: kidsCircleImageView.center, thisCircleRadius: kidsCircleImageView.frame.width/4, thisCircleArcFactor: 0.5, startIndex : 1, endIndex: 100, offsetAngleInDegrees: -90, scaleFactor: 2.0)
litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: kidsCircleImageView.center, thisCircleRadius: kidsCircleImageView.frame.width/4, thisCircleArcFactor: -0.5, startIndex : 101, endIndex: 200, offsetAngleInDegrees: 90, scaleFactor: 2.3)
litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: kidsCircleImageView.center, thisCircleRadius: kidsCircleImageView.frame.width/4, thisCircleArcFactor: 0.5, startIndex : 201, endIndex: 300, offsetAngleInDegrees: -90, scaleFactor: 2.6)
litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: kidsCircleImageView.center, thisCircleRadius: kidsCircleImageView.frame.width/4, thisCircleArcFactor: -0.5, startIndex : 301, endIndex: 400, offsetAngleInDegrees: 90, scaleFactor: 2.9)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 1,
fuseBurningVelocity : 150,
fuseBurningBirthRate : 2200,
fuseBurningScale : 0.08,
endingVelocity : 0,
endingBirthRate : 2,
endingScale : 0,
stepsPerFrame : 1,
initialCellLifetime: 0.5,
fuseBurningCellLifetime: 0.5,
endingCellLifetime: 0.5,
continuousFuseDesired: true)
}
if countOfTouches == 5
{
litFuse.hideAllEmitters()

readMeTextView.alpha = 0
}
if countOfTouches == 6
{
readMeTextView.alpha = 1

readMeTextView.text = "You can specify any scale factor in the API calls that result in any desired standoff distance from any object or any shape."

kidsImageView.alpha = 1
kidsCircleImageView.alpha = 0
kidsImageView.frame = CGRect(x: 270, y:  520, width: 520, height: 390)

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ…ฐ๏ธ", startIndex: 1, endIndex: 80)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ†—", startIndex: 81, endIndex: 160)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "โ˜ฎ๏ธ", startIndex: 161, endIndex: 240)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿšผ", startIndex: 241, endIndex: 320)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ…ฟ๏ธ", startIndex: 321, endIndex: 400)

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: kidsImageView.frame, startIndex: 1, endIndex: 80, scaleFactor: 1.1)
litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: kidsImageView.frame, startIndex: 81, endIndex: 160, scaleFactor: 1.3)
litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: kidsImageView.frame, startIndex: 161, endIndex: 240, scaleFactor: 1.5)
litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: kidsImageView.frame, startIndex: 241, endIndex: 320, scaleFactor: 1.67)
litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: kidsImageView.frame, startIndex: 321, endIndex: 400, scaleFactor: 1.85)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0,
fuseBurningVelocity : 150,
fuseBurningBirthRate : 1500,
fuseBurningScale : 0.1,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.5,
stepsPerFrame : 1,
initialCellLifetime: 0.3,
fuseBurningCellLifetime: 0.3,
endingCellLifetime: 0.3)
}
if countOfTouches == 7
{
litFuse.hideAllEmitters()

readMeTextView.alpha = 0
}
if countOfTouches == 8
{
readMeTextView.alpha = 1

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 363)
readMeTextView.text = "You can specify any desired pattern of colorful emoji to be used as the sparks for the lit fuse.  Using many colored emojis results in fuses that burn with any desired color scheme as long as those colors can be found in any of Apples emoji.\n\nPlease note that there are ways to tint the cells as desired."

kidsImageView.alpha = 0
//kidsImageView.frame = CGRect(x: 270, y:  520, width: 520, height: 390)

arrayOfEmoji.removeAll()

for _ in 1...50
{
arrayOfEmoji.append("๐Ÿ”ด")
}
for _ in 1...50
{
arrayOfEmoji.append("๐ŸŸก")
}
for _ in 1...50
{
arrayOfEmoji.append("๐Ÿ’ฅ")
}
for _ in 1...50
{
arrayOfEmoji.append("๐Ÿ”•")
}
for _ in 1...50
{
arrayOfEmoji.append("๐Ÿ€")
}
for _ in 1...50
{
arrayOfEmoji.append("๐ŸŸฃ")
}
for _ in 1...1
{
for _ in 1...20
{
arrayOfEmoji.append("๐Ÿ‘€")
}
for _ in 1...20
{
arrayOfEmoji.append("๐Ÿฅถ")
}

for _ in 1...20
{
arrayOfEmoji.append("๐Ÿ‡")
}
for _ in 1...20
{
arrayOfEmoji.append("๐ŸฅŽ")
}
for _ in 1...20
{
arrayOfEmoji.append("๐ŸŽ")
}
}

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 500, y: 900), thisCircleRadius: 300, thisCircleArcFactor: 1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 90, scaleFactor: 1.0)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0.0,
fuseBurningVelocity : 1000,
fuseBurningBirthRate : 2800,
fuseBurningScale : 1.5,
endingVelocity : 0,
endingBirthRate : 10,
endingScale : 1.5,
stepsPerFrame : 1,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 0.2,
endingCellLifetime: 0.2)
}

if countOfTouches == 9
{
litFuse.hideAllEmitters()

readMeTextView.alpha = 0
}
if countOfTouches == 10
{
readMeTextView.alpha = 1

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 122)
readMeTextView.text = "You can command a lit fuse to burn continuously at any rate."

kidsImageView.alpha = 0

arrayOfEmoji.removeAll()

for _ in 1...10
{
arrayOfEmoji.append("๐Ÿ”ด")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸก")
}
for _ in 1...10
{
arrayOfEmoji.append("๐Ÿ”ต")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸ ")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸข")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸฃ")
}

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 550, y: 700), thisCircleRadius: 600, thisCircleArcFactor: 1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 90, scaleFactor: 0.5)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 50,
initialScale : 0.4,
fuseBurningVelocity : 100,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.4,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.4,
stepsPerFrame : 1,
initialCellLifetime: 1.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}

if countOfTouches == 11
{
litFuse.hideAllEmitters()
}
if countOfTouches == 12
{
//litFuse.hideAllEmitters()

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 15,
initialScale : 0.1,
fuseBurningVelocity : 1000,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.25,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.4,
stepsPerFrame : 5,
initialCellLifetime: 1.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}
if countOfTouches == 13
{
litFuse.hideAllEmitters()
}
if countOfTouches == 14
{
litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 550, y: 700), thisCircleRadius: 600, thisCircleArcFactor: -1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 90, scaleFactor: 0.5)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 15,
initialScale : 0.1,
fuseBurningVelocity : 70,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.25,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.4,
stepsPerFrame : 1,
initialCellLifetime: 1.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}
if countOfTouches == 15
{
litFuse.hideAllEmitters()
}
if countOfTouches == 16
{
readMeTextView.text = "You can choose an arc factor that can draw sub-arcs, or even wrap around the circle by any percent factor"

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 550, y: 700), thisCircleRadius: 600, thisCircleArcFactor: -0.5, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 90, scaleFactor: 0.5)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 15,
initialScale : 0.4,
fuseBurningVelocity : 70,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.4,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.4,
stepsPerFrame : 1,
initialCellLifetime: 1.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}
if countOfTouches == 17
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 1
}
if countOfTouches == 18
{
readMeTextView.text = "You can tint the emitted cells with differrent colors at initial placement, during fuse burning, and at ending state."

let pointOne = CGPoint(x: 200, y: 800)
let pointTwo = CGPoint(x: 900, y: 1300)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 1, endIndex: 400)

arrayOfEmoji.removeAll()

for _ in 1...4 { arrayOfEmoji.append("๐Ÿฆ„") }
for _ in 1...3 { arrayOfEmoji.append("๐Ÿ") }
for _ in 1...2 { arrayOfEmoji.append("๐Ÿž") }
for _ in 1...1 { arrayOfEmoji.append("๐Ÿ‘€") }

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(
desiredArrayAsText: arrayOfEmoji,
startIndex: 1,
endIndex: 400)

litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: true)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 50,
initialBirthRate : 55,
initialScale : 0.2,
initialSpin: -1,
initialTint: .orange,
fuseBurningVelocity : 100,
fuseBurningBirthRate : 200,
fuseBurningScale : 1.5,
fuseBurningSpin: 1,
fuseBurningTint: .white,
endingVelocity : 80,
endingBirthRate : 5,
endingScale : 0.5,
endingSpin: -1,
endingTint: .cyan,
stepsPerFrame : 1,
initialCellLifetime: 0.5,
fuseBurningCellLifetime: 4.5,
endingCellLifetime: 8.2)
}
if countOfTouches == 19
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 0
litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: false)

}
if countOfTouches == 20
{
readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 222)
readMeTextView.text = "You can command a lit fuse to burn periodically with a specified gap between.\n\nNote this fuse burns and leaves a trail behind as it burns."
readMeTextView.alpha = 1

//litFuse.desiredRangeOfVisibleEmitters(startIndex: 1, endIndex: 400)

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸก", startIndex: 1, endIndex: 200)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐Ÿ”ต", startIndex: 201, endIndex: 400)

let pointOne = CGPoint(x: 100, y: 400)
let pointTwo = CGPoint(x: 800, y: 1200)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 1, endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 1.5,
initialScale : 0,
fuseBurningVelocity : 500,
fuseBurningBirthRate : 1111,
fuseBurningScale : 0.25,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.2,
stepsPerFrame : 1,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 0.2,
endingCellLifetime: 0.2,
repeatingFuseDesired: true,
timeBetweenRepeatsInSeconds: 1)
}

if countOfTouches == 21
{
litFuse.hideAllEmitters()
}
if countOfTouches == 22
{
readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 122)
readMeTextView.text = "Note that this fuse burns the trail and leaves nothing behind."
readMeTextView.alpha = 1

let pointOne = CGPoint(x: 500, y: 400)
let pointTwo = CGPoint(x: 500, y: 1200)

arrayOfEmoji.removeAll()

arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’™")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’Ÿ")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("๐Ÿ’˜")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("โค๏ธ")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’›")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿ’œ")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿงก")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ") // multiple emoji works fine
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿค‘ ๐Ÿฅถ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ ๐Ÿฆ‹ ๐Ÿ‡ ๐ŸŽ")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")
arrayOfEmoji.append("๐Ÿ˜Ž ๐Ÿฆœ ๐Ÿฆ„ ๐Ÿคฏ ๐Ÿง›๐Ÿปโ€โ™‚๏ธ ๐Ÿ’๐Ÿผโ€โ™€๏ธ ๐Ÿงš๐Ÿฝโ€โ™‚๏ธ ๐Ÿฆ‰")

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 1, endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 6,
initialScale : 0.1,
fuseBurningVelocity : 500,
fuseBurningBirthRate : 1800,
fuseBurningScale : 1.1,
endingVelocity : 0,
endingBirthRate : 1,
endingScale : 0,
stepsPerFrame : 1,
initialCellLifetime: 0.3,
fuseBurningCellLifetime: 0.3,
endingCellLifetime: 0.3,
repeatingFuseDesired: true,
timeBetweenRepeatsInSeconds: 2)
}
if countOfTouches == 23
{
litFuse.hideAllEmitters()
}
if countOfTouches == 24
{
readMeTextView.frame = CGRect(x: 125, y:  805, width: 845, height: 350)
readMeTextView.text = "\nBesides the continuous and repeating lit fuses, you can also specify a one shot burn of a fuse.\n\nNote that a fuse can have as many parts as desired.\n\nFuses can combine many shapes together."

var pointOne = CGPoint(x: 250, y: 300)
var pointTwo = CGPoint(x: 250, y: 800)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 1, endIndex: 50)

pointOne = CGPoint(x: 450, y: 300)
pointTwo = CGPoint(x: 450, y: 800)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 51, endIndex: 100)

pointOne = CGPoint(x: 650, y: 300)
pointTwo = CGPoint(x: 650, y: 800)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 101, endIndex: 150)

pointOne = CGPoint(x: 850, y: 300)
pointTwo = CGPoint(x: 850, y: 800)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 151, endIndex: 200)

litFuse.placeEmittersOnSpecifiedRectangle(thisRectangle: readMeTextView.frame, startIndex: 201, endIndex: 400)

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฅ", startIndex: 1, endIndex: 25)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฉ", startIndex: 26, endIndex: 50)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸจ", startIndex: 51, endIndex: 75)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฆ", startIndex: 76, endIndex: 100)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸง", startIndex: 101, endIndex: 125)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸช", startIndex: 126, endIndex: 150)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฅ", startIndex: 151, endIndex: 175)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฉ", startIndex: 176, endIndex: 200)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸฅŽ", startIndex: 201, endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0,
fuseBurningVelocity : 777,
fuseBurningBirthRate : 5800,
fuseBurningScale : 0.3,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.5,
stepsPerFrame : 1,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 0.2,
endingCellLifetime: 0.2)
}

if countOfTouches == 25
{
litFuse.hideAllEmitters()
}
if countOfTouches == 26
{
readMeTextView.frame = CGRect(x: 45, y:  250, width: 830, height: 950)
readMeTextView.text = "You can specify any repeating pattern of emoji to be used to populate the fuse.  Just place the emoji into an array and call and API designed for that.  For instance, this code was used to produce the emoji pattern used in the fuse shown here :\n\nfor _ in 1...4 { arrayOfEmoji.append(\"๐Ÿฆ„\") }\narrayOfEmoji.append(\" \")\nfor _ in 1...3 { arrayOfEmoji.append(\"๐Ÿ\") }\narrayOfEmoji.append(\" \")\nfor _ in 1...2 { arrayOfEmoji.append(\"๐Ÿž\") }\narrayOfEmoji.append(\" \")\nfor _ in 1...1 { arrayOfEmoji.append(\"๐Ÿฆ‹\") }\narrayOfEmoji.append(\" \")\n\nlitFuse.\nalternateCellImagesWithGivenArrayOfEmojiOrText\nForDesiredRangeOfEmitters\n(\ndesiredArrayAsText: arrayOfEmoji,\nstartIndex: 1,\nendIndex: 400\n)"

var pointOne = CGPoint(x: 50, y: 50)
var pointTwo = CGPoint(x: 850, y: 50)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 1, endIndex: 57)

pointOne = CGPoint(x: 50, y: 100)
pointTwo = CGPoint(x: 850, y: 100)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 58, endIndex: 114)

pointOne = CGPoint(x: 50, y: 150)
pointTwo = CGPoint(x: 850, y: 150)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 115, endIndex: 171)

pointOne = CGPoint(x: 50, y: 200)
pointTwo = CGPoint(x: 850, y: 200)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 172, endIndex: 228)

pointOne = CGPoint(x: 900, y: 50)
pointTwo = CGPoint(x: 900, y: 1300)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 229, endIndex: 314)

pointOne = CGPoint(x: 950, y: 50)
pointTwo = CGPoint(x: 950, y: 1300)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 315, endIndex: 400)

arrayOfEmoji.removeAll()

for _ in 1...4 { arrayOfEmoji.append("๐Ÿฆ„") }
arrayOfEmoji.append(" ")
for _ in 1...3 { arrayOfEmoji.append("๐Ÿ") }
arrayOfEmoji.append(" ")
for _ in 1...2 { arrayOfEmoji.append("๐Ÿž") }
arrayOfEmoji.append(" ")
for _ in 1...1 { arrayOfEmoji.append("๐Ÿฆ‹") }
arrayOfEmoji.append(" ")

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0,
fuseBurningVelocity : 1000,
fuseBurningBirthRate : 2200,
fuseBurningScale : 0.1,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0.9,
stepsPerFrame : 2,
initialCellLifetime: 0.2,
fuseBurningCellLifetime: 0.2,
endingCellLifetime: 0.2,
repeatingFuseDesired: true,
timeBetweenRepeatsInSeconds: 1.7)
}
if countOfTouches == 27
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 0
}

if countOfTouches == 28
{
var pointOne = CGPoint(x: 100, y: 300)
var pointTwo = CGPoint(x: 100, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 1, endIndex: 50)

pointOne = CGPoint(x: 200, y: 300)
pointTwo = CGPoint(x: 200, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 51, endIndex: 100)

pointOne = CGPoint(x: 300, y: 300)
pointTwo = CGPoint(x: 300, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 101, endIndex: 150)

pointOne = CGPoint(x: 400, y: 300)
pointTwo = CGPoint(x: 400, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 151, endIndex: 200)

pointOne = CGPoint(x: 500, y: 300)
pointTwo = CGPoint(x: 500, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 201, endIndex: 250)

pointOne = CGPoint(x: 600, y: 300)
pointTwo = CGPoint(x: 600, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 251, endIndex: 300)

pointOne = CGPoint(x: 700, y: 300)
pointTwo = CGPoint(x: 700, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 301, endIndex: 350)

pointOne = CGPoint(x: 800, y: 300)
pointTwo = CGPoint(x: 800, y: 700)

litFuse.placeEmittersOnSpecifiedLine(startingPoint: pointOne, endingPoint: pointTwo, startIndex: 351, endIndex: 400)

litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฅ", startIndex: 1, endIndex: 50)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฉ", startIndex: 51, endIndex: 100)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸจ", startIndex: 101, endIndex: 150)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฆ", startIndex: 151, endIndex: 200)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸง", startIndex: 201, endIndex: 250)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸช", startIndex: 251, endIndex: 300)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฅ", startIndex: 301, endIndex: 350)
litFuse.setCellImageFromTextStringForDesiredRangeOfEmitters(desiredImageAsText: "๐ŸŸฉ", startIndex: 351, endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 0,
initialBirthRate : 5,
initialScale : 0,
fuseBurningVelocity : 250,
fuseBurningBirthRate : 1000,
fuseBurningScale : 0.2,
endingVelocity : 0,
endingBirthRate : 5,
endingScale : 0,
stepsPerFrame : 3,
initialCellLifetime: 0.01,
fuseBurningCellLifetime: 0.4,
endingCellLifetime: 0.2,
continuousFuseDesired: true)
}

if countOfTouches == 29
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 0
}

if countOfTouches == 30
{
readMeTextView.alpha = 1

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 322)
readMeTextView.text = "You can comb the emission angle!\n\nThe combing is based on circular arcs and the idea is to get emitters that line up radially, but variations are possible.  In order to see the effect you need to specify an initialVelocityRange that is non zero.  And there is no fuse burning, besides the whole circle burning like a sun."

kidsImageView.alpha = 0

arrayOfEmoji.removeAll()

for _ in 1...10
{
arrayOfEmoji.append("๐Ÿ”ด")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸก")
}
for _ in 1...10
{
arrayOfEmoji.append("๐Ÿ”ต")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸ ")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸข")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸฃ")
}

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 800), thisCircleRadius: 300, thisCircleArcFactor: 1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 0, scaleFactor: 0.5)

litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: true)

litFuse.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow: 0, coneWideningFactorNormallyZero: 0, combArcFactor: 1, startIndex: 1, endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 100,
initialVelocityRange : 100,
initialBirthRate : 50,
initialScale : 0.1,
fuseBurningVelocity : 100,
fuseBurningVelocityRange: 100,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.1,
endingVelocity : 100,
endingVelocityRange : 100,
endingBirthRate : 5,
endingScale : 0.1,
stepsPerFrame : 1,
initialCellLifetime: 1.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}

if countOfTouches == 31
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 0

// Stop this since it was started in last stage
litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: false)

// And stop the actual combing.
litFuse.stopCombingTheEmitters(startIndex : 1, endIndex: 400)
}

if countOfTouches == 32
{
readMeTextView.alpha = 1

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 322)
readMeTextView.text = "You can offset the angle.  Choosing a 180 degree offset flows the emitters inwards.\n\nOther offset values can make the flows less perpendicular to the circle."

kidsImageView.alpha = 0

arrayOfEmoji.removeAll()

for _ in 1...10
{
arrayOfEmoji.append("๐Ÿ”ด")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸก")
}
for _ in 1...10
{
arrayOfEmoji.append("๐Ÿ”ต")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸ ")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸข")
}
for _ in 1...10
{
arrayOfEmoji.append("๐ŸŸฃ")
}

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 800), thisCircleRadius: 600, thisCircleArcFactor: 1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 123, scaleFactor: 0.5)

litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: true)

litFuse.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 180,
desiredOffsetAngleForShape : 123,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1,
startIndex: 1,
endIndex: 400)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 100,
initialVelocityRange : 100,
initialBirthRate : 50,
initialScale : 0.1,
fuseBurningVelocity : 100,
fuseBurningVelocityRange: 100,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.1,
endingVelocity : 100,
endingVelocityRange : 100,
endingBirthRate : 5,
endingScale : 0.1,
stepsPerFrame : 1,
initialCellLifetime: 1.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}

if countOfTouches == 33
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 0

// Stop this since it was started in last stage
litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: false)

// And stop the actual combing.
litFuse.stopCombingTheEmitters(startIndex : 1, endIndex: 400)
}

if countOfTouches == 34
{
readMeTextView.alpha = 1

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 322)
readMeTextView.text = "You can have some of the cells flow inwards and some flow outwards at the same time.\n\nBy controlling the the circle radius, the initial cell lifetime, and the initial cell velocities you can get a thin ring with a hole, or a thicker ring with no hole."

kidsImageView.alpha = 0

arrayOfEmoji.removeAll()

for _ in 1...200
{
arrayOfEmoji.append("๐Ÿคฏ")
}

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 800), thisCircleRadius: 250, thisCircleArcFactor: 1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 90, scaleFactor: 0.5)

litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: true)

litFuse.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 0,
desiredOffsetAngleForShape : 90,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1,
startIndex: 1,
endIndex: 400)

litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: true)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 25,
initialVelocityRange : 200,
initialBirthRate : 30,
initialScale : 1.5,
fuseBurningVelocity : 100,
fuseBurningVelocityRange: 100,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.1,
endingVelocity : 100,
endingVelocityRange : 100,
endingBirthRate : 5,
endingScale : 0.1,
stepsPerFrame : 1,
initialCellLifetime: 2.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}

if countOfTouches == 35
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 0

// Stop this since it was started in last stage
litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: false)

// And stop the actual combing.
litFuse.stopCombingTheEmitters(startIndex : 1, endIndex: 400)

litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: false)

}

if countOfTouches == 36
{
readMeTextView.alpha = 1

readMeTextView.frame = CGRect(x: 100, y:  50, width: 845, height: 122)
readMeTextView.text = "You get an amazing amount of animation and flexibility for about 10 lines of code ๐Ÿง"

kidsImageView.alpha = 0

arrayOfEmoji.removeAll()

for _ in 1...200
{
arrayOfEmoji.append("๐Ÿฆ„")
}

litFuse.alternateImageContentsWithGivenArrayOfEmojiOrTextForDesiredRangeOfEmitters(desiredArrayAsText: arrayOfEmoji, startIndex: 1, endIndex: 400)

litFuse.placeEmittersOnSpecifiedCircleOrArc(thisCircleCenter: CGPoint(x: 512, y: 800), thisCircleRadius: 500, thisCircleArcFactor: 1, startIndex : 1, endIndex: 400, offsetAngleInDegrees: 90, scaleFactor: 0.5)

litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: true)

litFuse.combCircularEmittersToPointInDesiredDirections(desiredOffsetAngleForCellFlow : 0,
desiredOffsetAngleForShape : 90,
coneWideningFactorNormallyZero: 0,
combArcFactor: 1,
startIndex: 1,
endIndex: 400)

litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: true)

litFuse.createLitFuseEffectForDesiredRangeOfEmitters(
startIndex : 1,
endIndex : 400,
initialVelocity : 12,
initialVelocityRange : 80,
initialBirthRate : 30,
initialScale : 1.5,
fuseBurningVelocity : 100,
fuseBurningVelocityRange: 100,
fuseBurningBirthRate : 2800,
fuseBurningScale : 0.1,
endingVelocity : 100,
endingVelocityRange : 100,
endingBirthRate : 5,
endingScale : 0.1,
stepsPerFrame : 1,
initialCellLifetime: 2.0,
fuseBurningCellLifetime: 1.0,
endingCellLifetime: 1.0,
continuousFuseDesired: true)
}

if countOfTouches == 37
{
litFuse.hideAllEmitters()
readMeTextView.alpha = 0

// Stop this since it was started in last stage
litFuse.setFuseEmitterPhases(onlyUseInitialPlacementLogic: false)

// And stop the actual combing.
litFuse.stopCombingTheEmitters(startIndex : 1, endIndex: 400)

litFuse.syncScaleSpeedToShrinkOverLifetimeDesired(syncDesired: false)

}


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

countOfTouches += 1
if countOfTouches == touchesEndValue
{
countOfTouches = -1
kidsCircleImageView.alpha = 0
}

} // ends touchesBegan

var touchesEndValue = 38
}

Description

  • Swift Tools 5.2.0
View More Packages from this Author

Dependencies

  • None
Last updated: Thu Mar 14 2024 22:59:17 GMT-0900 (Hawaii-Aleutian Daylight Time)