{"version":3,"sources":["../src/ParticleUtils.ts","../src/PropertyNode.ts","../src/PropertyList.ts","../src/Emitter.ts","../src/Particle.ts","../src/PolygonalChain.ts","../src/PathParticle.ts","../src/AnimatedParticle.ts"],"names":["TextureFromString","PropertyNode","value","time","ease","this","next","isStepped","ParticleUtils","generateEase","createList","data","array","list","node","_a","first","hexToRGB","length","i","_b","value_1","time_1","start","end","pixiNS","pixi","GetTextureFromString","s","parseInt","exec","pixi.VERSION","Texture","fromImage","from","verbose","DEG_TO_RADS","Math","PI","rotatePoint","angle","p","sin","c","cos","xnew","x","y","ynew","combineRGBComponents","r","g","b","normalize","point","oneOverLen","scaleBy","sqrt","color","output","alpha","charAt","substr","indexOf","a","segments","qty","oneOverQty","t","cp","e","getBlendMode","name","BLEND_MODES","NORMAL","toUpperCase","replace","createSteppedGradient","numSteps","currentNode","current","nextIndex","lerp","curVal","nextVal","intValueSimple","intColorSimple","intValueComplex","intColorComplex","intValueStepped","intColorStepped","ticker","PropertyList","isColor","interpolate","prototype","reset","Particle","emitter","_this","_super","call","anchor","velocity","Point","rotationSpeed","rotationAcceleration","maxLife","age","extraData","alphaList","speedList","speedMultiplier","acceleration","maxSpeed","NaN","scaleList","scaleMultiplier","colorList","_doAlpha","_doScale","_doSpeed","_doAcceleration","_doColor","_doNormalMovement","_oneOverLife","prev","init","Particle_init","update","Particle_update","Sprite_destroy","destroy","Particle_destroy","applyArt","kill","__extends","rotation","noRotation","scale","tint","visible","art","texture","EMPTY","delta","deltaX","deltaY","speed","oldVX","oldVY","currentSpeed","position","newRotationSpeed","atan2","recycle","parent","removeChild","parseArt","baseTexture","window","console","warn","parseData","Sprite","PolygonalChain","countingLengths","totalLength","Array","isArray","chain","prevPoint","j","second","push","p1","p2","l","segLength","getRandomPoint","out","chosenSeg","rand","random","shared","Ticker","helperPoint","Emitter","particleParent","particleImages","config","_currentImageIndex","_particleConstructor","startAlpha","startSpeed","minimumSpeedMultiplier","startScale","minimumScaleMultiplier","startColor","minLifetime","maxLifetime","minStartRotation","maxStartRotation","minRotationSpeed","maxRotationSpeed","particleBlendMode","customEase","_frequency","spawnChance","maxParticles","emitterLifetime","spawnPos","spawnType","_spawnFunc","spawnRect","spawnCircle","spawnPolygonalChain","particlesPerWave","particleSpacing","angleStart","ownerPos","_prevEmitterPos","_prevPosIsValid","_posChanged","_parent","addAtBack","particleCount","_emit","_spawnTimer","_emitterLife","_activeParticlesFirst","_activeParticlesLast","_poolFirst","_origConfig","_origArt","_autoUpdate","_destroyWhenComplete","_completeCallback","rotate","updateSpawnPos","updateOwnerPos","Object","defineProperty","cleanup","particle","slice","partClass","startRotation","min","max","lifetime","blendMode","parseSpawnType","frequency","pos","initAdditional","clone","emit","undefined","autoUpdate","orderedArt","_spawnRect","Rectangle","w","h","_spawnCircle","Circle","_spawnRing","minRadius","minR","_spawnBurst","_spawnPoint","_spawnPolygonalChain","spawnPolygon","newRot","diff","resetPositionTracking","remove","add","playOnceAndDestroy","callback","playOnce","settings","TARGET_FPMS","prevX","prevY","curX","curY","emitPosX","emitPosY","len","particleConstructor","floor","applyAdditionalProperties","children","shift","pop","index","splice","unshift","addChildAt","addChild","cb","width","height","radius","MATH_FUNCS","WHITELISTER","RegExp","concat","join","PathParticle","path","initialRotation","initialPosition","movement","pathString","matches","match","Function","parsePath","error","AnimatedParticle","textures","duration","framerate","elapsed","loop","frame","outArr","outTextures","tex","dupe","count"],"mappings":"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","file":"dist/pixi-particles.min.js.map","sourcesContent":["import { BLEND_MODES, Point, Texture } from 'pixi.js';\nimport { PropertyNode, ValueStep } from './PropertyNode';\n// eslint-disable-next-line no-duplicate-imports\nimport * as pixi from 'pixi.js';\n// get Texture.from()/Texture.fromImage(), in V4 and V5 friendly methods\n/**\n * @hidden\n */\nlet TextureFromString: (s: string) => pixi.Texture;\n// to avoid Rollup transforming our import, save pixi namespace in a variable\nconst pixiNS = pixi;\n\nif (parseInt((/^(\\d+)\\./).exec(pixi.VERSION)[1], 10) < 5)\n{\n TextureFromString = pixiNS.Texture.fromImage;\n}\nelse\n{\n TextureFromString = (pixiNS as any).Texture.from;\n}\n\nexport function GetTextureFromString(s: string): Texture\n{\n return TextureFromString(s);\n}\n\nexport interface Color {\n r: number;\n g: number;\n b: number;\n a?: number;\n}\n\nexport interface EaseSegment {\n cp: number;\n s: number;\n e: number;\n}\n\nexport type SimpleEase = (time: number) => number;\n\n/**\n * Contains helper functions for particles and emitters to use.\n */\nexport namespace ParticleUtils {\n /**\n * If errors and warnings should be logged within the library.\n */\n export const verbose = false;\n\n export const DEG_TO_RADS = Math.PI / 180;\n\n /**\n * Rotates a point by a given angle.\n * @param angle The angle to rotate by in degrees\n * @param p The point to rotate around 0,0.\n */\n export function rotatePoint(angle: number, p: Point): void\n {\n if (!angle) return;\n angle *= ParticleUtils.DEG_TO_RADS;\n const s = Math.sin(angle);\n const c = Math.cos(angle);\n const xnew = (p.x * c) - (p.y * s);\n const ynew = (p.x * s) + (p.y * c);\n\n p.x = xnew;\n p.y = ynew;\n }\n\n /**\n * Combines separate color components (0-255) into a single uint color.\n * @param r The red value of the color\n * @param g The green value of the color\n * @param b The blue value of the color\n * @return The color in the form of 0xRRGGBB\n */\n export function combineRGBComponents(r: number, g: number, b: number/* , a*/): number\n {\n return /* a << 24 |*/ (r << 16) | (g << 8) | b;\n }\n\n /**\n * Reduces the point to a length of 1.\n * @param point The point to normalize\n */\n export function normalize(point: Point): void\n {\n const oneOverLen = 1 / ParticleUtils.length(point);\n\n point.x *= oneOverLen;\n point.y *= oneOverLen;\n }\n\n /**\n * Multiplies the x and y values of this point by a value.\n * @param point The point to scaleBy\n * @param value The value to scale by.\n */\n export function scaleBy(point: Point, value: number): void\n {\n point.x *= value;\n point.y *= value;\n }\n\n /**\n * Returns the length (or magnitude) of this point.\n * @param point The point to measure length\n * @return The length of this point.\n */\n export function length(point: Point): number\n {\n return Math.sqrt((point.x * point.x) + (point.y * point.y));\n }\n\n /**\n * Converts a hex string from \"#AARRGGBB\", \"#RRGGBB\", \"0xAARRGGBB\", \"0xRRGGBB\",\n * \"AARRGGBB\", or \"RRGGBB\" to an object of ints of 0-255, as\n * {r, g, b, (a)}.\n * @param color The input color string.\n * @param output An object to put the output in. If omitted, a new object is created.\n * @return The object with r, g, and b properties, possibly with an a property.\n */\n export function hexToRGB(color: string, output?: Color): Color\n {\n if (!output)\n {\n output = {} as Color;\n }\n if (color.charAt(0) === '#')\n {\n color = color.substr(1);\n }\n else if (color.indexOf('0x') === 0)\n {\n color = color.substr(2);\n }\n let alpha;\n\n if (color.length === 8)\n {\n alpha = color.substr(0, 2);\n color = color.substr(2);\n }\n output.r = parseInt(color.substr(0, 2), 16);// Red\n output.g = parseInt(color.substr(2, 2), 16);// Green\n output.b = parseInt(color.substr(4, 2), 16);// Blue\n if (alpha)\n {\n output.a = parseInt(alpha, 16);\n }\n\n return output;\n }\n\n /**\n * Generates a custom ease function, based on the GreenSock custom ease, as demonstrated\n * by the related tool at http://www.greensock.com/customease/.\n * @param segments An array of segments, as created by\n * http://www.greensock.com/customease/.\n * @return A function that calculates the percentage of change at\n * a given point in time (0-1 inclusive).\n */\n export function generateEase(segments: EaseSegment[]): SimpleEase\n {\n const qty = segments.length;\n const oneOverQty = 1 / qty;\n /*\n * Calculates the percentage of change at a given point in time (0-1 inclusive).\n * @param {Number} time The time of the ease, 0-1 inclusive.\n * @return {Number} The percentage of the change, 0-1 inclusive (unless your\n * ease goes outside those bounds).\n */\n\n // eslint-disable-next-line func-names\n return function (time: number): number\n {\n const i = (qty * time) | 0;// do a quick floor operation\n\n const t = (time - (i * oneOverQty)) * qty;\n const s = segments[i] || segments[qty - 1];\n\n return (s.s + (t * ((2 * (1 - t) * (s.cp - s.s)) + (t * (s.e - s.s)))));\n };\n }\n\n /**\n * Gets a blend mode, ensuring that it is valid.\n * @param name The name of the blend mode to get.\n * @return The blend mode as specified in the PIXI.BLEND_MODES enumeration.\n */\n export function getBlendMode(name: string): number\n {\n if (!name) return BLEND_MODES.NORMAL;\n name = name.toUpperCase();\n while (name.indexOf(' ') >= 0)\n {\n name = name.replace(' ', '_');\n }\n\n return (BLEND_MODES as any)[name] || BLEND_MODES.NORMAL;\n }\n\n /**\n * Converts a list of {value, time} objects starting at time 0 and ending at time 1 into an evenly\n * spaced stepped list of PropertyNodes for color values. This is primarily to handle conversion of\n * linear gradients to fewer colors, allowing for some optimization for Canvas2d fallbacks.\n * @param list The list of data to convert.\n * @param [numSteps=10] The number of steps to use.\n * @return The blend mode as specified in the PIXI.blendModes enumeration.\n */\n export function createSteppedGradient(list: ValueStep[], numSteps = 10): PropertyNode\n {\n if (typeof numSteps !== 'number' || numSteps <= 0)\n {\n numSteps = 10;\n }\n const first = new PropertyNode(ParticleUtils.hexToRGB(list[0].value), list[0].time);\n\n first.isStepped = true;\n let currentNode = first;\n let current = list[0];\n let nextIndex = 1;\n let next = list[nextIndex];\n\n for (let i = 1; i < numSteps; ++i)\n {\n let lerp = i / numSteps;\n // ensure we are on the right segment, if multiple\n\n while (lerp > next.time)\n {\n current = next;\n next = list[++nextIndex];\n }\n // convert the lerp value to the segment range\n lerp = (lerp - current.time) / (next.time - current.time);\n const curVal = ParticleUtils.hexToRGB(current.value);\n const nextVal = ParticleUtils.hexToRGB(next.value);\n const output: Color = {\n r: ((nextVal.r - curVal.r) * lerp) + curVal.r,\n g: ((nextVal.g - curVal.g) * lerp) + curVal.g,\n b: ((nextVal.b - curVal.b) * lerp) + curVal.b,\n };\n\n currentNode.next = new PropertyNode(output, i / numSteps);\n currentNode = currentNode.next;\n }\n\n // we don't need to have a PropertyNode for time of 1, because in a stepped version at that point\n // the particle has died of old age\n return first;\n }\n}\n","import { ParticleUtils, EaseSegment, SimpleEase, Color } from './ParticleUtils';\nimport { BasicTweenable } from './EmitterConfig';\n\nexport interface ValueStep {\n value: T;\n time: number;\n}\n\nexport interface ValueList {\n list: ValueStep[];\n isStepped?: boolean;\n ease?: SimpleEase|EaseSegment[];\n}\n/**\n * A single node in a PropertyList.\n */\nexport class PropertyNode\n{\n /**\n * Value for the node.\n */\n public value: V;\n /**\n * Time value for the node. Between 0-1.\n */\n public time: number;\n /**\n * The next node in line.\n */\n public next: PropertyNode;\n /**\n * If this is the first node in the list, controls if the entire list is stepped or not.\n */\n public isStepped: boolean;\n public ease: SimpleEase;\n\n /**\n * @param value The value for this node\n * @param time The time for this node, between 0-1\n * @param [ease] Custom ease for this list. Only relevant for the first node.\n */\n constructor(value: V, time: number, ease?: SimpleEase|EaseSegment[])\n {\n this.value = value;\n this.time = time;\n this.next = null;\n this.isStepped = false;\n if (ease)\n {\n this.ease = typeof ease === 'function' ? ease : ParticleUtils.generateEase(ease);\n }\n else\n {\n this.ease = null;\n }\n }\n\n /**\n * Creates a list of property values from a data object {list, isStepped} with a list of objects in\n * the form {value, time}. Alternatively, the data object can be in the deprecated form of\n * {start, end}.\n * @param data The data for the list.\n * @param data.list The array of value and time objects.\n * @param data.isStepped If the list is stepped rather than interpolated.\n * @param data.ease Custom ease for this list.\n * @return The first node in the list\n */\n // eslint-disable-next-line max-len\n public static createList(data: ValueList|BasicTweenable): PropertyNode\n {\n if ('list' in data)\n {\n const array = data.list;\n let node;\n const { value, time } = array[0];\n\n // eslint-disable-next-line max-len\n const first = node = new PropertyNode(typeof value === 'string' ? ParticleUtils.hexToRGB(value) : value, time, data.ease);\n\n // only set up subsequent nodes if there are a bunch or the 2nd one is different from the first\n if (array.length > 2 || (array.length === 2 && array[1].value !== value))\n {\n for (let i = 1; i < array.length; ++i)\n {\n const { value, time } = array[i];\n\n node.next = new PropertyNode(typeof value === 'string' ? ParticleUtils.hexToRGB(value) : value, time);\n node = node.next;\n }\n }\n first.isStepped = !!data.isStepped;\n\n return first as PropertyNode;\n }\n\n // Handle deprecated version here\n const start = new PropertyNode(typeof data.start === 'string' ? ParticleUtils.hexToRGB(data.start) : data.start, 0);\n // only set up a next value if it is different from the starting value\n\n if (data.end !== data.start)\n {\n start.next = new PropertyNode(typeof data.end === 'string' ? ParticleUtils.hexToRGB(data.end) : data.end, 1);\n }\n\n return start as PropertyNode;\n }\n}\n","import { ParticleUtils, SimpleEase, Color } from './ParticleUtils';\nimport { PropertyNode } from './PropertyNode';\n\nfunction intValueSimple(this: PropertyList, lerp: number): number\n{\n if (this.ease)\n { lerp = this.ease(lerp); }\n\n return ((this.next.value - this.current.value) * lerp) + this.current.value;\n}\n\nfunction intColorSimple(this: PropertyList, lerp: number): number\n{\n if (this.ease)\n { lerp = this.ease(lerp); }\n const curVal = this.current.value; const\n nextVal = this.next.value;\n const r = ((nextVal.r - curVal.r) * lerp) + curVal.r;\n const g = ((nextVal.g - curVal.g) * lerp) + curVal.g;\n const b = ((nextVal.b - curVal.b) * lerp) + curVal.b;\n\n return ParticleUtils.combineRGBComponents(r, g, b);\n}\n\nfunction intValueComplex(this: PropertyList, lerp: number): number\n{\n if (this.ease)\n { lerp = this.ease(lerp); }\n // make sure we are on the right segment\n while (lerp > this.next.time)\n {\n this.current = this.next;\n this.next = this.next.next;\n }\n // convert the lerp value to the segment range\n lerp = (lerp - this.current.time) / (this.next.time - this.current.time);\n\n return ((this.next.value - this.current.value) * lerp) + this.current.value;\n}\n\nfunction intColorComplex(this: PropertyList, lerp: number): number\n{\n if (this.ease)\n { lerp = this.ease(lerp); }\n // make sure we are on the right segment\n while (lerp > this.next.time)\n {\n this.current = this.next;\n this.next = this.next.next;\n }\n // convert the lerp value to the segment range\n lerp = (lerp - this.current.time) / (this.next.time - this.current.time);\n const curVal = this.current.value; const\n nextVal = this.next.value;\n const r = ((nextVal.r - curVal.r) * lerp) + curVal.r;\n const g = ((nextVal.g - curVal.g) * lerp) + curVal.g;\n const b = ((nextVal.b - curVal.b) * lerp) + curVal.b;\n\n return ParticleUtils.combineRGBComponents(r, g, b);\n}\n\nfunction intValueStepped(this: PropertyList, lerp: number): number\n{\n if (this.ease)\n { lerp = this.ease(lerp); }\n // make sure we are on the right segment\n while (this.next && lerp > this.next.time)\n {\n this.current = this.next;\n this.next = this.next.next;\n }\n\n return this.current.value;\n}\n\nfunction intColorStepped(this: PropertyList, lerp: number): number\n{\n if (this.ease)\n { lerp = this.ease(lerp); }\n // make sure we are on the right segment\n while (this.next && lerp > this.next.time)\n {\n this.current = this.next;\n this.next = this.next.next;\n }\n const curVal = this.current.value;\n\n return ParticleUtils.combineRGBComponents(curVal.r, curVal.g, curVal.b);\n}\n\n/**\n * Singly linked list container for keeping track of interpolated properties for particles.\n * Each Particle will have one of these for each interpolated property.\n */\nexport class PropertyList\n{\n /**\n * The current property node in the linked list.\n */\n public current: PropertyNode;\n /**\n * The next property node in the linked list. Stored separately for slightly less variable\n * access.\n */\n public next: PropertyNode;\n /**\n * Calculates the correct value for the current interpolation value. This method is set in\n * the reset() method.\n * @param lerp The interpolation value from 0-1.\n * @return The interpolated value. Colors are converted to the hex value.\n */\n public interpolate: (lerp: number) => number;\n /**\n * A custom easing method for this list.\n * @param lerp The interpolation value from 0-1.\n * @return The eased value, also from 0-1.\n */\n public ease: SimpleEase;\n /**\n * If this list manages colors, which requires a different method for interpolation.\n */\n private isColor: boolean;\n\n /**\n * @param isColor If this list handles color values\n */\n constructor(isColor = false)\n {\n this.current = null;\n this.next = null;\n this.isColor = !!isColor;\n this.interpolate = null;\n this.ease = null;\n }\n\n /**\n * Resets the list for use.\n * @param first The first node in the list.\n * @param first.isStepped If the values should be stepped instead of interpolated linearly.\n */\n public reset(first: PropertyNode): void\n {\n this.current = first;\n this.next = first.next;\n const isSimple = this.next && this.next.time >= 1;\n\n if (isSimple)\n {\n this.interpolate = this.isColor ? intColorSimple : intValueSimple;\n }\n else if (first.isStepped)\n {\n this.interpolate = this.isColor ? intColorStepped : intValueStepped;\n }\n else\n {\n this.interpolate = this.isColor ? intColorComplex : intValueComplex;\n }\n this.ease = this.current.ease;\n }\n}\n","import { ParticleUtils, Color, SimpleEase } from './ParticleUtils';\nimport { Particle } from './Particle';\nimport { PropertyNode } from './PropertyNode';\nimport { PolygonalChain } from './PolygonalChain';\nimport { EmitterConfig, OldEmitterConfig } from './EmitterConfig';\nimport { Point, Circle, Rectangle, Container, settings } from 'pixi.js';\n// eslint-disable-next-line no-duplicate-imports\nimport * as pixi from 'pixi.js';\n// get the shared ticker, in V4 and V5 friendly methods\n/**\n * @hidden\n */\nlet ticker: pixi.ticker.Ticker;\n// to avoid Rollup transforming our import, save pixi namespace in a variable\nconst pixiNS = pixi;\n\nif (parseInt((/^(\\d+)\\./).exec(pixi.VERSION)[1], 10) < 5)\n{\n ticker = pixiNS.ticker.shared;\n}\nelse\n{\n ticker = (pixiNS as any).Ticker.shared;\n}\n\nexport interface ParticleConstructor\n{\n new (emitter: Emitter): Particle;\n}\n\n/**\n * @hidden\n */\nconst helperPoint = new Point();\n\n/**\n * A particle emitter.\n */\nexport class Emitter\n{\n /**\n * The constructor used to create new particles. The default is\n * the built in particle class.\n */\n protected _particleConstructor: typeof Particle;\n // properties for individual particles\n /**\n * An array of PIXI Texture objects.\n */\n public particleImages: any[];\n /**\n * The first node in the list of alpha values for all particles.\n */\n public startAlpha: PropertyNode;\n /**\n * The first node in the list of speed values of all particles.\n */\n public startSpeed: PropertyNode;\n /**\n * A minimum multiplier for the speed of a particle at all stages of its life. A value between\n * minimumSpeedMultiplier and 1 is randomly generated for each particle.\n */\n public minimumSpeedMultiplier: number;\n /**\n * Acceleration to apply to particles. Using this disables\n * any interpolation of particle speed. If the particles do\n * not have a rotation speed, then they will be rotated to\n * match the direction of travel.\n */\n public acceleration: Point;\n /**\n * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\n * will disable the maximum speed.\n */\n public maxSpeed: number;\n /**\n * The first node in the list of scale values of all particles.\n */\n public startScale: PropertyNode;\n /**\n * A minimum multiplier for the scale of a particle at all stages of its life. A value between\n * minimumScaleMultiplier and 1 is randomly generated for each particle.\n */\n public minimumScaleMultiplier: number;\n /**\n * The first node in the list of color values of all particles, as red, green, and blue\n * uints from 0-255.\n */\n public startColor: PropertyNode;\n /**\n * The minimum lifetime for a particle, in seconds.\n */\n public minLifetime: number;\n /**\n * The maximum lifetime for a particle, in seconds.\n */\n public maxLifetime: number;\n /**\n * The minimum start rotation for a particle, in degrees. This value\n * is ignored if the spawn type is \"burst\" or \"arc\".\n */\n public minStartRotation: number;\n /**\n * The maximum start rotation for a particle, in degrees. This value\n * is ignored if the spawn type is \"burst\" or \"arc\".\n */\n public maxStartRotation: number;\n /**\n * If no particle rotation should occur. Starting rotation will still\n * affect the direction in which particles move. If the rotation speed\n * is set, then this will be ignored.\n */\n public noRotation: boolean;\n /**\n * The minimum rotation speed for a particle, in degrees per second.\n * This only visually spins the particle, it does not change direction\n * of movement.\n */\n public minRotationSpeed: number;\n /**\n * The maximum rotation speed for a particle, in degrees per second.\n * This only visually spins the particle, it does not change direction\n * of movement.\n */\n public maxRotationSpeed: number;\n /**\n * The Acceleration of rotation (angular acceleration) for a particle, in degrees per second.\n */\n public rotationAcceleration: number;\n /**\n * The blend mode for all particles, as named by PIXI.blendModes.\n */\n public particleBlendMode: number;\n /**\n * An easing function for nonlinear interpolation of values. Accepts a single\n * parameter of time as a value from 0-1, inclusive. Expected outputs are values\n * from 0-1, inclusive.\n */\n public customEase: SimpleEase;\n /**\n *\tExtra data for use in custom particles. The emitter doesn't look inside, but\n *\tpasses it on to the particle to use in init().\n */\n public extraData: any;\n // properties for spawning particles\n /**\n * Time between particle spawns in seconds.\n */\n protected _frequency: number;\n /**\n * Chance that a particle will be spawned on each opportunity to spawn one.\n * 0 is 0%, 1 is 100%.\n */\n public spawnChance: number;\n /**\n * Maximum number of particles to keep alive at a time. If this limit\n * is reached, no more particles will spawn until some have died.\n */\n public maxParticles: number;\n /**\n * The amount of time in seconds to emit for before setting emit to false.\n * A value of -1 is an unlimited amount of time.\n */\n public emitterLifetime: number;\n /**\n * Position at which to spawn particles, relative to the emitter's owner's origin.\n * For example, the flames of a rocket travelling right might have a spawnPos\n * of {x:-50, y:0}.\n * to spawn at the rear of the rocket.\n * To change this, use updateSpawnPos().\n */\n public spawnPos: Point;\n /**\n * How the particles will be spawned. Valid types are \"point\", \"rectangle\",\n * \"circle\", \"burst\", \"ring\".\n */\n public spawnType: string;\n /**\n * A reference to the emitter function specific to the spawn type.\n */\n protected _spawnFunc: (p: Particle, emitPosX: number, emitPosY: number, i?: number) => void;\n /**\n * A rectangle relative to spawnPos to spawn particles inside if the spawn type is \"rect\".\n */\n public spawnRect: Rectangle;\n /**\n * A polygon relative to spawnPos to spawn particles on the chain if the spawn type is \"polygonalChain\".\n */\n public spawnPolygonalChain: PolygonalChain;\n /**\n * A circle relative to spawnPos to spawn particles inside if the spawn type is \"circle\".\n */\n public spawnCircle: Circle & {minRadius: number};\n /**\n * Number of particles to spawn time that the frequency allows for particles to spawn.\n */\n public particlesPerWave: number;\n /**\n * Spacing between particles in a burst. 0 gives a random angle for each particle.\n */\n public particleSpacing: number;\n /**\n * Angle at which to start spawning particles in a burst.\n */\n public angleStart: number;\n /**\n * Rotation of the emitter or emitter's owner in degrees. This is added to\n * the calculated spawn angle.\n * To change this, use rotate().\n */\n protected rotation: number;\n /**\n * The world position of the emitter's owner, to add spawnPos to when\n * spawning particles. To change this, use updateOwnerPos().\n */\n protected ownerPos: Point;\n /**\n * The origin + spawnPos in the previous update, so that the spawn position\n * can be interpolated to space out particles better.\n */\n protected _prevEmitterPos: Point;\n /**\n * If _prevEmitterPos is valid, to prevent interpolation on the first update\n */\n protected _prevPosIsValid: boolean;\n /**\n * If either ownerPos or spawnPos has changed since the previous update.\n */\n protected _posChanged: boolean;\n /**\n * The container to add particles to.\n */\n protected _parent: Container;\n /**\n * If particles should be added at the back of the display list instead of the front.\n */\n public addAtBack: boolean;\n /**\n * The current number of active particles.\n */\n public particleCount: number;\n /**\n * If particles should be emitted during update() calls. Setting this to false\n * stops new particles from being created, but allows existing ones to die out.\n */\n protected _emit: boolean;\n /**\n * The timer for when to spawn particles in seconds, where numbers less\n * than 0 mean that particles should be spawned.\n */\n protected _spawnTimer: number;\n /**\n * The life of the emitter in seconds.\n */\n protected _emitterLife: number;\n /**\n * The particles that are active and on the display list. This is the first particle in a\n * linked list.\n */\n protected _activeParticlesFirst: Particle;\n /**\n * The particles that are active and on the display list. This is the last particle in a\n * linked list.\n */\n protected _activeParticlesLast: Particle;\n /**\n * The particles that are not currently being used. This is the first particle in a\n * linked list.\n */\n protected _poolFirst: Particle;\n /**\n * The original config object that this emitter was initialized with.\n */\n protected _origConfig: any;\n /**\n * The original particle image data that this emitter was initialized with.\n */\n protected _origArt: any;\n /**\n * If the update function is called automatically from the shared ticker.\n * Setting this to false requires calling the update function manually.\n */\n protected _autoUpdate: boolean;\n /**\n * A number keeping index of currently applied image. Used to emit arts in order.\n */\n protected _currentImageIndex = -1;\n /**\n * If the emitter should destroy itself when all particles have died out. This is set by\n * playOnceAndDestroy();\n */\n protected _destroyWhenComplete: boolean;\n /**\n * A callback for when all particles have died out. This is set by\n * playOnceAndDestroy() or playOnce();\n */\n protected _completeCallback: () => void;\n\n /**\n * @param particleParent The container to add the particles to.\n * @param particleImages A texture or array of textures to use\n * for the particles. Strings will be turned\n * into textures via Texture.fromImage().\n * @param config A configuration object containing settings for the emitter.\n * @param config.emit If config.emit is explicitly passed as false, the\n * Emitter will start disabled.\n * @param config.autoUpdate If config.autoUpdate is explicitly passed as\n * true, the Emitter will automatically call\n * update via the PIXI shared ticker.\n */\n constructor(particleParent: Container, particleImages: any, config: EmitterConfig|OldEmitterConfig)\n {\n this._particleConstructor = Particle;\n // properties for individual particles\n this.particleImages = null;\n this.startAlpha = null;\n this.startSpeed = null;\n this.minimumSpeedMultiplier = 1;\n this.acceleration = null;\n this.maxSpeed = NaN;\n this.startScale = null;\n this.minimumScaleMultiplier = 1;\n this.startColor = null;\n this.minLifetime = 0;\n this.maxLifetime = 0;\n this.minStartRotation = 0;\n this.maxStartRotation = 0;\n this.noRotation = false;\n this.minRotationSpeed = 0;\n this.maxRotationSpeed = 0;\n this.particleBlendMode = 0;\n this.customEase = null;\n this.extraData = null;\n // properties for spawning particles\n this._frequency = 1;\n this.spawnChance = 1;\n this.maxParticles = 1000;\n this.emitterLifetime = -1;\n this.spawnPos = null;\n this.spawnType = null;\n this._spawnFunc = null;\n this.spawnRect = null;\n this.spawnCircle = null;\n this.spawnPolygonalChain = null;\n this.particlesPerWave = 1;\n this.particleSpacing = 0;\n this.angleStart = 0;\n // emitter properties\n this.rotation = 0;\n this.ownerPos = null;\n this._prevEmitterPos = null;\n this._prevPosIsValid = false;\n this._posChanged = false;\n this._parent = null;\n this.addAtBack = false;\n this.particleCount = 0;\n this._emit = false;\n this._spawnTimer = 0;\n this._emitterLife = -1;\n this._activeParticlesFirst = null;\n this._activeParticlesLast = null;\n this._poolFirst = null;\n this._origConfig = null;\n this._origArt = null;\n this._autoUpdate = false;\n this._currentImageIndex = -1;\n this._destroyWhenComplete = false;\n this._completeCallback = null;\n\n // set the initial parent\n this.parent = particleParent;\n\n if (particleImages && config)\n {\n this.init(particleImages, config);\n }\n\n // save often used functions on the instance instead of the prototype for better speed\n this.recycle = this.recycle;\n this.update = this.update;\n this.rotate = this.rotate;\n this.updateSpawnPos = this.updateSpawnPos;\n this.updateOwnerPos = this.updateOwnerPos;\n }\n\n /**\n * If the emitter is using particle art in order as provided in `particleImages`.\n * Effective only when `particleImages` has multiple art options.\n * This is particularly useful ensuring that each art shows up once, in case you need to emit a body in an order.\n * For example: dragon - [Head, body1, body2, ..., tail]\n */\n public get orderedArt(): boolean { return this._currentImageIndex !== -1; }\n public set orderedArt(value)\n {\n this._currentImageIndex = value ? 0 : -1;\n }\n\n /**\n * Time between particle spawns in seconds. If this value is not a number greater than 0,\n * it will be set to 1 (particle per second) to prevent infinite loops.\n */\n public get frequency(): number { return this._frequency; }\n public set frequency(value)\n {\n // do some error checking to prevent infinite loops\n if (typeof value === 'number' && value > 0)\n {\n this._frequency = value;\n }\n else\n {\n this._frequency = 1;\n }\n }\n /**\n * The constructor used to create new particles. The default is\n * the built in Particle class. Setting this will dump any active or\n * pooled particles, if the emitter has already been used.\n */\n public get particleConstructor(): typeof Particle { return this._particleConstructor; }\n public set particleConstructor(value)\n {\n if (value !== this._particleConstructor)\n {\n this._particleConstructor = value;\n // clean up existing particles\n this.cleanup();\n // scrap all the particles\n for (let particle = this._poolFirst; particle; particle = particle.next)\n {\n particle.destroy();\n }\n this._poolFirst = null;\n // re-initialize the emitter so that the new constructor can do anything it needs to\n if (this._origConfig && this._origArt)\n {\n this.init(this._origArt, this._origConfig);\n }\n }\n }\n\n /**\n * The container to add particles to. Settings this will dump any active particles.\n */\n public get parent(): Container { return this._parent; }\n public set parent(value)\n {\n this.cleanup();\n this._parent = value;\n }\n\n /**\n * Sets up the emitter based on the config settings.\n * @param art A texture or array of textures to use for the particles.\n * @param config A configuration object containing settings for the emitter.\n */\n public init(art: any, config: EmitterConfig|OldEmitterConfig): void\n {\n if (!art || !config)\n {\n return;\n }\n // clean up any existing particles\n this.cleanup();\n\n // store the original config and particle images, in case we need to re-initialize\n // when the particle constructor is changed\n this._origConfig = config;\n this._origArt = art;\n\n // set up the array of data, also ensuring that it is an array\n art = Array.isArray(art) ? art.slice() : [art];\n // run the art through the particle class's parsing function\n const partClass = this._particleConstructor;\n\n this.particleImages = partClass.parseArt ? partClass.parseArt(art) : art;\n // /////////////////////////\n // Particle Properties //\n // /////////////////////////\n // set up the alpha\n if (config.alpha)\n {\n this.startAlpha = PropertyNode.createList(config.alpha);\n }\n else\n {\n this.startAlpha = new PropertyNode(1, 0);\n }\n // set up the speed\n if (config.speed)\n {\n this.startSpeed = PropertyNode.createList(config.speed);\n // eslint-disable-next-line max-len\n this.minimumSpeedMultiplier = ('minimumSpeedMultiplier' in config ? config.minimumSpeedMultiplier : (config.speed as any).minimumSpeedMultiplier) || 1;\n }\n else\n {\n this.minimumSpeedMultiplier = 1;\n this.startSpeed = new PropertyNode(0, 0);\n }\n // set up acceleration\n const acceleration = config.acceleration;\n\n if (acceleration && (acceleration.x || acceleration.y))\n {\n // make sure we disable speed interpolation\n this.startSpeed.next = null;\n this.acceleration = new Point(acceleration.x, acceleration.y);\n this.maxSpeed = config.maxSpeed || NaN;\n }\n else\n {\n this.acceleration = new Point();\n }\n // set up the scale\n if (config.scale)\n {\n this.startScale = PropertyNode.createList(config.scale);\n // eslint-disable-next-line max-len\n this.minimumScaleMultiplier = ('minimumScaleMultiplier' in config ? config.minimumScaleMultiplier : (config.scale as any).minimumScaleMultiplier) || 1;\n }\n else\n {\n this.startScale = new PropertyNode(1, 0);\n this.minimumScaleMultiplier = 1;\n }\n // set up the color\n if (config.color)\n {\n this.startColor = PropertyNode.createList(config.color);\n }\n else\n {\n this.startColor = new PropertyNode({ r: 0xFF, g: 0xFF, b: 0xFF }, 0);\n }\n // set up the start rotation\n if (config.startRotation)\n {\n this.minStartRotation = config.startRotation.min;\n this.maxStartRotation = config.startRotation.max;\n }\n else\n {\n this.minStartRotation = this.maxStartRotation = 0;\n }\n if (config.noRotation\n && (this.minStartRotation || this.maxStartRotation))\n {\n this.noRotation = !!config.noRotation;\n }\n else\n {\n this.noRotation = false;\n }\n // set up the rotation speed\n if (config.rotationSpeed)\n {\n this.minRotationSpeed = config.rotationSpeed.min;\n this.maxRotationSpeed = config.rotationSpeed.max;\n }\n else\n {\n this.minRotationSpeed = this.maxRotationSpeed = 0;\n }\n\n this.rotationAcceleration = config.rotationAcceleration || 0;\n // set up the lifetime\n this.minLifetime = config.lifetime.min;\n this.maxLifetime = config.lifetime.max;\n // get the blend mode\n this.particleBlendMode = ParticleUtils.getBlendMode(config.blendMode);\n // use the custom ease if provided\n if (config.ease)\n {\n this.customEase = typeof config.ease === 'function'\n ? config.ease : ParticleUtils.generateEase(config.ease);\n }\n else\n {\n this.customEase = null;\n }\n // set up the extra data, running it through the particle class's parseData function.\n if (partClass.parseData)\n {\n this.extraData = partClass.parseData(config.extraData);\n }\n else\n {\n this.extraData = config.extraData || null;\n }\n // ////////////////////////\n // Emitter Properties //\n // ////////////////////////\n // reset spawn type specific settings\n this.spawnRect = this.spawnCircle = null;\n this.particlesPerWave = 1;\n if (config.particlesPerWave && config.particlesPerWave > 1)\n {\n this.particlesPerWave = config.particlesPerWave;\n }\n this.particleSpacing = 0;\n this.angleStart = 0;\n // determine the spawn function to use\n this.parseSpawnType(config);\n // set the spawning frequency\n this.frequency = config.frequency;\n this.spawnChance = (typeof config.spawnChance === 'number' && config.spawnChance > 0) ? config.spawnChance : 1;\n // set the emitter lifetime\n this.emitterLifetime = config.emitterLifetime || -1;\n // set the max particles\n this.maxParticles = config.maxParticles > 0 ? config.maxParticles : 1000;\n // determine if we should add the particle at the back of the list or not\n this.addAtBack = !!config.addAtBack;\n // reset the emitter position and rotation variables\n this.rotation = 0;\n this.ownerPos = new Point();\n this.spawnPos = new Point(config.pos.x, config.pos.y);\n\n this.initAdditional(art, config);\n\n this._prevEmitterPos = this.spawnPos.clone();\n // previous emitter position is invalid and should not be used for interpolation\n this._prevPosIsValid = false;\n // start emitting\n this._spawnTimer = 0;\n this.emit = config.emit === undefined ? true : !!config.emit;\n this.autoUpdate = !!config.autoUpdate;\n this.orderedArt = !!config.orderedArt;\n }\n\n /**\n * Sets up additional parameters to the emitter from config settings.\n * Using for parsing additional parameters on classes that extend from Emitter\n * @param art A texture or array of textures to use for the particles.\n * @param config A configuration object containing settings for the emitter.\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected initAdditional(art: any, config: EmitterConfig|OldEmitterConfig): void\n {\n // override in subclasses\n }\n\n /**\n * Parsing emitter spawn type from config settings.\n * Place for override and add new kind of spawn type\n * @param config A configuration object containing settings for the emitter.\n */\n protected parseSpawnType(config: EmitterConfig|OldEmitterConfig): void\n {\n let spawnCircle;\n\n switch (config.spawnType)\n {\n case 'rect':\n this.spawnType = 'rect';\n this._spawnFunc = this._spawnRect;\n const spawnRect = config.spawnRect;\n\n this.spawnRect = new Rectangle(spawnRect.x, spawnRect.y, spawnRect.w, spawnRect.h);\n break;\n case 'circle':\n this.spawnType = 'circle';\n this._spawnFunc = this._spawnCircle;\n spawnCircle = config.spawnCircle;\n this.spawnCircle = new Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r) as any;\n break;\n case 'ring':\n this.spawnType = 'ring';\n this._spawnFunc = this._spawnRing;\n spawnCircle = config.spawnCircle;\n this.spawnCircle = new Circle(spawnCircle.x, spawnCircle.y, spawnCircle.r) as any;\n this.spawnCircle.minRadius = spawnCircle.minR;\n break;\n case 'burst':\n this.spawnType = 'burst';\n this._spawnFunc = this._spawnBurst;\n this.particleSpacing = config.particleSpacing;\n this.angleStart = config.angleStart ? config.angleStart : 0;\n break;\n case 'point':\n this.spawnType = 'point';\n this._spawnFunc = this._spawnPoint;\n break;\n case 'polygonalChain':\n this.spawnType = 'polygonalChain';\n this._spawnFunc = this._spawnPolygonalChain;\n this.spawnPolygonalChain = new PolygonalChain(config.spawnPolygon);\n break;\n default:\n this.spawnType = 'point';\n this._spawnFunc = this._spawnPoint;\n break;\n }\n }\n\n /**\n * Recycles an individual particle. For internal use only.\n * @param particle The particle to recycle.\n * @internal\n */\n public recycle(particle: Particle): void\n {\n if (particle.next)\n {\n particle.next.prev = particle.prev;\n }\n if (particle.prev)\n {\n particle.prev.next = particle.next;\n }\n if (particle === this._activeParticlesLast)\n {\n this._activeParticlesLast = particle.prev;\n }\n if (particle === this._activeParticlesFirst)\n {\n this._activeParticlesFirst = particle.next;\n }\n // add to pool\n particle.prev = null;\n particle.next = this._poolFirst;\n this._poolFirst = particle;\n // remove child from display, or make it invisible if it is in a ParticleContainer\n if (particle.parent)\n {\n particle.parent.removeChild(particle);\n }\n // decrease count\n --this.particleCount;\n }\n\n /**\n * Sets the rotation of the emitter to a new value.\n * @param newRot The new rotation, in degrees.\n */\n public rotate(newRot: number): void\n {\n if (this.rotation === newRot) return;\n // caclulate the difference in rotation for rotating spawnPos\n const diff = newRot - this.rotation;\n\n this.rotation = newRot;\n // rotate spawnPos\n ParticleUtils.rotatePoint(diff, this.spawnPos);\n // mark the position as having changed\n this._posChanged = true;\n }\n\n /**\n * Changes the spawn position of the emitter.\n * @param x The new x value of the spawn position for the emitter.\n * @param y The new y value of the spawn position for the emitter.\n */\n public updateSpawnPos(x: number, y: number): void\n {\n this._posChanged = true;\n this.spawnPos.x = x;\n this.spawnPos.y = y;\n }\n\n /**\n * Changes the position of the emitter's owner. You should call this if you are adding\n * particles to the world container that your emitter's owner is moving around in.\n * @param x The new x value of the emitter's owner.\n * @param y The new y value of the emitter's owner.\n */\n public updateOwnerPos(x: number, y: number): void\n {\n this._posChanged = true;\n this.ownerPos.x = x;\n this.ownerPos.y = y;\n }\n\n /**\n * Prevents emitter position interpolation in the next update.\n * This should be used if you made a major position change of your emitter's owner\n * that was not normal movement.\n */\n public resetPositionTracking(): void\n {\n this._prevPosIsValid = false;\n }\n\n /**\n * If particles should be emitted during update() calls. Setting this to false\n * stops new particles from being created, but allows existing ones to die out.\n */\n public get emit(): boolean { return this._emit; }\n public set emit(value)\n {\n this._emit = !!value;\n this._emitterLife = this.emitterLifetime;\n }\n\n /**\n * If the update function is called automatically from the shared ticker.\n * Setting this to false requires calling the update function manually.\n */\n public get autoUpdate(): boolean { return this._autoUpdate; }\n public set autoUpdate(value)\n {\n if (this._autoUpdate && !value)\n {\n ticker.remove(this.update, this);\n }\n else if (!this._autoUpdate && value)\n {\n ticker.add(this.update, this);\n }\n this._autoUpdate = !!value;\n }\n\n /**\n * Starts emitting particles, sets autoUpdate to true, and sets up the Emitter to destroy itself\n * when particle emission is complete.\n * @param callback Callback for when emission is complete (all particles have died off)\n */\n public playOnceAndDestroy(callback?: () => void): void\n {\n this.autoUpdate = true;\n this.emit = true;\n this._destroyWhenComplete = true;\n this._completeCallback = callback;\n }\n\n /**\n * Starts emitting particles and optionally calls a callback when particle emission is complete.\n * @param callback Callback for when emission is complete (all particles have died off)\n */\n public playOnce(callback?: () => void): void\n {\n this.emit = true;\n this._completeCallback = callback;\n }\n\n /**\n * Updates all particles spawned by this emitter and emits new ones.\n * @param delta Time elapsed since the previous frame, in __seconds__.\n */\n public update(delta: number): void\n {\n if (this._autoUpdate)\n {\n delta = delta / settings.TARGET_FPMS / 1000;\n }\n\n // if we don't have a parent to add particles to, then don't do anything.\n // this also works as a isDestroyed check\n if (!this._parent) return;\n // update existing particles\n let i;\n let particle;\n let next;\n\n for (particle = this._activeParticlesFirst; particle; particle = next)\n {\n next = particle.next;\n particle.update(delta);\n }\n let prevX;\n let prevY;\n // if the previous position is valid, store these for later interpolation\n\n if (this._prevPosIsValid)\n {\n prevX = this._prevEmitterPos.x;\n prevY = this._prevEmitterPos.y;\n }\n // store current position of the emitter as local variables\n const curX = this.ownerPos.x + this.spawnPos.x;\n const curY = this.ownerPos.y + this.spawnPos.y;\n // spawn new particles\n\n if (this._emit)\n {\n // decrease spawn timer\n this._spawnTimer -= delta < 0 ? 0 : delta;\n // while _spawnTimer < 0, we have particles to spawn\n while (this._spawnTimer <= 0)\n {\n // determine if the emitter should stop spawning\n if (this._emitterLife >= 0)\n {\n this._emitterLife -= this._frequency;\n if (this._emitterLife <= 0)\n {\n this._spawnTimer = 0;\n this._emitterLife = 0;\n this.emit = false;\n break;\n }\n }\n // determine if we have hit the particle limit\n if (this.particleCount >= this.maxParticles)\n {\n this._spawnTimer += this._frequency;\n continue;\n }\n // determine the particle lifetime\n let lifetime;\n\n if (this.minLifetime === this.maxLifetime)\n {\n lifetime = this.minLifetime;\n }\n else\n {\n lifetime = (Math.random() * (this.maxLifetime - this.minLifetime)) + this.minLifetime;\n }\n // only make the particle if it wouldn't immediately destroy itself\n if (-this._spawnTimer < lifetime)\n {\n // If the position has changed and this isn't the first spawn,\n // interpolate the spawn position\n let emitPosX; let\n emitPosY;\n\n if (this._prevPosIsValid && this._posChanged)\n {\n // 1 - _spawnTimer / delta, but _spawnTimer is negative\n const lerp = 1 + (this._spawnTimer / delta);\n\n emitPosX = ((curX - prevX) * lerp) + prevX;\n emitPosY = ((curY - prevY) * lerp) + prevY;\n }\n else// otherwise just set to the spawn position\n {\n emitPosX = curX;\n emitPosY = curY;\n }\n // create enough particles to fill the wave (non-burst types have a wave of 1)\n i = 0;\n for (let len = Math.min(this.particlesPerWave, this.maxParticles - this.particleCount); i < len; ++i)\n {\n // see if we actually spawn one\n if (this.spawnChance < 1 && Math.random() >= this.spawnChance)\n {\n continue;\n }\n // create particle\n let p;\n\n if (this._poolFirst)\n {\n p = this._poolFirst;\n this._poolFirst = this._poolFirst.next;\n p.next = null;\n }\n else\n {\n p = new this.particleConstructor(this);\n }\n\n // set a random texture if we have more than one\n if (this.particleImages.length > 1)\n {\n // if using ordered art\n if (this._currentImageIndex !== -1)\n {\n // get current art index, then increment for the next particle\n p.applyArt(this.particleImages[this._currentImageIndex++]);\n // loop around if needed\n if (this._currentImageIndex < 0 || this._currentImageIndex >= this.particleImages.length)\n {\n this._currentImageIndex = 0;\n }\n }\n // otherwise grab a random one\n else\n {\n p.applyArt(this.particleImages[Math.floor(Math.random() * this.particleImages.length)]);\n }\n }\n else\n {\n // if they are actually the same texture, a standard particle\n // will quit early from the texture setting in setTexture().\n p.applyArt(this.particleImages[0]);\n }\n // set up the start and end values\n p.alphaList.reset(this.startAlpha);\n if (this.minimumSpeedMultiplier !== 1)\n {\n // eslint-disable-next-line max-len\n p.speedMultiplier = (Math.random() * (1 - this.minimumSpeedMultiplier)) + this.minimumSpeedMultiplier;\n }\n p.speedList.reset(this.startSpeed);\n p.acceleration.x = this.acceleration.x;\n p.acceleration.y = this.acceleration.y;\n p.maxSpeed = this.maxSpeed;\n if (this.minimumScaleMultiplier !== 1)\n {\n // eslint-disable-next-line max-len\n p.scaleMultiplier = (Math.random() * (1 - this.minimumScaleMultiplier)) + this.minimumScaleMultiplier;\n }\n p.scaleList.reset(this.startScale);\n p.colorList.reset(this.startColor);\n // randomize the rotation speed\n if (this.minRotationSpeed === this.maxRotationSpeed)\n {\n p.rotationSpeed = this.minRotationSpeed;\n }\n else\n {\n // eslint-disable-next-line max-len\n p.rotationSpeed = (Math.random() * (this.maxRotationSpeed - this.minRotationSpeed)) + this.minRotationSpeed;\n }\n p.rotationAcceleration = this.rotationAcceleration;\n p.noRotation = this.noRotation;\n // set up the lifetime\n p.maxLife = lifetime;\n // set the blend mode\n p.blendMode = this.particleBlendMode;\n // set the custom ease, if any\n p.ease = this.customEase;\n // set the extra data, if any\n p.extraData = this.extraData;\n // set additional properties to particle\n this.applyAdditionalProperties(p);\n // call the proper function to handle rotation and position of particle\n this._spawnFunc(p, emitPosX, emitPosY, i);\n // initialize particle\n p.init();\n // add the particle to the display list\n if (!p.parent)\n {\n if (this.addAtBack)\n {\n this._parent.addChildAt(p, 0);\n }\n else\n {\n this._parent.addChild(p);\n }\n }\n else\n {\n // kind of hacky, but performance friendly\n // shuffle children to correct place\n const children = this._parent.children;\n // avoid using splice if possible\n\n if (children[0] === p)\n {\n children.shift();\n }\n else if (children[children.length - 1] === p)\n {\n children.pop();\n }\n else\n {\n const index = children.indexOf(p);\n\n children.splice(index, 1);\n }\n if (this.addAtBack)\n {\n children.unshift(p);\n }\n else\n {\n children.push(p);\n }\n }\n // add particle to list of active particles\n if (this._activeParticlesLast)\n {\n this._activeParticlesLast.next = p;\n p.prev = this._activeParticlesLast;\n this._activeParticlesLast = p;\n }\n else\n {\n this._activeParticlesLast = this._activeParticlesFirst = p;\n }\n ++this.particleCount;\n // update the particle by the time passed, so the particles are spread out properly\n p.update(-this._spawnTimer);// we want a positive delta, because a negative delta messes things up\n }\n }\n // increase timer and continue on to any other particles that need to be created\n this._spawnTimer += this._frequency;\n }\n }\n // if the position changed before this update, then keep track of that\n if (this._posChanged)\n {\n this._prevEmitterPos.x = curX;\n this._prevEmitterPos.y = curY;\n this._prevPosIsValid = true;\n this._posChanged = false;\n }\n\n // if we are all done and should destroy ourselves, take care of that\n if (!this._emit && !this._activeParticlesFirst)\n {\n if (this._completeCallback)\n {\n const cb = this._completeCallback;\n\n this._completeCallback = null;\n cb();\n }\n if (this._destroyWhenComplete)\n {\n this.destroy();\n }\n }\n }\n\n /**\n * Set additional properties to new particle.\n * Using on classes that extend from Emitter\n * @param p The particle\n */\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected applyAdditionalProperties(p: Particle): void\n {\n // for override in subclass\n }\n\n /**\n * Positions a particle for a point type emitter.\n * @param p The particle to position and rotate.\n * @param emitPosX The emitter's x position\n * @param emitPosY The emitter's y position\n * @param i The particle number in the current wave. Not used for this function.\n */\n protected _spawnPoint(p: Particle, emitPosX: number, emitPosY: number): void\n {\n // set the initial rotation/direction of the particle based on\n // starting particle angle and rotation of emitter\n if (this.minStartRotation === this.maxStartRotation)\n {\n p.rotation = this.minStartRotation + this.rotation;\n }\n else\n {\n // eslint-disable-next-line max-len\n p.rotation = (Math.random() * (this.maxStartRotation - this.minStartRotation)) + this.minStartRotation + this.rotation;\n }\n // drop the particle at the emitter's position\n p.position.x = emitPosX;\n p.position.y = emitPosY;\n }\n\n /**\n * Positions a particle for a rectangle type emitter.\n * @param p The particle to position and rotate.\n * @param emitPosX The emitter's x position\n * @param emitPosY The emitter's y position\n * @param i The particle number in the current wave. Not used for this function.\n */\n protected _spawnRect(p: Particle, emitPosX: number, emitPosY: number): void\n {\n // set the initial rotation/direction of the particle based on starting\n // particle angle and rotation of emitter\n if (this.minStartRotation === this.maxStartRotation)\n {\n p.rotation = this.minStartRotation + this.rotation;\n }\n else\n {\n // eslint-disable-next-line max-len\n p.rotation = (Math.random() * (this.maxStartRotation - this.minStartRotation)) + this.minStartRotation + this.rotation;\n }\n // place the particle at a random point in the rectangle\n helperPoint.x = (Math.random() * this.spawnRect.width) + this.spawnRect.x;\n helperPoint.y = (Math.random() * this.spawnRect.height) + this.spawnRect.y;\n if (this.rotation !== 0)\n {\n ParticleUtils.rotatePoint(this.rotation, helperPoint);\n }\n p.position.x = emitPosX + helperPoint.x;\n p.position.y = emitPosY + helperPoint.y;\n }\n\n /**\n * Positions a particle for a circle type emitter.\n * @param p The particle to position and rotate.\n * @param emitPosX The emitter's x position\n * @param emitPosY The emitter's y position\n * @param i The particle number in the current wave. Not used for this function.\n */\n protected _spawnCircle(p: Particle, emitPosX: number, emitPosY: number): void\n {\n // set the initial rotation/direction of the particle based on starting\n // particle angle and rotation of emitter\n if (this.minStartRotation === this.maxStartRotation)\n {\n p.rotation = this.minStartRotation + this.rotation;\n }\n else\n {\n // eslint-disable-next-line max-len\n p.rotation = (Math.random() * (this.maxStartRotation - this.minStartRotation)) + this.minStartRotation + this.rotation;\n }\n // place the particle at a random radius in the circle\n helperPoint.x = Math.random() * this.spawnCircle.radius;\n helperPoint.y = 0;\n // rotate the point to a random angle in the circle\n ParticleUtils.rotatePoint(Math.random() * 360, helperPoint);\n // offset by the circle's center\n helperPoint.x += this.spawnCircle.x;\n helperPoint.y += this.spawnCircle.y;\n // rotate the point by the emitter's rotation\n if (this.rotation !== 0)\n {\n ParticleUtils.rotatePoint(this.rotation, helperPoint);\n }\n // set the position, offset by the emitter's position\n p.position.x = emitPosX + helperPoint.x;\n p.position.y = emitPosY + helperPoint.y;\n }\n\n /**\n * Positions a particle for a ring type emitter.\n * @param p The particle to position and rotate.\n * @param emitPosX The emitter's x position\n * @param emitPosY The emitter's y position\n * @param i The particle number in the current wave. Not used for this function.\n */\n protected _spawnRing(p: Particle, emitPosX: number, emitPosY: number): void\n {\n const spawnCircle = this.spawnCircle;\n // set the initial rotation/direction of the particle based on starting\n // particle angle and rotation of emitter\n\n if (this.minStartRotation === this.maxStartRotation)\n {\n p.rotation = this.minStartRotation + this.rotation;\n }\n else\n {\n p.rotation = (Math.random() * (this.maxStartRotation - this.minStartRotation))\n + this.minStartRotation + this.rotation;\n }\n // place the particle at a random radius in the ring\n if (spawnCircle.minRadius !== spawnCircle.radius)\n {\n helperPoint.x = (Math.random() * (spawnCircle.radius - spawnCircle.minRadius))\n + spawnCircle.minRadius;\n }\n else\n {\n helperPoint.x = spawnCircle.radius;\n }\n helperPoint.y = 0;\n // rotate the point to a random angle in the circle\n const angle = Math.random() * 360;\n\n p.rotation += angle;\n ParticleUtils.rotatePoint(angle, helperPoint);\n // offset by the circle's center\n helperPoint.x += this.spawnCircle.x;\n helperPoint.y += this.spawnCircle.y;\n // rotate the point by the emitter's rotation\n if (this.rotation !== 0)\n {\n ParticleUtils.rotatePoint(this.rotation, helperPoint);\n }\n // set the position, offset by the emitter's position\n p.position.x = emitPosX + helperPoint.x;\n p.position.y = emitPosY + helperPoint.y;\n }\n\n /**\n * Positions a particle for polygonal chain.\n * @param p The particle to position and rotate.\n * @param emitPosX The emitter's x position\n * @param emitPosY The emitter's y position\n * @param i The particle number in the current wave. Not used for this function.\n */\n protected _spawnPolygonalChain(p: Particle, emitPosX: number, emitPosY: number): void\n {\n // set the initial rotation/direction of the particle based on starting\n // particle angle and rotation of emitter\n if (this.minStartRotation === this.maxStartRotation)\n {\n p.rotation = this.minStartRotation + this.rotation;\n }\n else\n {\n p.rotation = (Math.random() * (this.maxStartRotation - this.minStartRotation))\n + this.minStartRotation + this.rotation;\n }\n // get random point on the polygon chain\n this.spawnPolygonalChain.getRandomPoint(helperPoint);\n // rotate the point by the emitter's rotation\n if (this.rotation !== 0)\n {\n ParticleUtils.rotatePoint(this.rotation, helperPoint);\n }\n // set the position, offset by the emitter's position\n p.position.x = emitPosX + helperPoint.x;\n p.position.y = emitPosY + helperPoint.y;\n }\n\n /**\n * Positions a particle for a burst type emitter.\n * @param p The particle to position and rotate.\n * @param emitPosX The emitter's x position\n * @param emitPosY The emitter's y position\n * @param i The particle number in the current wave.\n */\n protected _spawnBurst(p: Particle, emitPosX: number, emitPosY: number, i: number): void\n {\n // set the initial rotation/direction of the particle based on spawn\n // angle and rotation of emitter\n if (this.particleSpacing === 0)\n {\n p.rotation = Math.random() * 360;\n }\n else\n {\n p.rotation = this.angleStart + (this.particleSpacing * i) + this.rotation;\n }\n // drop the particle at the emitter's position\n p.position.x = emitPosX;\n p.position.y = emitPosY;\n }\n\n /**\n * Kills all active particles immediately.\n */\n public cleanup(): void\n {\n let particle;\n let next;\n\n for (particle = this._activeParticlesFirst; particle; particle = next)\n {\n next = particle.next;\n this.recycle(particle);\n if (particle.parent)\n {\n particle.parent.removeChild(particle);\n }\n }\n this._activeParticlesFirst = this._activeParticlesLast = null;\n this.particleCount = 0;\n }\n\n /**\n * Destroys the emitter and all of its particles.\n */\n public destroy(): void\n {\n // make sure we aren't still listening to any tickers\n this.autoUpdate = false;\n // puts all active particles in the pool, and removes them from the particle parent\n this.cleanup();\n // wipe the pool clean\n let next;\n\n for (let particle = this._poolFirst; particle; particle = next)\n {\n // store next value so we don't lose it in our destroy call\n next = particle.next;\n particle.destroy();\n }\n this._poolFirst = this._parent = this.particleImages = this.spawnPos = this.ownerPos\n = this.startColor = this.startScale = this.startAlpha = this.startSpeed\n = this.customEase = this._completeCallback = null;\n }\n}\n","import { Emitter } from './Emitter';\nimport { ParticleUtils, SimpleEase, Color, GetTextureFromString } from './ParticleUtils';\nimport { PropertyList } from './PropertyList';\nimport { Sprite, Point, Texture } from 'pixi.js';\n\n/**\n * An individual particle image. You shouldn't have to deal with these.\n */\nexport class Particle extends Sprite\n{\n /**\n * The emitter that controls this particle.\n */\n public emitter: Emitter;\n /**\n * The velocity of the particle. Speed may change, but the angle also\n * contained in velocity is constant.\n */\n public velocity: Point;\n /**\n * The maximum lifetime of this particle, in seconds.\n */\n public maxLife: number;\n /**\n * The current age of the particle, in seconds.\n */\n public age: number;\n /**\n * A simple easing function to be applied to all properties that\n * are being interpolated.\n */\n public ease: SimpleEase;\n /**\n * Extra data that the emitter passes along for custom particles.\n */\n public extraData: any;\n /**\n * The alpha of the particle throughout its life.\n */\n public alphaList: PropertyList;\n /**\n * The speed of the particle throughout its life.\n */\n public speedList: PropertyList;\n /**\n * A multiplier from 0-1 applied to the speed of the particle at all times.\n */\n public speedMultiplier: number;\n /**\n * Acceleration to apply to the particle.\n */\n public acceleration: Point;\n /**\n * The maximum speed allowed for accelerating particles. Negative values, values of 0 or NaN\n * will disable the maximum speed.\n */\n public maxSpeed: number;\n /**\n * Speed at which the particle rotates, in radians per second.\n */\n public rotationSpeed: number;\n\n /**\n * Acceleration of rotation (angular acceleration) to apply to the particle.\n */\n public rotationAcceleration: number;\n\n /**\n * If particle rotation is locked, preventing rotation from occurring due\n * to directional changes.\n */\n public noRotation: boolean;\n /**\n * The scale of the particle throughout its life.\n */\n public scaleList: PropertyList;\n /**\n * A multiplier from 0-1 applied to the scale of the particle at all times.\n */\n public scaleMultiplier: number;\n /**\n * The tint of the particle throughout its life.\n */\n public colorList: PropertyList;\n /**\n * A reference to init, so that subclasses can access it without the penalty of Function.call()\n */\n protected Particle_init: typeof Particle.prototype.init;\n /**\n * A reference to update so that subclasses can access the original without the overhead\n * of Function.call().\n * @param delta Time elapsed since the previous frame, in __seconds__.\n * @return The standard interpolation multiplier (0-1) used for all relevant particle\n * properties. A value of -1 means the particle died of old age instead.\n */\n protected Particle_update: typeof Particle.prototype.update;\n protected Particle_destroy: typeof Particle.prototype.destroy;\n protected Sprite_destroy: typeof Sprite.prototype.destroy;\n /**\n * If alpha should be interpolated at all.\n */\n protected _doAlpha: boolean;\n /**\n * If scale should be interpolated at all.\n */\n protected _doScale: boolean;\n /**\n * If speed should be interpolated at all.\n */\n protected _doSpeed: boolean;\n /**\n * If acceleration should be handled at all. _doSpeed is mutually exclusive with this,\n * and _doSpeed gets priority.\n */\n protected _doAcceleration: boolean;\n /**\n * If color should be interpolated at all.\n */\n protected _doColor: boolean;\n /**\n * If normal movement should be handled. Subclasses wishing to override movement\n * can set this to false in init().\n */\n protected _doNormalMovement: boolean;\n /**\n * One divided by the max life of the particle, saved for slightly faster math.\n */\n private _oneOverLife: number;\n /**\n * Reference to the next particle in the list.\n */\n public next: Particle;\n\n /**\n * Reference to the previous particle in the list.\n */\n public prev: Particle;\n\n /**\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this particle.\n */\n constructor(emitter: Emitter)\n {\n // start off the sprite with a blank texture, since we are going to replace it\n // later when the particle is initialized.\n super();\n this.emitter = emitter;\n // particles should be centered\n this.anchor.x = this.anchor.y = 0.5;\n this.velocity = new Point();\n this.rotationSpeed = 0;\n this.rotationAcceleration = 0;\n this.maxLife = 0;\n this.age = 0;\n this.ease = null;\n this.extraData = null;\n this.alphaList = new PropertyList();\n this.speedList = new PropertyList();\n this.speedMultiplier = 1;\n this.acceleration = new Point();\n this.maxSpeed = NaN;\n this.scaleList = new PropertyList();\n this.scaleMultiplier = 1;\n this.colorList = new PropertyList(true);\n this._doAlpha = false;\n this._doScale = false;\n this._doSpeed = false;\n this._doAcceleration = false;\n this._doColor = false;\n this._doNormalMovement = false;\n this._oneOverLife = 0;\n this.next = null;\n this.prev = null;\n\n // save often used functions on the instance instead of the prototype for better speed\n this.init = this.init;\n this.Particle_init = Particle.prototype.init;\n this.update = this.update;\n this.Particle_update = Particle.prototype.update;\n this.Sprite_destroy = super.destroy;\n this.Particle_destroy = Particle.prototype.destroy;\n this.applyArt = this.applyArt;\n this.kill = this.kill;\n }\n\n /**\n * Initializes the particle for use, based on the properties that have to\n * have been set already on the particle.\n */\n public init(): void\n {\n // reset the age\n this.age = 0;\n // set up the velocity based on the start speed and rotation\n this.velocity.x = this.speedList.current.value * this.speedMultiplier;\n this.velocity.y = 0;\n ParticleUtils.rotatePoint(this.rotation, this.velocity);\n if (this.noRotation)\n {\n this.rotation = 0;\n }\n else\n {\n // convert rotation to Radians from Degrees\n this.rotation *= ParticleUtils.DEG_TO_RADS;\n }\n // convert rotation speed to Radians from Degrees\n this.rotationSpeed *= ParticleUtils.DEG_TO_RADS;\n this.rotationAcceleration *= ParticleUtils.DEG_TO_RADS;\n\n // set alpha to inital alpha\n this.alpha = this.alphaList.current.value;\n // set scale to initial scale\n this.scale.x = this.scale.y = this.scaleList.current.value;\n // figure out what we need to interpolate\n this._doAlpha = !!this.alphaList.current.next;\n this._doSpeed = !!this.speedList.current.next;\n this._doScale = !!this.scaleList.current.next;\n this._doColor = !!this.colorList.current.next;\n this._doAcceleration = this.acceleration.x !== 0 || this.acceleration.y !== 0;\n // _doNormalMovement can be cancelled by subclasses\n this._doNormalMovement = this._doSpeed || this.speedList.current.value !== 0 || this._doAcceleration;\n // save our lerp helper\n this._oneOverLife = 1 / this.maxLife;\n // set the inital color\n const color = this.colorList.current.value;\n\n this.tint = ParticleUtils.combineRGBComponents(color.r, color.g, color.b);\n // ensure visibility\n this.visible = true;\n }\n\n /**\n * Sets the texture for the particle. This can be overridden to allow\n * for an animated particle.\n * @param art The texture to set.\n */\n public applyArt(art: any): void\n {\n this.texture = art || Texture.EMPTY;\n }\n\n /**\n * Updates the particle.\n * @param delta Time elapsed since the previous frame, in __seconds__.\n * @return The standard interpolation multiplier (0-1) used for all\n * relevant particle properties. A value of -1 means the particle\n * died of old age instead.\n */\n public update(delta: number): number\n {\n // increase age\n this.age += delta;\n // recycle particle if it is too old\n if (this.age >= this.maxLife || this.age < 0)\n {\n this.kill();\n\n return -1;\n }\n\n // determine our interpolation value\n let lerp = this.age * this._oneOverLife;// lifetime / maxLife;\n\n if (this.ease)\n {\n if (this.ease.length === 4)\n {\n // the t, b, c, d parameters that some tween libraries use\n // (time, initial value, end value, duration)\n lerp = (this.ease as any)(lerp, 0, 1, 1);\n }\n else\n {\n // the simplified version that we like that takes\n // one parameter, time from 0-1. TweenJS eases provide this usage.\n lerp = this.ease(lerp);\n }\n }\n\n // interpolate alpha\n if (this._doAlpha)\n {\n this.alpha = this.alphaList.interpolate(lerp);\n }\n // interpolate scale\n if (this._doScale)\n {\n const scale = this.scaleList.interpolate(lerp) * this.scaleMultiplier;\n\n this.scale.x = this.scale.y = scale;\n }\n // handle movement\n if (this._doNormalMovement)\n {\n let deltaX: number;\n let deltaY: number;\n // interpolate speed\n\n if (this._doSpeed)\n {\n const speed = this.speedList.interpolate(lerp) * this.speedMultiplier;\n\n ParticleUtils.normalize(this.velocity);\n ParticleUtils.scaleBy(this.velocity, speed);\n deltaX = this.velocity.x * delta;\n deltaY = this.velocity.y * delta;\n }\n else if (this._doAcceleration)\n {\n const oldVX = this.velocity.x;\n const oldVY = this.velocity.y;\n\n this.velocity.x += this.acceleration.x * delta;\n this.velocity.y += this.acceleration.y * delta;\n if (this.maxSpeed)\n {\n const currentSpeed = ParticleUtils.length(this.velocity);\n // if we are going faster than we should, clamp at the max speed\n // DO NOT recalculate vector length\n\n if (currentSpeed > this.maxSpeed)\n {\n ParticleUtils.scaleBy(this.velocity, this.maxSpeed / currentSpeed);\n }\n }\n // calculate position delta by the midpoint between our old velocity and our new velocity\n deltaX = (oldVX + this.velocity.x) / 2 * delta;\n deltaY = (oldVY + this.velocity.y) / 2 * delta;\n }\n else\n {\n deltaX = this.velocity.x * delta;\n deltaY = this.velocity.y * delta;\n }\n // adjust position based on velocity\n this.position.x += deltaX;\n this.position.y += deltaY;\n }\n // interpolate color\n if (this._doColor)\n {\n this.tint = this.colorList.interpolate(lerp);\n }\n // update rotation\n if (this.rotationAcceleration !== 0)\n {\n const newRotationSpeed = this.rotationSpeed + (this.rotationAcceleration * delta);\n\n this.rotation += (this.rotationSpeed + newRotationSpeed) / 2 * delta;\n this.rotationSpeed = newRotationSpeed;\n }\n else if (this.rotationSpeed !== 0)\n {\n this.rotation += this.rotationSpeed * delta;\n }\n else if (this.acceleration && !this.noRotation)\n {\n this.rotation = Math.atan2(this.velocity.y, this.velocity.x);// + Math.PI / 2;\n }\n\n return lerp;\n }\n\n /**\n * Kills the particle, removing it from the display list\n * and telling the emitter to recycle it.\n */\n public kill(): void\n {\n this.emitter.recycle(this);\n }\n\n /**\n * Destroys the particle, removing references and preventing future use.\n */\n public destroy(): void\n {\n if (this.parent)\n {\n this.parent.removeChild(this);\n }\n this.Sprite_destroy();\n this.emitter = this.velocity = this.colorList = this.scaleList = this.alphaList\n = this.speedList = this.ease = this.next = this.prev = null;\n }\n\n /**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time.\n * @param art The array of art data. For Particle, it should be an array of\n * Textures. Any strings in the array will be converted to\n * Textures via Texture.from().\n * @return The art, after any needed modifications.\n */\n public static parseArt(art: any[]): any[]\n {\n // convert any strings to Textures.\n let i;\n\n for (i = art.length; i >= 0; --i)\n {\n if (typeof art[i] === 'string')\n {\n art[i] = GetTextureFromString(art[i]);\n }\n }\n // particles from different base textures will be slower in WebGL than if they\n // were from one spritesheet\n if (ParticleUtils.verbose)\n {\n for (i = art.length - 1; i > 0; --i)\n {\n if (art[i].baseTexture !== art[i - 1].baseTexture)\n {\n if (window.console)\n {\n // eslint-disable-next-line max-len\n console.warn('PixiParticles: using particle textures from different images may hinder performance in WebGL');\n }\n break;\n }\n }\n }\n\n return art;\n }\n\n /**\n * Parses extra emitter data to ensure it is set up for this particle class.\n * Particle does nothing to the extra data.\n * @param extraData The extra data from the particle config.\n * @return The parsed extra data.\n */\n public static parseData(extraData: any): any\n {\n return extraData;\n }\n}\n","import { Point } from 'pixi.js';\n\nexport interface BasicPoint\n{\n x: number;\n y: number;\n}\n\nexport interface Segment\n{\n p1: BasicPoint;\n p2: BasicPoint;\n l: number;\n}\n\n/**\n * Chain of line segments for generating spawn positions.\n */\nexport class PolygonalChain\n{\n /**\n * List of segment objects in the chain.\n */\n private segments: Segment[];\n /**\n * Total length of all segments of the chain.\n */\n private totalLength: number;\n /**\n * Total length of segments up to and including the segment of the same index.\n * Used for weighted random selection of segment.\n */\n private countingLengths: number[];\n\n /**\n * @param data Point data for polygon chains. Either a list of points for a single chain, or a list of chains.\n */\n constructor(data: BasicPoint[]|BasicPoint[][])\n {\n this.segments = [];\n this.countingLengths = [];\n this.totalLength = 0;\n this.init(data);\n }\n\n /**\n * @param data Point data for polygon chains. Either a list of points for a single chain, or a list of chains.\n */\n private init(data: BasicPoint[]|BasicPoint[][]): void\n {\n // if data is not present, set up a segment of length 0\n if (!data || !data.length)\n {\n this.segments.push({ p1: { x: 0, y: 0 }, p2: { x: 0, y: 0 }, l: 0 });\n }\n else if (Array.isArray(data[0]))\n {\n // list of segment chains, each defined as a list of points\n for (let i = 0; i < data.length; ++i)\n {\n // loop through the chain, connecting points\n const chain = data[i] as BasicPoint[];\n let prevPoint = chain[0] as BasicPoint;\n\n for (let j = 1; j < chain.length; ++j)\n {\n const second = chain[j] as BasicPoint;\n\n this.segments.push({ p1: prevPoint, p2: second, l: 0 });\n prevPoint = second;\n }\n }\n }\n else\n {\n let prevPoint = data[0] as BasicPoint;\n // list of points\n\n for (let i = 1; i < data.length; ++i)\n {\n const second = data[i] as BasicPoint;\n\n this.segments.push({ p1: prevPoint, p2: second, l: 0 });\n prevPoint = second;\n }\n }\n // now go through our segments to calculate the lengths so that we\n // can set up a nice weighted random distribution\n for (let i = 0; i < this.segments.length; ++i)\n {\n const { p1, p2 } = this.segments[i];\n const segLength = Math.sqrt(((p2.x - p1.x) * (p2.x - p1.x)) + ((p2.y - p1.y) * (p2.y - p1.y)));\n // save length so we can turn a random number into a 0-1 interpolation value later\n\n this.segments[i].l = segLength;\n this.totalLength += segLength;\n // keep track of the length so far, counting up\n this.countingLengths.push(this.totalLength);\n }\n }\n\n /**\n * Gets a random point in the chain.\n * @param out The point to store the selected position in.\n */\n public getRandomPoint(out: Point): void\n {\n // select a random spot in the length of the chain\n const rand = Math.random() * this.totalLength;\n let chosenSeg: Segment;\n let lerp: number;\n\n // if only one segment, it wins\n if (this.segments.length === 1)\n {\n chosenSeg = this.segments[0];\n lerp = rand;\n }\n else\n {\n // otherwise, go through countingLengths until we have determined\n // which segment we chose\n for (let i = 0; i < this.countingLengths.length; ++i)\n {\n if (rand < this.countingLengths[i])\n {\n chosenSeg = this.segments[i];\n // set lerp equal to the length into that segment\n // (i.e. the remainder after subtracting all the segments before it)\n lerp = i === 0 ? rand : rand - this.countingLengths[i - 1];\n break;\n }\n }\n }\n // divide lerp by the segment length, to result in a 0-1 number.\n lerp /= chosenSeg.l || 1;\n const { p1, p2 } = chosenSeg;\n // now calculate the position in the segment that the lerp value represents\n\n out.x = p1.x + (lerp * (p2.x - p1.x));\n out.y = p1.y + (lerp * (p2.y - p1.y));\n }\n}\n","import { ParticleUtils } from './ParticleUtils';\nimport { Particle } from './Particle';\nimport { Emitter } from './Emitter';\nimport { Point, Texture } from 'pixi.js';\n\n/**\n * A helper point for math things.\n * @hidden\n */\nconst helperPoint = new Point();\n\n/**\n * A hand picked list of Math functions (and a couple properties) that are\n * allowable. They should be used without the preceding \"Math.\"\n * @hidden\n */\nconst MATH_FUNCS = [\n 'pow',\n 'sqrt',\n 'abs',\n 'floor',\n 'round',\n 'ceil',\n 'E',\n 'PI',\n 'sin',\n 'cos',\n 'tan',\n 'asin',\n 'acos',\n 'atan',\n 'atan2',\n 'log',\n];\n/**\n * create an actual regular expression object from the string\n * @hidden\n */\nconst WHITELISTER = new RegExp(\n [\n // Allow the 4 basic operations, parentheses and all numbers/decimals, as well\n // as 'x', for the variable usage.\n '[01234567890\\\\.\\\\*\\\\-\\\\+\\\\/\\\\(\\\\)x ,]',\n ].concat(MATH_FUNCS).join('|'),\n 'g',\n);\n\n/**\n * Parses a string into a function for path following.\n * This involves whitelisting the string for safety, inserting \"Math.\" to math function\n * names, and using `new Function()` to generate a function.\n * @hidden\n * @param pathString The string to parse.\n * @return The path function - takes x, outputs y.\n */\nfunction parsePath(pathString: string): (x: number) => number\n{\n const matches = pathString.match(WHITELISTER);\n\n for (let i = matches.length - 1; i >= 0; --i)\n {\n if (MATH_FUNCS.indexOf(matches[i]) >= 0)\n { matches[i] = `Math.${matches[i]}`; }\n }\n pathString = matches.join('');\n\n // eslint-disable-next-line no-new-func\n return new Function('x', `return ${pathString};`) as (x: number) => number;\n}\n\n/**\n * An particle that follows a path defined by an algebraic expression, e.g. \"sin(x)\" or\n * \"5x + 3\".\n * To use this class, the particle config must have a \"path\" string in the\n * \"extraData\" parameter. This string should have \"x\" in it to represent movement (from the\n * speed settings of the particle). It may have numbers, parentheses, the four basic\n * operations, and the following Math functions or properties (without the preceding \"Math.\"):\n * \"pow\", \"sqrt\", \"abs\", \"floor\", \"round\", \"ceil\", \"E\", \"PI\", \"sin\", \"cos\", \"tan\", \"asin\",\n * \"acos\", \"atan\", \"atan2\", \"log\".\n * The overall movement of the particle and the expression value become x and y positions for\n * the particle, respectively. The final position is rotated by the spawn rotation/angle of\n * the particle.\n *\n * Some example paths:\n *\n * \t\"sin(x/10) * 20\" // A sine wave path.\n * \t\"cos(x/100) * 30\" // Particles curve counterclockwise (for medium speed/low lifetime particles)\n * \t\"pow(x/10, 2) / 2\" // Particles curve clockwise (remember, +y is down).\n */\nexport class PathParticle extends Particle\n{\n /**\n * The function representing the path the particle should take.\n */\n public path: Function;\n /**\n * The initial rotation in degrees of the particle, because the direction of the path\n * is based on that.\n */\n public initialRotation: number;\n /**\n * The initial position of the particle, as all path movement is added to that.\n */\n public initialPosition: Point;\n /**\n * Total single directional movement, due to speed.\n */\n public movement: number;\n\n /**\n * @param {PIXI.particles.Emitter} emitter The emitter that controls this PathParticle.\n */\n constructor(emitter: Emitter)\n {\n super(emitter);\n this.path = null;\n this.initialRotation = 0;\n this.initialPosition = new Point();\n this.movement = 0;\n }\n\n /**\n * Initializes the particle for use, based on the properties that have to\n * have been set already on the particle.\n */\n public init(): void\n {\n // get initial rotation before it is converted to radians\n this.initialRotation = this.rotation;\n // standard init\n this.Particle_init();\n\n // set the path for the particle\n this.path = this.extraData.path;\n // cancel the normal movement behavior\n this._doNormalMovement = !this.path;\n // reset movement\n this.movement = 0;\n // grab position\n this.initialPosition.x = this.position.x;\n this.initialPosition.y = this.position.y;\n }\n\n /**\n * Updates the particle.\n * @param delta Time elapsed since the previous frame, in __seconds__.\n */\n public update(delta: number): number\n {\n const lerp = this.Particle_update(delta);\n // if the particle died during the update, then don't bother\n\n if (lerp >= 0 && this.path)\n {\n // increase linear movement based on speed\n if (this._doSpeed)\n {\n const speed = this.speedList.interpolate(lerp) * this.speedMultiplier;\n\n this.movement += speed * delta;\n }\n else\n {\n const speed = this.speedList.current.value * this.speedMultiplier;\n\n this.movement += speed * delta;\n }\n // set up the helper point for rotation\n helperPoint.x = this.movement;\n helperPoint.y = this.path(this.movement);\n ParticleUtils.rotatePoint(this.initialRotation, helperPoint);\n this.position.x = this.initialPosition.x + helperPoint.x;\n this.position.y = this.initialPosition.y + helperPoint.y;\n }\n\n return lerp;\n }\n\n /**\n * Destroys the particle, removing references and preventing future use.\n */\n public destroy(): void\n {\n this.Particle_destroy();\n this.path = this.initialPosition = null;\n }\n\n /**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time. This just runs Particle.parseArt().\n * @param art The array of art data. For Particle, it should be an array of\n * Textures. Any strings in the array will be converted to\n * Textures via Texture.fromImage().\n * @return The art, after any needed modifications.\n */\n public static parseArt(art: (Texture|string)[]): Texture[]\n {\n return Particle.parseArt(art);\n }\n\n /**\n * Parses extra emitter data to ensure it is set up for this particle class.\n * PathParticle checks for the existence of path data, and parses the path data for use\n * by particle instances.\n * @param extraData The extra data from the particle config.\n * @return The parsed extra data.\n */\n public static parseData(extraData: {path: string}): any\n {\n const output: any = {};\n\n if (extraData && extraData.path)\n {\n try\n {\n output.path = parsePath(extraData.path);\n }\n catch (e)\n {\n if (ParticleUtils.verbose)\n {\n console.error('PathParticle: error in parsing path expression');\n }\n output.path = null;\n }\n }\n else\n {\n if (ParticleUtils.verbose)\n {\n console.error('PathParticle requires a path string in extraData!');\n }\n output.path = null;\n }\n\n return output;\n }\n}\n","import { Particle } from './Particle';\nimport { Emitter } from './Emitter';\nimport { GetTextureFromString } from './ParticleUtils';\nimport { Texture } from 'pixi.js';\n\nexport interface ParsedAnimatedParticleArt\n{\n textures: Texture[];\n duration: number;\n framerate: number;\n loop: boolean;\n}\n\nexport interface AnimatedParticleArt\n{\n framerate: 'matchLife'|number;\n loop?: boolean;\n textures: (string|Texture|{texture: string|Texture;count: number})[];\n}\n\n/**\n * An individual particle image with an animation. Art data passed to the emitter must be\n * formatted in a particular way for AnimatedParticle to be able to handle it:\n *\n * ```typescript\n * {\n * //framerate is required. It is the animation speed of the particle in frames per\n * //second.\n * //A value of \"matchLife\" causes the animation to match the lifetime of an individual\n * //particle, instead of at a constant framerate. This causes the animation to play\n * //through one time, completing when the particle expires.\n * framerate: 6,\n * //loop is optional, and defaults to false.\n * loop: true,\n * //textures is required, and can be an array of any (non-zero) length.\n * textures: [\n * //each entry represents a single texture that should be used for one or more\n * //frames. Any strings will be converted to Textures with Texture.from().\n * //Instances of PIXI.Texture will be used directly.\n * \"animFrame1.png\",\n * //entries can be an object with a 'count' property, telling AnimatedParticle to\n * //use that texture for 'count' frames sequentially.\n * {\n * texture: \"animFrame2.png\",\n * count: 3\n * },\n * \"animFrame3.png\"\n * ]\n * }\n * ```\n */\nexport class AnimatedParticle extends Particle\n{\n /**\n * Texture array used as each frame of animation, similarly to how MovieClip works.\n */\n private textures: Texture[];\n\n /**\n * Duration of the animation, in seconds.\n */\n private duration: number;\n\n /**\n * Animation framerate, in frames per second.\n */\n private framerate: number;\n\n /**\n * Animation time elapsed, in seconds.\n */\n private elapsed: number;\n\n /**\n * If this particle animation should loop.\n */\n private loop: boolean;\n\n /**\n * @param emitter The emitter that controls this AnimatedParticle.\n */\n constructor(emitter: Emitter)\n {\n super(emitter);\n\n this.textures = null;\n this.duration = 0;\n this.framerate = 0;\n this.elapsed = 0;\n this.loop = false;\n }\n\n /**\n * Initializes the particle for use, based on the properties that have to\n * have been set already on the particle.\n */\n public init(): void\n {\n this.Particle_init();\n\n this.elapsed = 0;\n\n // if the animation needs to match the particle's life, then cacluate variables\n if (this.framerate < 0)\n {\n this.duration = this.maxLife;\n this.framerate = this.textures.length / this.duration;\n }\n }\n\n /**\n * Sets the textures for the particle.\n * @param art An array of PIXI.Texture objects for this animated particle.\n */\n public applyArt(art: ParsedAnimatedParticleArt): void\n {\n this.textures = art.textures;\n this.framerate = art.framerate;\n this.duration = art.duration;\n this.loop = art.loop;\n }\n\n /**\n * Updates the particle.\n * @param delta Time elapsed since the previous frame, in __seconds__.\n */\n public update(delta: number): number\n {\n const lerp = this.Particle_update(delta);\n // only animate the particle if it is still alive\n\n if (lerp >= 0)\n {\n this.elapsed += delta;\n if (this.elapsed > this.duration)\n {\n // loop elapsed back around\n if (this.loop)\n {\n this.elapsed = this.elapsed % this.duration;\n }\n // subtract a small amount to prevent attempting to go past the end of the animation\n else\n {\n this.elapsed = this.duration - 0.000001;\n }\n }\n // add a very small number to the frame and then floor it to avoid\n // the frame being one short due to floating point errors.\n const frame = ((this.elapsed * this.framerate) + 0.0000001) | 0;\n\n this.texture = this.textures[frame] || Texture.EMPTY;\n }\n\n return lerp;\n }\n\n /**\n * Destroys the particle, removing references and preventing future use.\n */\n public destroy(): void\n {\n this.Particle_destroy();\n this.textures = null;\n }\n\n /**\n * Checks over the art that was passed to the Emitter's init() function, to do any special\n * modifications to prepare it ahead of time.\n * @param art The array of art data, properly formatted for AnimatedParticle.\n * @return The art, after any needed modifications.\n */\n public static parseArt(art: AnimatedParticleArt[]): any\n {\n const outArr: ParsedAnimatedParticleArt[] = [];\n\n for (let i = 0; i < art.length; ++i)\n {\n const data = art[i];\n const output = outArr[i] = {} as ParsedAnimatedParticleArt;\n const outTextures = output.textures = [] as Texture[];\n const textures = data.textures;\n\n for (let j = 0; j < textures.length; ++j)\n {\n let tex = textures[j];\n\n if (typeof tex === 'string')\n {\n outTextures.push(GetTextureFromString(tex));\n }\n else if (tex instanceof Texture)\n {\n outTextures.push(tex);\n }\n // assume an object with extra data determining duplicate frame data\n else\n {\n let dupe = tex.count || 1;\n\n if (typeof tex.texture === 'string')\n {\n tex = GetTextureFromString(tex.texture);\n }\n else// if(tex.texture instanceof Texture)\n {\n tex = tex.texture;\n }\n for (; dupe > 0; --dupe)\n {\n outTextures.push(tex);\n }\n }\n }\n\n // use these values to signify that the animation should match the particle life time.\n if (data.framerate === 'matchLife')\n {\n // -1 means that it should be calculated\n output.framerate = -1;\n output.duration = 0;\n output.loop = false;\n }\n else\n {\n // determine if the animation should loop\n output.loop = !!data.loop;\n // get the framerate, default to 60\n output.framerate = data.framerate > 0 ? data.framerate : 60;\n // determine the duration\n output.duration = outTextures.length / output.framerate;\n }\n }\n\n return outArr;\n }\n}\n"]}