protected BaseSpriteParticle NewParticle( Vector3 pos, Vector3 velocity, float lifeTime, Vector4 color, float maxRotation, int numTiles) { BaseSpriteParticle part = null; if (particleList.Count < MaxSprites) { if (unused.Count > 0) { part = unused[unused.Count - 1]; unused.RemoveAt(unused.Count - 1); part.Set(pos, velocity, lifeTime, color, maxRotation, numTiles); } else { part = new BaseSpriteParticle(); part.Set(pos, velocity, lifeTime, color, maxRotation, numTiles); } } return(part); }
public override void UpdateParticles(float dt) { // Let the particles keep up with us as we move Vector3 advance = (Position - PreviousPosition) * KeepUp; for (int i = 0; i < particleList.Count;) { BaseSpriteParticle particle = (BaseSpriteParticle)particleList[i]; particle.age += dt; Debug.Assert(particle.age >= 0.0f); float t = particle.age / particle.lifetime; if (t > 1.0f) { // Dead particle. ReleaseParticle(i); } else { particle.radius = MyMath.Lerp(startRadius, endRadius, t) * scale; particle.alpha = MyMath.Lerp(startAlpha, endAlpha, t); particle.rotation += particle.deltaRotation * dt; // Change the linear fade to a curve. particle.alpha *= particle.alpha; // Add in gravity effect. if (NonZeroGravity) { particle.velocity += Gravity * dt; float speed2 = particle.velocity.LengthSquared(); if (speed2 > MaxSpeed * MaxSpeed) { particle.velocity.Normalize(); particle.velocity *= MaxSpeed; } } particle.position += advance; particle.position += particle.velocity * dt; // Now make the spin about the source Vector2 fromCenter = new Vector2(particle.position.X - Position.X, particle.position.Y - Position.Y); fromCenter.Normalize(); double theta = dt * wreathRate; float sinTheta = (float)Math.Sin(theta); float cosTheta = (float)Math.Cos(theta); Vector2 delPos = scale * wreathRadius * ((float)theta) * (sinTheta * fromCenter + cosTheta * new Vector2(fromCenter.Y, -fromCenter.X)); particle.position.X += delPos.X; particle.position.Y += delPos.Y; i++; } } // end loop update particles. }
} // end of BaseSpriteEmitter Update() private void UpdateVerts() { for (int i = 0; i < particleList.Count; i++) { BaseSpriteParticle particle = (BaseSpriteParticle)particleList[particleList.Count - i - 1]; Vector3 newState = new Vector3(particle.rotation, particle.radius, particle.alpha); for (int j = 0; j < 4; j++) { localVerts[i * 4 + j].position = particle.position; localVerts[i * 4 + j].texCoord.Z = particle.tile; localVerts[i * 4 + j].state = newState; } } }
} // end of c'tor protected override void Emit(float dt) { if (emitting && manager.AllowEmission()) { // Adjust emission rate according to active particle count float adjustedEmissionRate = manager.AdjustEmissionRate(emissionRate); if (LinearEmission) { Vector3 deltaPosition = position - PreviousPosition; float dist = deltaPosition.Length(); partial += dist * adjustedEmissionRate; } else { partial += dt * adjustedEmissionRate; } // Emit as many particles as needed this // frame to keep up with the emission rate. while (partial >= 1.0f) { if (particleList.Count < maxSprites) { // Pick a random position somewhere along the path covered this frame. Vector3 pos = position - (position - PreviousPosition) * (float)rnd.NextDouble(); if (PositionJitter > 0.0f) { pos += PositionJitter * new Vector3((float)rnd.NextDouble() - (float)rnd.NextDouble(), (float)rnd.NextDouble() - (float)rnd.NextDouble(), (float)rnd.NextDouble() - (float)rnd.NextDouble()); } double rads = rnd.NextDouble() * MathHelper.TwoPi; Vector3 radial = scale * new Vector3((float)Math.Cos(rads), (float)Math.Sin(rads), 0.0f) * (wreathRadius + RadialJitter * ((float)rnd.NextDouble() * 2.0f - 1.0f)); pos += radial; // adjust lifetime according to active particle count Vector2 adjLifeTime = manager.AdjustLifetime(minLifetime, maxLifetime); float lifetime = adjLifeTime.X + (float)rnd.NextDouble() * (adjLifeTime.Y - adjLifeTime.X); BaseSpriteParticle particle = NewParticle(pos, initParticleVelocity, lifetime, color, maxRotationRate, NumTiles); particleList.Add(particle); } partial -= 1.0f; } } PreviousPosition = position; }
public virtual void UpdateParticles(float dt) { for (int i = 0; i < particleList.Count;) { BaseSpriteParticle particle = (BaseSpriteParticle)particleList[i]; particle.age += dt; Debug.Assert(particle.age >= 0.0f); float t = particle.age / particle.lifetime; if (t > 1.0f) { // Dead particle. ReleaseParticle(i); } else { particle.radius = MyMath.Lerp(startRadius, endRadius, t) * scale; particle.alpha = MyMath.Lerp(startAlpha, endAlpha, t); particle.rotation += particle.deltaRotation * dt; // Change the linear fade to a curve. particle.alpha *= particle.alpha; // Add in gravity effect. if (NonZeroGravity) { particle.velocity += Gravity * dt; float speed2 = particle.velocity.LengthSquared(); if (speed2 > MaxSpeed * MaxSpeed) { particle.velocity.Normalize(); particle.velocity *= MaxSpeed; } } particle.position += particle.velocity * dt; i++; } } // end loop update particles. }
} // end of c'tor // Cut and pasted from BaseSpriteEmitter, just to override // how the position is computed. Might like to refactor the // Update into common particle tasks (spawn, kill, move, etc.) public override void Update(Camera camera) { if (Active) { // Emit new particles if needed. float dt = Time.GameTimeFrameSeconds; dt = MathHelper.Clamp(dt, 0.0f, 1.0f); // Limit to reasonable values. Position += Velocity * dt; if (Emitting) { if (LinearEmission) { Vector3 deltaPosition = Position - PreviousPosition; float dist = deltaPosition.Length(); partial += dist * EmissionRate; } else { partial += dt * EmissionRate; } // Emit as many particles as needed this // frame to keep up with the emission rate. while (partial >= 1.0f) { if (particleList.Count < MaxSprites) { // Pick a random position on the sphere. Vector3 rndVec = new Vector3((float)(rnd.NextDouble() - rnd.NextDouble()), (float)(rnd.NextDouble() - rnd.NextDouble()), (float)(rnd.NextDouble() - rnd.NextDouble())); rndVec.Normalize(); rndVec *= targetRadius; Vector3 pos = Position + rndVec; // Pick a random position somewhere along the path covered this frame. if (PositionJitter > 0.0f) { pos += PositionJitter * new Vector3((float)rnd.NextDouble() - (float)rnd.NextDouble(), (float)rnd.NextDouble() - (float)rnd.NextDouble(), (float)rnd.NextDouble() - (float)rnd.NextDouble()); } float lifetime = MinLifetime + (float)rnd.NextDouble() * (MaxLifetime - MinLifetime); BaseSpriteParticle particle = new BaseSpriteParticle(pos, lifetime, Color, MaxRotationRate, NumTiles); particleList.Add(particle); } partial -= 1.0f; } } // Update the previous position to match the current one for the next frame. ResetPreviousPosition(); // Update any existing particles. For more heavyweight particles we could // have an Update call per particle. These are lightweight enough that we // can just update them directly. for (int i = 0; i < particleList.Count;) { BaseSpriteParticle particle = (BaseSpriteParticle)particleList[i]; particle.age += dt; Debug.Assert(particle.age >= 0.0f); float t = particle.age / particle.lifetime; if (t > 1.0f) { // Dead particle. particleList.RemoveAt(i); } else { particle.radius = MyMath.Lerp(StartRadius, EndRadius, t); particle.alpha = MyMath.Lerp(StartAlpha, EndAlpha, t); particle.rotation += particle.deltaRotation * dt; // Change the linear fade to a curve. particle.alpha *= particle.alpha; // Add in gravity effect. if (NonZeroGravity) { particle.velocity += Gravity * dt; float speed2 = particle.velocity.LengthSquared(); if (speed2 > MaxSpeed * MaxSpeed) { particle.velocity.Normalize(); particle.velocity *= MaxSpeed; } } particle.position += particle.velocity * dt; i++; } } // end loop update particles. // Now that we've updated all the particles, create/update the vertex buffer. UpdateVerts(); // See if we've died. if (Dying && particleList.Count == 0) { Active = false; RemoveFromManager(); } } // end of if active } // end Update