protected override void SetupRender() { _maxGroundHeight = 0; _xSpeedAdjustment = 1; _ySpeedAdjustment = 1; _wobbleAdjustment = 1; if (EnableGroundLevel) { _tempBuffer = new PixelFrameBuffer(BufferWi + 10, BufferHt + 10); for (int x = 0; x < BufferWi; x++) { for (int y = 0; y < CalculateGroundLevel(((double)100 / BufferWi) * x); y++) { _tempBuffer.SetPixel(x, y, GroundColor.GetColorAt(0)); int temp = (int)CalculateGroundLevel(y); if (temp > _maxGroundHeight) { _maxGroundHeight = temp; } } } } _meteors = new List <MeteorClass>(32); _maxBufferSize = Math.Max(BufferHt / 2, BufferWi / 2); }
protected override void SetupRender() { _maxGroundHeight = 0; if (EnableGroundLevel) { _tempBuffer = new PixelFrameBuffer(BufferWi + 10, BufferHt + 10); for (int x = 0; x < BufferWi; x++) { for (int y = 0; y < CalculateGroundLevel(((double)100 / BufferWi) * x); y++) { _tempBuffer.SetPixel(x, y, GroundColor.GetColorAt(0)); int temp = (int)CalculateGroundLevel(y); if (temp > _maxGroundHeight) { _maxGroundHeight = temp; } } } } }
protected override void RenderEffect(int frame, IPixelFrameBuffer frameBuffer) { int colorcnt = Colors.Count; var intervalPosFactor = GetEffectTimeIntervalPosition(frame) * 100; double level = LevelCurve.GetValue(intervalPosFactor) / 100; var length = CalculateLength(intervalPosFactor); int tailLength = BufferHt < 10 ? length / 10 : BufferHt * length / 100; int minDirection = 1; int maxDirection = 360; int pixelCount = CalculatePixelCount(intervalPosFactor); double centerSpeed = CalculateCenterSpeed(intervalPosFactor); double spreadSpeed = CalculateSpeedVariation(intervalPosFactor); double minSpeed = centerSpeed - (spreadSpeed / 2); double maxSpeed = centerSpeed + (spreadSpeed / 2); if (minSpeed < 1) { minSpeed = 1; } if (maxSpeed > 200) { maxSpeed = 200; } if (tailLength < 1) { tailLength = 1; } // create new meteors and maintain maximum number as per users selection. HSV hsv; int adjustedPixelCount; if (frame < pixelCount) { if (MeteorStartPosition == MeteorStartPosition.InitiallyRandom && frame > pixelCount) { adjustedPixelCount = 1; } else if (MeteorStartPosition == MeteorStartPosition.ZeroPosition) { adjustedPixelCount = pixelCount; } else { adjustedPixelCount = pixelCount < 10 ? pixelCount : pixelCount / 10; } } else { adjustedPixelCount = pixelCount; } int stringCount = 1; if (CountPerString && MeteorPerString) { stringCount = BufferWi; } for (int i = 0; i < adjustedPixelCount; i++) { for (int j = 0; j < stringCount; j++) { if (_meteors.Count >= pixelCount * stringCount) { break; } double position = (RandDouble() * ((maxSpeed) - minSpeed) + minSpeed) / 20; MeteorClass m = new MeteorClass(); if (MeteorEffect == MeteorsEffect.RandomDirection) { minDirection = MinDirection; maxDirection = MaxDirection; } int direction; if (MeteorEffect == MeteorsEffect.None) { direction = Direction; //Set Range for standard Meteor as we don't want to just have them going straight down or two dirctions like the original Meteor effect. } else { //This is to generate random directions between the Min and Max values //However if Someone makes the MaxDirection lower then the Min Direction then //the new direction will be the inverserve of the Min and Max effectively changing //the range from a downward motion to an upward motion, increasing the feature capability. if (maxDirection <= minDirection) { //used for the Upward movement of the Meteor (added feature) direction = Rand(1, 3) == 1 ? Rand(1, maxDirection) : Rand(minDirection, 360); } else { //used for the downward movemnet of the Meteor (standard way) direction = Rand(minDirection, maxDirection); } } //Moving if (!CountPerString) { m.X = Rand() % BufferWi; } m.Y = Rand() % BufferHt; if (MeteorPerString) { m.TailY = FlipDirection ? 1 : -1; if (CountPerString) { var meteorExists = false; foreach (var meteor in _meteors) { if (meteor.X == j) { meteorExists = true; break; } } if (meteorExists) { continue; } m.X = j; } m.DeltaY = m.TailY * position; m.Y = Rand() % BufferHt; } else if (direction >= 0 && direction <= 90) { m.TailX = ((double)direction / 90); m.DeltaX = m.TailX * position; m.TailY = ((double)Math.Abs(direction - 90) / 90); m.DeltaY = m.TailY * position; if (RandDouble() >= (double)(90 - direction) / 100) { m.X = 0; m.Y = Rand() % BufferHt; } else { m.X = Rand() % BufferWi; m.Y = 0; } } else if (direction > 90 && direction <= 180) { m.TailX = ((double)Math.Abs(direction - 180) / 90); m.DeltaX = m.TailX * position; m.TailY = -1 * ((double)Math.Abs(direction - 90) / 90); m.DeltaY = m.TailY * position; if (RandDouble() >= (double)(180 - direction) / 100) { m.X = Rand() % BufferWi; m.Y = BufferHt; } else { m.X = 0; m.Y = Rand() % BufferHt; } } else if (direction > 180 && direction <= 270) { m.TailX = -1 * ((double)Math.Abs(direction - 180) / 90); m.DeltaX = m.TailX * position; m.TailY = -1 * ((double)Math.Abs(direction - 270) / 90); m.DeltaY = m.TailY * position; if (RandDouble() >= (double)(270 - direction) / 100) { m.X = BufferWi; m.Y = Rand() % BufferHt; } else { m.X = Rand() % BufferWi; m.Y = BufferHt; } } else if (direction > 270 && direction <= 360) { m.TailX = -1 * ((double)Math.Abs(direction - 360) / 90); m.DeltaX = m.TailX * position; m.TailY = ((double)Math.Abs(270 - direction) / 90); m.DeltaY = m.TailY * position; if (RandDouble() >= (double)(360 - direction) / 100) { m.X = Rand() % BufferWi; m.Y = 0; } else { m.X = BufferWi; m.Y = Rand() % BufferHt; } } if (MeteorEffect == MeteorsEffect.Explode) { m.X = (BufferWi - 1) / 2; m.Y = (BufferHt - 1) / 2; } else { if (MeteorStartPosition == MeteorStartPosition.ZeroPosition) { if (MeteorPerString) { m.Y = FlipDirection ? 0 : BufferHt; } } else if (MeteorStartPosition == MeteorStartPosition.Random || frame < pixelCount) { if (!MeteorPerString) { m.X = Rand() % BufferWi - 1; } m.Y = BufferHt - 1 <= _maxGroundHeight ? 0 : Rand(_maxGroundHeight, BufferHt - 1); } } m.DeltaXOrig = m.DeltaX; m.DeltaYOrig = m.DeltaY; switch (ColorType) { case MeteorsColorType.Range: //Random two colors are selected from the list for each meteor. m.Hsv = SetRangeColor( HSV.FromRGB(Colors[Rand() % colorcnt].GetColorAt((intervalPosFactor) / 100)), HSV.FromRGB(Colors[Rand() % colorcnt].GetColorAt((intervalPosFactor) / 100))); break; case MeteorsColorType.Palette: //All colors are used m.Hsv = HSV.FromRGB(Colors[Rand() % colorcnt].GetColorAt((intervalPosFactor) / 100)); break; case MeteorsColorType.Gradient: m.Color = Rand() % colorcnt; _gradientPosition = 100 / (double)tailLength / 100; m.Hsv = HSV.FromRGB(Colors[m.Color].GetColorAt(0)); break; } m.HsvBrightness = RandomBrightness ? RandDouble() * (1.0 - .20) + .20 : 1; _meteors.Add(m); } } if (EnableGroundLevel) { hsv = HSV.FromRGB(GroundColor.GetColorAt((intervalPosFactor) / 100)); hsv.V *= LevelCurve.GetValue(intervalPosFactor) / 100; for (int x = 0; x < BufferWi; x++) { for (int y = 0; y < CalculateGroundLevel(((double)100 / BufferWi) * x); y++) { if (_tempBuffer.GetColorAt(x, y) != Color.Empty) { frameBuffer.SetPixel(x, y, hsv); } } } } // render meteors foreach (MeteorClass meteor in _meteors) { meteor.DeltaX += meteor.DeltaXOrig; meteor.DeltaY += meteor.DeltaYOrig; int colorX = meteor.X + (int)meteor.DeltaX - BufferWi / 100; int colorY = meteor.Y + (int)meteor.DeltaY + BufferHt / 100; for (int ph = 0; ph < tailLength; ph++) { switch (ColorType) { case MeteorsColorType.RainBow: //No user colors are used for Rainbow effect. meteor.Hsv.H = (float)(Rand() % 1000) / 1000.0f; meteor.Hsv.S = 1.0f; meteor.Hsv.V = 1.0f; break; case MeteorsColorType.Gradient: meteor.Hsv = HSV.FromRGB(Colors[meteor.Color].GetColorAt(_gradientPosition * ph)); break; } hsv = meteor.Hsv; hsv.V *= meteor.HsvBrightness * (float)(1.0 - (double)ph / tailLength) * level; //var decPlaces = (int) (((decimal) (meteor.TailX*ph)%1)*100); var decPlaces = (int)(meteor.TailX * ph % 1d * 100); if (decPlaces <= 40 || decPlaces >= 60) { if (MeteorEffect == MeteorsEffect.Explode && ph > 0 && (colorX == (BufferWi / 2) + (int)(Math.Round(meteor.TailX * ph)) || colorX == (BufferWi / 2) - (int)(Math.Round(meteor.TailX * ph)) || colorY == (BufferHt / 2) + (int)(Math.Round(meteor.TailY * ph)) || colorY == (BufferHt / 2) - (int)(Math.Round(meteor.TailY * ph)))) { break; } frameBuffer.SetPixel(colorX - (int)(Math.Round(meteor.TailX * ph)), colorY - (int)(Math.Round(meteor.TailY * ph)), hsv); } } if (colorX > 0 && colorX < BufferWi - 1 && colorY > 0 && colorY < BufferHt && EnableGroundLevel) { if (!_tempBuffer.GetColorAt(colorX, colorY).IsEmpty) { if (frame > 1) { _tempBuffer.SetPixel(colorX, colorY, Color.Empty); _tempBuffer.SetPixel(colorX, colorY - 1, Color.Empty); _tempBuffer.SetPixel(colorX - 1, colorY, Color.Empty); _tempBuffer.SetPixel(colorX + 1, colorY, Color.Empty); _tempBuffer.SetPixel(colorX, colorY + 1, Color.Empty); _tempBuffer.SetPixel(colorX + 1, colorY + 1, Color.Empty); _tempBuffer.SetPixel(colorX - 1, colorY + 1, Color.Empty); _tempBuffer.SetPixel(colorX + 1, colorY + 2, Color.Empty); _tempBuffer.SetPixel(colorX - 1, colorY + 2, Color.Empty); _tempBuffer.SetPixel(colorX + 1, colorY + 3, Color.Empty); _tempBuffer.SetPixel(colorX - 1, colorY + 3, Color.Empty); _tempBuffer.SetPixel(colorX + 2, colorY + 3, Color.Empty); _tempBuffer.SetPixel(colorX - 2, colorY + 3, Color.Empty); _tempBuffer.SetPixel(colorX + 2, colorY + 2, Color.Empty); _tempBuffer.SetPixel(colorX - 2, colorY + 2, Color.Empty); _tempBuffer.SetPixel(colorX, colorY + 2, Color.Empty); _tempBuffer.SetPixel(colorX, colorY + 3, Color.Empty); _tempBuffer.SetPixel(colorX - 2, colorY + 4, Color.Empty); _tempBuffer.SetPixel(colorX - 1, colorY + 4, Color.Empty); _tempBuffer.SetPixel(colorX, colorY + 4, Color.Empty); _tempBuffer.SetPixel(colorX + 1, colorY + 4, Color.Empty); _tempBuffer.SetPixel(colorX + 2, colorY + 4, Color.Empty); } meteor.Expired = true; } } if (colorX >= BufferWi + tailLength || colorY >= BufferHt + tailLength || colorX < 0 - tailLength || colorY < 0 - tailLength) { meteor.Expired = true; //flags Meteors that have reached the end of the grid as expiried. // break; } } // delete old meteors int meteorNum = 0; while (meteorNum < _meteors.Count) { if (_meteors[meteorNum].Expired) { _meteors.RemoveAt(meteorNum); } else { meteorNum++; } } }