public void Init(TextureRegion2D[] art, EmitterConfig config)
        {
            Cleanup();

            //store the original config and particle images, in case we need to re-initialize
            //when the particle constructor is changed
            origConfig     = config;
            origArt        = art;
            particleImages = art;
            ///////////////////////////
            // Particle Properties   //
            ///////////////////////////
            //set up the alpha
            if (config.alpha.HasValue)
            {
                startAlpha = PropertyNode <float> .CreateList((BasicTweenable <float>) config.alpha);
            }
            else
            {
                startAlpha = new PropertyNode <float>(1f, 0f);
            }
            //set up the speed
            if (config.speed.HasValue)
            {
                startSpeed = PropertyNode <float> .CreateList((BasicTweenable <float>) config.speed);

                minimumSpeedMultiplier = (config.minimumSpeedMultiplier.HasValue) ? (float)config.minimumSpeedMultiplier : 1f;
            }
            else
            {
                minimumSpeedMultiplier = 1f;
                startSpeed             = new PropertyNode <float>(0f, 0f);
            }
            //set up acceleration
            var acceleration = config.acceleration;

            if (acceleration.HasValue)
            {
                //make sure we disable speed interpolation
                startSpeed.next   = null;
                this.acceleration = (Vector2)acceleration;
                maxSpeed          = (float)(config.maxSpeed.HasValue ? config.maxSpeed : float.NaN);
            }
            else
            {
                this.acceleration = new Vector2();
            }
            //set up the scale
            if (config.scale.HasValue)
            {
                startScale = PropertyNode <float> .CreateList((BasicTweenable <float>) config.scale);

                minimumScaleMultiplier = (config.minimumScaleMultiplier.HasValue) ? (float)config.minimumScaleMultiplier : 1f;
            }
            else
            {
                startScale             = new PropertyNode <float>(1f, 0f);
                minimumScaleMultiplier = 1f;
            }
            //set up the color
            if (config.color.HasValue)
            {
                startColor = PropertyNode <Color> .CreateList((BasicTweenable <string>) config.color);
            }
            else
            {
                startColor = new PropertyNode <Color>(Color.White, 0);
            }
            //set up the start rotation
            if (config.startRotation.HasValue)
            {
                var startRot = (RandNumber)config.startRotation;
                minStartRotation = startRot.min;
                maxStartRotation = startRot.max;
            }
            else
            {
                minStartRotation = maxStartRotation = 0f;
            }
            if (config.noRotation.HasValue && (minStartRotation != 0f || maxStartRotation != 0f))
            {
                noRotation = (bool)config.noRotation;
            }
            else
            {
                noRotation = false;
            }
            //set up the rotation speed
            if (config.rotationSpeed.HasValue)
            {
                var rotSpeed = (RandNumber)config.rotationSpeed;
                minRotationSpeed = rotSpeed.min;
                maxRotationSpeed = rotSpeed.max;
            }
            else
            {
                minRotationSpeed = maxRotationSpeed = 0;
            }

            rotationAcceleration = config.rotationAcceleration.HasValue ? (float)config.rotationAcceleration : 0f;
            //set up the lifetime
            minLifetime = config.lifetime.min;
            maxLifetime = config.lifetime.max;
            //get the blend mode
            particleBlendMode = ParticleUtils.GetBlendMode(config.blendMode);

            //////////////////////////
            // Emitter Properties   //
            //////////////////////////
            //reset spawn type specific settings
            particlesPerWave = 1;
            if (config.particlesPerWave.HasValue && config.particlesPerWave > 1)
            {
                particlesPerWave = (int)config.particlesPerWave;
            }

            particleSpacing = 0;
            angleStart      = 0;
            Circle spawnCircle;

            //determine the spawn function to use
            switch (config.spawnType)
            {
            case "rect":
                spawnType = "rect";
                spawnFunc = SpawnRect;
                var spawnRect = (Rectangle)config.spawnRect;
                this.spawnRect = spawnRect;
                break;

            case "circle":
                spawnType        = "circle";
                spawnFunc        = SpawnCircle;
                spawnCircle      = (Circle)config.spawnCircle;
                this.spawnCircle = spawnCircle;
                break;

            case "ring":
                spawnType        = "ring";
                spawnFunc        = SpawnRing;
                spawnCircle      = (Circle)config.spawnCircle;
                this.spawnCircle = spawnCircle;
                break;

            case "burst":
                spawnType       = "burst";
                spawnFunc       = SpawnBurst;
                particleSpacing = (float)config.particleSpacing;
                angleStart      = config.angleStart.HasValue ? (float)config.angleStart : 0f;
                break;

            case "point":
                spawnType = "point";
                spawnFunc = SpawnPoint;
                break;

            default:
                spawnType = "point";
                spawnFunc = SpawnPoint;
                break;
            }
            //set the spawning frequency
            frequency   = config.frequency;
            spawnChance = (config.spawnChance.HasValue && config.spawnChance > 0) ? (float)config.spawnChance : 1f;
            //set the emitter lifetime
            emitterLifetime = config.emitterLifetime.HasValue ? (float)config.emitterLifetime : -1f;
            //set the max particles
            maxParticles = config.maxParticles > 0 ? (int)config.maxParticles : 1000;
            //determine if we should add the particle at the back of the list or not
            addAtBack = config.addAtBack;
            //reset the emitter position and rotation variables
            rotation       = 0;
            ownerPos       = new Vector2();
            spawnPos       = config.pos;
            prevEmitterPos = new Vector2(spawnPos.X, spawnPos.Y);
            //previous emitter position is invalid and should not be used for interpolation
            prevPosIsValid = false;
            //start emitting
            spawnTimer = 0;
            Emit       = config.emit;
        }
        public Emitter(Container particleParent, TextureRegion2D[] particleImages, EmitterConfig config)
        {
            //properties for individual particles
            this.particleImages    = null;
            startAlpha             = null;
            startSpeed             = null;
            minimumSpeedMultiplier = 1;
            acceleration           = new Vector2();
            maxSpeed               = float.NaN;
            startScale             = null;
            minimumScaleMultiplier = 1;
            startColor             = null;
            minLifetime            = 0f;
            maxLifetime            = 0f;
            minStartRotation       = 0;
            maxStartRotation       = 0;
            noRotation             = false;
            minRotationSpeed       = 0;
            maxRotationSpeed       = 0;
            particleBlendMode      = BlendState.AlphaBlend;
            /// this.customEase = null;
            /// this.extraData = null;
            //properties for spawning particles
            frequency       = 1;
            spawnChance     = 1;
            maxParticles    = 1000;
            emitterLifetime = -1;
            // this.spawnPos = null;
            spawnType = null;
            spawnFunc = null;
            // this.spawnRect = null;
            // this.spawnCircle = null;
            //  this.spawnPolygonalChain = null;
            particlesPerWave = 1;
            particleSpacing  = 0;
            angleStart       = 0;
            //emitter properties
            rotation = 0;
            // this.ownerPos = null;
            //  this.prevEmitterPos = null;
            prevPosIsValid       = false;
            posChanged           = false;
            parent               = null;
            addAtBack            = false;
            particleCount        = 0;
            _emit                = false;
            spawnTimer           = 0;
            emitterLife          = -1;
            activeParticlesFirst = null;
            activeParticlesLast  = null;
            poolFirst            = null;
            origConfig           = null;
            origArt              = null;
            autoUpdate           = false;
            destroyWhenComplete  = false;
            completeCallback     = null;

            //set the initial parent
            parent = particleParent;

            if (particleImages != null && config != null)
            {
                Init(particleImages, config);
            }
        }