import { ShapeGenerator } from "../assets/shape-generator" ; import { ColorData } from "../data/data-color" ; import { DrawingData } from "../data/data-drawing" ; import { AlphaCurveType } from "../enum/alpha-curve-type" ; import { Particle } from "./particle" ; type { string } export const VERSION = "1.0.0" ; param value export function checkVersion ( value ) { const currentVersion = VERSION . split ( "." ) ; if ( currentVersion . length <= 2 ) { console . log ( "バージョン表記エラーが発生しました。" ) ; return false ; } if ( ! value ) { if ( currentVersion [ 0 ] == "0" && currentVersion [ 1 ] == "1" ) { return true ; } else { return false ; } } const jsonVersion = value . split ( "." ) ; if ( currentVersion [ 0 ] != jsonVersion [ 0 ] ) { return false ; } if ( currentVersion [ 1 ] != jsonVersion [ 1 ] ) { return false ; } return true ; } /**
 * パーティクルの制御クラスです。
 */ export class ParticleSystem { /**
     *  グラフィックオブジェクトです。内部計算に使用します。
     */ private static HELPER_GRAPHICS : createjs . Graphics = new createjs . Graphics ( ) ; /**
     * パーティクルが配置されるコンテナーです。
     */ public container : createjs . Container ; private private _particlesPool : Particle [ ] ; private private _activeParticles : Particle [ ] ; private private _drawingData : DrawingData ; private private _frameCount : number = 0 ; private private _playing : boolean ; private private shapeGenerator : ShapeGenerator ; returns { boolean } public isPlaying ( ) { return this . _playing ; } constructor ( ) { this . _drawingData = new DrawingData ( ) ; this . _particlesPool = [ ] ; this . _activeParticles = [ ] ; this . container = new createjs . Container ( ) ; this . container . mouseChildren = false ; this . container . mouseEnabled = false ; this . _playing = true ; this . shapeGenerator = new ShapeGenerator ( ) ; } /**
     * パーティクルの設定データを取り込みます。
     */ public setData ( drawingData ) { this . _drawingData = drawingData ; } /**
     * パーティクルの設定データをJson形式のオブジェクトで取り込みます。
     */ public importFromJson ( jsonObject ) { if ( ! checkVersion ( jsonObject [ "VERSION" ] || "" ) ) { console . warn ( "読み込んだJSONファイルとParticleJSのバージョンが異なります。\n" + "https://github.com/ics-creative/ParticleJS" ) ; } this . _drawingData . importFromJson ( jsonObject ) ; } /**
     * パーティクルシステムの更新を行います。
     */ public update ( ) { if ( ! this . _playing ) { return ; } this . emit ( ) ; this . animate ( ) ; this . lifeCheck ( ) ; } /**
     * パーティクルの動きを更新します。
     */ private animate ( ) { const rad = createjs . Matrix2D . DEG_TO_RAD * this . _drawingData . accelerationDirection ; const accX = Math . cos ( rad ) * this . _drawingData . accelerationSpeed ; const accY = Math . sin ( rad ) * this . _drawingData . accelerationSpeed ; for ( let i = 0 ; i < this . _activeParticles . length ; i ++ ) { const particle = this . _activeParticles [ i ] ; particle . vx += accX ; particle . vy += accY ; particle . vx *= 1 - this . _drawingData . friction ; particle . vy *= 1 - this . _drawingData . friction ; particle . x += particle . vx ; particle . y += particle . vy ; particle . particleShape . x = particle . x ; particle . particleShape . y = particle . y ; const lifeParcent = particle . currentLife / particle . totalLife ; switch ( Number ( particle . alphaCurveType ) ) { case AlphaCurveType . Random : const min = Math . min ( particle . finishAlpha , particle . startAlpha ) ; const max = Math . max ( particle . finishAlpha , particle . startAlpha ) ; particle . particleShape . alpha = Math . random ( ) * ( max - min ) + min ; break ; case AlphaCurveType . Normal : default : const alpha = this . calcCurrentValue ( particle . startAlpha , particle . finishAlpha , lifeParcent ) ; particle . particleShape . alpha = alpha ; break ; } const scale = this . calcCurrentValue ( particle . startScale , particle . finishScale , lifeParcent ) ; particle . particleShape . scaleX = particle . particleShape . scaleY = scale ; if ( particle . currentLife < 0 ) { particle . isAlive = false ; } particle . currentLife -- ; } } /**
     * パーティクルが生きているか確認します。
     */ private lifeCheck ( ) { for ( let i = 0 ; i < this . _activeParticles . length ; i ++ ) { if ( ! this . _activeParticles [ i ] . isAlive ) { const particle = this . _activeParticles [ i ] ; this . container . removeChild ( particle . particleShape ) ; this . _activeParticles . splice ( i , 1 ) ; this . _particlesPool . push ( particle ) ; i -- ; } } } /**
     * パーティクルを全て削除します。
     */ public clear ( ) { for ( let i = 0 ; i < this . _activeParticles . length ; i ++ ) { const particle = this . _activeParticles [ i ] ; particle . isAlive = false ; this . container . removeChild ( particle . particleShape ) ; this . _activeParticles . splice ( i , 1 ) ; this . _particlesPool . push ( particle ) ; i -- ; } } /**
     * パーティクルシステムを破棄します。
     */ public dispose ( ) { for ( let i = 0 ; i < this . _activeParticles . length ; i ++ ) { const particle = this . _activeParticles [ i ] ; particle . isAlive = false ; this . container . removeChild ( particle . particleShape ) ; } this . _activeParticles . splice ( 0 , this . _activeParticles . length ) ; this . _particlesPool . splice ( 0 , this . _particlesPool . length ) ; this . _activeParticles = null ; this . _particlesPool = null ; this . container = null ; } /**
     * パーティクルの生成を行います。
     */ private emit ( ) { const framerate = Math . round ( createjs . Ticker . framerate ) ; const frameInSec = this . _frameCount % framerate ; const emitPerSec = this . _drawingData . emitFrequency ; const loopInt = emitPerSec == 0 ? 0 : Math . floor ( emitPerSec / framerate ) ; for ( let i = 0 ; i < loopInt ; i ++ ) { this . emitParticle ( ) ; } const loopFloat = emitPerSec / framerate - loopInt ; if ( emitPerSec != 0 && frameInSec % Math . floor ( 1 / loopFloat ) == 0 ) { this . emitParticle ( ) ; } this . _frameCount ++ ; if ( this . _frameCount >= framerate ) { this . _frameCount = 0 ; } } returns { Particle } private emitParticle ( ) { const particle = this . generateParticle ( ) ; this . container . addChild ( particle . particleShape ) ; this . _activeParticles . push ( particle ) ; } returns { Particle } private generateParticle ( ) { let particle = null ; if ( this . _particlesPool . length >= 1 ) { particle = this . _particlesPool . shift ( ) ; } else { particle = new Particle ( ) ; } this . setParticleParameter ( particle ) ; return particle ; } param particle private setParticleParameter ( particle ) { particle . particleShape . removeAllChildren ( ) ; particle . isAlive = true ; particle . x = this . calcRandomValueWithVariance ( this . _drawingData . startX , this . _drawingData . startXVariance , false ) ; particle . y = this . calcRandomValueWithVariance ( this . _drawingData . startY , this . _drawingData . startYVariance , false ) ; this . generateShape ( particle , this . _drawingData . shapeIdList ) ; particle . totalLife = Math . max ( 1 , this . calcRandomValueWithVariance ( this . _drawingData . lifeSpan , this . _drawingData . lifeSpanVariance , true ) ) ; particle . currentLife = particle . totalLife ; const speed = Math . max ( 0 , this . calcRandomValueWithVariance ( this . _drawingData . initialSpeed , this . _drawingData . initialSpeedVariance , false ) ) ; const angle = createjs . Matrix2D . DEG_TO_RAD * this . calcRandomValueWithVariance ( this . _drawingData . initialDirection , this . _drawingData . initialDirectionVariance , false ) ; particle . vx = Math . cos ( angle ) * speed ; particle . vy = Math . sin ( angle ) * speed ; particle . startAlpha = this . calcRandomValueWithRange ( 0.0 , 1.0 , this . calcRandomValueWithVariance ( this . _drawingData . startAlpha , this . _drawingData . startAlphaVariance , false ) ) ; particle . finishAlpha = this . calcRandomValueWithRange ( 0.0 , 1.0 , this . calcRandomValueWithVariance ( this . _drawingData . finishAlpha , this . _drawingData . finishAlphaVariance , false ) ) ; particle . startScale = Math . max ( 0 , this . calcRandomValueWithVariance ( this . _drawingData . startScale , this . _drawingData . startScaleVariance , false ) ) ; particle . finishScale = Math . max ( 0 , this . calcRandomValueWithVariance ( this . _drawingData . finishScale , this . _drawingData . finishScaleVariance , false ) ) ; particle . particleShape . compositeOperation = this . _drawingData . blendMode == true ? "lighter" : null ; particle . alphaCurveType = this . _drawingData . alphaCurveType ; } param particle param shapeIdList public generateShape ( particle , shapeIdList ) { particle . particleShape . removeAllChildren ( ) ; const startColor = this . _drawingData . startColor ; particle . startColor . hue = this . calcRandomValueWithVariance ( startColor . hue , startColor . hueVariance , false ) % 360 ; particle . startColor . luminance = this . calcRandomValueWithVariance ( startColor . luminance , startColor . luminanceVariance , false ) ; particle . startColor . saturation = this . calcRandomValueWithVariance ( startColor . saturation , startColor . saturationVariance , false ) ; const hue = Number ( particle . startColor . hue ) ; const saturation = Number ( particle . startColor . saturation ) ; const luminance = Number ( particle . startColor . luminance ) ; const color = `hsl(${ hue }, ${ saturation }%, ${ luminance }%)` ; const r = Math . floor ( Math . random ( ) * this . _drawingData . shapeIdList . length ) ; const shapeId = this . _drawingData . shapeIdList . length == 0 ? "" : this . _drawingData . shapeIdList [ r ] ; particle . colorCommand = null ; const container = < createjs . Container > ( this . shapeGenerator . generateShape ( shapeId ) ) ; particle . particleShape . addChild ( container ) ; const shape = < createjs . Shape > container . getChildAt ( 0 ) ; if ( shape == null ) { return ; } const instructions = shape . graphics . instructions ; if ( instructions && instructions . length > 0 ) { for ( let i = 0 ; i < instructions . length ; i ++ ) { const cmd = instructions [ i ] ; if ( cmd instanceof createjs . Graphics . Fill ) { if ( cmd . style instanceof CanvasGradient ) { const oldStyle = < any > cmd . style ; const g = ParticleSystem . HELPER_GRAPHICS ; const newStyle = g . beginRadialGradientFill ( [ color , `hsla(${ hue }, ${ saturation }%, ${ luminance }%, 0)` ] , oldStyle . props . ratios , oldStyle . props . x0 , oldStyle . props . y0 , oldStyle . props . r0 , oldStyle . props . x1 , oldStyle . props . y1 , oldStyle . props . r1 ) . command ; instructions [ i ] = newStyle ; } else { cmd . style = color ; particle . colorCommand = cmd ; } } else if ( cmd instanceof createjs . Graphics . Stroke ) { cmd . style = color ; particle . colorCommand = cmd ; } } } } /**
     * 一時的にパーティクルの再生を停止します。
     */ public pause ( ) { this . _playing = false ; } /**
     * pause()で停止したパーティクルの再生を再開します。
     */ public resume ( ) { this . _playing = true ; } param minValue param maxValue param value returns { number } private calcRandomValueWithRange ( minValue , maxValue , value ) { return Math . min ( maxValue , Math . max ( minValue , value ) ) ; } param value param variance param isInteger returns { number } private calcRandomValueWithVariance ( value , variance , isInteger ) { const result = Number ( value ) + ( Math . random ( ) - 0.5 ) * variance ; if ( isInteger == true ) { return Math . floor ( result ) ; } return result ; } param start param end param life returns { number } private calcCurrentValue ( start , end , life ) { return Number ( start ) * life + Number ( end ) * ( 1 - life ) ; } param value public set emitFrequency ( value ) { this . _drawingData . emitFrequency = value ; } returns { number } public get emitFrequency ( ) : number { return this . _drawingData . emitFrequency ; } param value public set startX ( value ) { this . _drawingData . startX = value ; } returns { number } public get startX ( ) : number { return this . _drawingData . startX ; } param value public set startXVariance ( value ) { this . _drawingData . startXVariance = value ; } returns { number } public get startXVariance ( ) : number { return this . _drawingData . startX ; } param value public set startY ( value ) { this . _drawingData . startY = value ; } returns { number } public get startY ( ) : number { return this . _drawingData . startY ; } param value public set startYVariance ( value ) { this . _drawingData . startYVariance = value ; } returns { number } public get startYVariance ( ) : number { return this . _drawingData . startYVariance ; } param value public set initialDirection ( value ) { this . _drawingData . initialDirection = value ; } returns { number } public get initialDirection ( ) : number { return this . _drawingData . initialDirection ; } param value public set initialDirectionVariance ( value ) { this . _drawingData . initialDirectionVariance = value ; } returns { number } public get initialDirectionVariance ( ) : number { return this . _drawingData . initialDirectionVariance ; } param value public set initialSpeed ( value ) { this . _drawingData . initialSpeed = value ; } returns { number } public get initialSpeed ( ) : number { return this . _drawingData . initialSpeed ; } param value public set initialSpeedVariance ( value ) { this . _drawingData . initialSpeedVariance = value ; } returns { number } public get initialSpeedVariance ( ) : number { return this . _drawingData . initialSpeedVariance ; } param value public set friction ( value ) { this . _drawingData . friction = value ; } returns { number } public get friction ( ) : number { return this . _drawingData . friction ; } param value public set accelerationSpeed ( value ) { this . _drawingData . accelerationSpeed = value ; } returns { number } public get accelerationSpeed ( ) : number { return this . _drawingData . accelerationSpeed ; } param value public set accelerationDirection ( value ) { this . _drawingData . accelerationDirection = value ; } returns { number } public get accelerationDirection ( ) : number { return this . _drawingData . accelerationDirection ; } param value public set startScale ( value ) { this . _drawingData . startScale = value ; } returns { number } public get startScale ( ) : number { return this . _drawingData . startScale ; } param value public set startScaleVariance ( value ) { this . _drawingData . startScaleVariance = value ; } returns { number } public get startScaleVariance ( ) : number { return this . _drawingData . startScaleVariance ; } param value public set finishScale ( value ) { this . _drawingData . finishScale = value ; } returns { number } public get finishScale ( ) : number { return this . _drawingData . finishScale ; } param value public set finishScaleVariance ( value ) { this . _drawingData . finishScaleVariance = value ; } returns { number } public get finishScaleVariance ( ) : number { return this . _drawingData . finishScaleVariance ; } param value public set lifeSpan ( value ) { this . _drawingData . lifeSpan = value ; } returns { number } public get lifeSpan ( ) : number { return this . _drawingData . lifeSpan ; } param value public set lifeSpanVariance ( value ) { this . _drawingData . lifeSpanVariance = value ; } returns { number } public get lifeSpanVariance ( ) : number { return this . _drawingData . lifeSpanVariance ; } param value public set startAlpha ( value ) { this . _drawingData . startAlpha = value ; } returns { number } public get startAlpha ( ) : number { return this . _drawingData . startAlpha ; } param value public set startAlphaVariance ( value ) { this . _drawingData . startAlphaVariance = value ; } returns { number } public get startAlphaVariance ( ) : number { return this . _drawingData . startAlphaVariance ; } param value public set finishAlpha ( value ) { this . _drawingData . finishAlpha = value ; } returns { number } public get finishAlpha ( ) : number { return this . _drawingData . finishAlpha ; } param value public set finishAlphaVariance ( value ) { this . _drawingData . finishAlphaVariance = value ; } returns { number } public get finishAlphaVariance ( ) : number { return this . _drawingData . finishAlphaVariance ; } param string public set shapeIdList ( value ) { this . _drawingData . shapeIdList = value ; } returns { string [ ] } public get shapeIdList ( ) : string [ ] { return this . _drawingData . shapeIdList ; } param value public set startColor ( value ) { this . _drawingData . startColor = value ; } returns { ColorData } public get startColor ( ) : ColorData { return this . _drawingData . startColor ; } param value public set blendMode ( value ) { this . _drawingData . blendMode = value ; } returns { boolean } public get blendMode ( ) : boolean { return this . _drawingData . blendMode ; } param value public set alphaCurveType ( value ) { this . _drawingData . alphaCurveType = value ; } returns { number } public get alphaCurveType ( ) : number { return this . _drawingData . alphaCurveType ; } }