/// <summary> /// Creates a new Particle type for this Emitter. /// </summary> /// <param name="name">Name of the particle type.</param> /// <param name="frames">Array of frame indices for the particles to animate.</param> /// <returns>A new ParticleType object.</returns> public ParticleType NewType(string name, int[] frames = null) { if (frames == null) { frames = FP.Frames(0); } if (_types.ContainsKey(name)) { throw new Exception("Cannot add multiple particle types of the same name"); } var type = new ParticleType(name, frames, _source, (int)_frameWidth, (int)_frameHeight); _types.Add(name, type); return(type); }
/// <summary> /// Emits a particle. /// </summary> /// <param name="name">Particle type to emit.</param> /// <param name="x">X point to emit from.</param> /// <param name="y">Y point to emit from.</param> /// <returns></returns> public Particle Emit(string name, float x, float y) { if (!_types.ContainsKey(name)) { throw new Exception("Particle type \"" + name + "\" does not exist."); } Particle p = null; ParticleType type = _types[name]; if (_cache != null) { p = _cache; _cache = p._next; } else { p = new Particle(); } p._next = _particle; p._prev = null; if (p._next != null) { p._next._prev = p; } p._type = type; p._time = 0; p._duration = type._duration + type._durationRange * FP.Random; float a = type._angle + type._angleRange * FP.Random; float d = type._distance + type._distanceRange * FP.Random; p._moveX = (float)Math.Cos(a) * d; p._moveY = (float)Math.Sin(a) * d; p._x = x; p._y = y; p._gravity = type._gravity + type._gravityRange * FP.Random; _particleCount++; return(_particle = p); }
/// <summary> /// Renders the particles. /// </summary> /// <param name="x">X position of the owning entity.</param> /// <param name="y">Y position of the owning entity.</param> public override void Render(float x, float y, Camera camera) { _vertexArray.Clear(); // quit if there are no particles if (_particle == null) { return; } // get rendering position // _point.x = point.x + x - camera.x * ScrollX; // _point.y = point.y + y - camera.y * ScrollY; // particle info float t, td; Particle p = _particle; ParticleType type = null; Vector2f _p = new Vector2f(); Vector2f _point = new Vector2f(X + x - (camera.X - FP.HalfWidth) * ScrollX, Y + y - (camera.Y - FP.HalfHeight) * ScrollY); var color = new Color(); var states = new RenderStates(_source); // loop through the particles while (p != null) { // get time scale t = p._time / p._duration; // get particle type type = p._type; // get position td = (type._ease == null) ? t : type._ease(t); _p.X = _point.X + p._x + p._moveX * td; _p.Y = _point.Y + p._y + p._moveY * td; // stops particles from moving when gravity is enabled // and if emitter.Active = false (for game pausing for example) if (Active) { p._moveY += p._gravity * td; } // get frame float frameX = _frameWidth * type._frames[(int)FP.Clamp(td * type._frameCount, 0, type._frames.Length - 1)]; float frameY = (int)(frameX / type._width) * _frameHeight; frameX %= (int)type._width; // get alpha float alphaT = (type._alphaEase == null) ? t : type._alphaEase(t); float a = type._alpha + type._alphaRange * alphaT; // get color td = (type._colorEase == null) ? t : type._colorEase(t); float r = type._red + type._redRange * td; float g = type._green + type._greenRange * td; float b = type._blue + type._blueRange * td; unchecked // screw you C# { color.R = (byte)(255 * r); color.G = (byte)(255 * g); color.B = (byte)(255 * b); color.A = (byte)(255 * a); } uint _x = _frameWidth; uint _y = _frameHeight; _vertexArray.Append(new Vertex(new Vector2f(_p.X, _p.Y), color, new Vector2f(frameX, frameY))); _vertexArray.Append(new Vertex(new Vector2f(_p.X + _x, _p.Y), color, new Vector2f(_x + frameX, frameY))); _vertexArray.Append(new Vertex(new Vector2f(_p.X + _x, _p.Y + _y), color, new Vector2f(_x + frameX, _y + frameY))); _vertexArray.Append(new Vertex(new Vector2f(_p.X, _p.Y + _y), color, new Vector2f(frameX, _y + frameY))); // get next particle p = p._next; } FP.Screen.Draw(_vertexArray, states); }