private static void PlotLineHigh(IScreenBuffer buffer, int x0, int y0, int x1, int y1, Color color)
        {
            int dx = x1 - x0;
            int dy = y1 - y0;
            int xi = 1;

            if (dx < 0)
            {
                xi = -1;
                dx = -dx;
            }

            int D = 2 * dx - dy;
            int x = x0;

            for (int y = y0; y <= y1; y++)
            {
                buffer.DrawPixel(x, y, color);

                if (D > 0)
                {
                    x = x + xi;
                    D = D - 2 * dy;
                }
                D = D + 2 * dx;
            }
        }
        private static void PlotLineLow(IScreenBuffer buffer, int x0, int y0, int x1, int y1, Color color)
        {
            int dx = x1 - x0;
            int dy = y1 - y0;
            int yi = 1;

            if (dy < 0)
            {
                yi = -1;
                dy = -dy;
            }

            int D = 2 * dy - dx;
            int y = y0;

            for (int x = x0; x <= x1; x++)
            {
                buffer.DrawPixel(x, y, color);

                if (D > 0)
                {
                    y = y + yi;
                    D = D - 2 * dx;
                }
                D = D + 2 * dy;
            }
        }
 private static void PlotCircleSegments(IScreenBuffer buffer, int xc, int yc, int x, int y, Color color)
 {
     buffer.DrawPixel(xc + x, yc + y, color);
     buffer.DrawPixel(xc - x, yc + y, color);
     buffer.DrawPixel(xc + x, yc - y, color);
     buffer.DrawPixel(xc - x, yc - y, color);
     buffer.DrawPixel(xc + y, yc + x, color);
     buffer.DrawPixel(xc - y, yc + x, color);
     buffer.DrawPixel(xc + y, yc - x, color);
     buffer.DrawPixel(xc - y, yc - x, color);
 }
        public void Render(IScreenBuffer screen, PlayerInfo player)
        {
            screen.Clear();
            if (_lastScreenSize != screen.Dimensions)
            {
                _lastScreenSize = screen.Dimensions;
                _size           = new Point(screen.Dimensions.X, FireHeight);
                _fireBuffer     = new byte[_size.Area()];
                InitializeFire();
            }

            var yOffset = screen.Height - FireHeight;

            for (int y = 0; y < _size.Y; y++)
            {
                for (int x = 0; x < _size.X; x++)
                {
                    var colorIndex = _fireBuffer[y * _size.X + x];
                    var color      = _palette[colorIndex];
                    screen.DrawPixel(x, yOffset + y, color);
                }
            }
        }
        public static void PlotLineSmooth(this IScreenBuffer buffer, int x0, int y0, int x1, int y1, Color baseColor)
        {
            void Swap(ref int a, ref int b)
            {
                var temp = a;

                a = b;
                b = temp;
            }

            float FractionalPart(float f) => f - (int)f;
            float ReciprocalOfFractionalPart(float f) => 1 - FractionalPart(f);

            float Gamma(float x, float exp) => (float)Pow(x, 1.0f / exp);
            void DrawPixel(int x, int y) => buffer.DrawPixel(x, y, baseColor);
            void DrawPixelScale(int x, int y, float intensity) => buffer.AddPixel(x, y, baseColor * Gamma(intensity, GammaExponent));

            // Make sure the line runs top to bottom
            if (y0 > y1)
            {
                Swap(ref x0, ref x1);
                Swap(ref y0, ref y1);
            }
            // Draw the initial pixel, which is always exactly intersected by the line and so needs no weighting
            DrawPixel(x0, y0);

            var deltaX = x1 - x0;
            var xDir   = 1;

            if (deltaX < 0)
            {
                xDir   = -1;
                deltaX = -deltaX; // make DeltaX positive
            }

            var deltaY = y1 - y0; // Guaranteed to be positive since we made sure it goes from top to bottom

            // Special cases for horizontal, vertical, and diagonal lines
            if (deltaY == 0)
            {
                while (deltaX-- != 0)
                {
                    x0 += xDir;
                    DrawPixel(x0, y0);
                }
                return;
            }
            if (deltaX == 0)
            {
                do
                {
                    y0++;
                    DrawPixel(x0, y0);
                } while (--deltaY != 0);
                return;
            }
            if (deltaX == deltaY)
            {
                do
                {
                    x0 += xDir;
                    y0++;
                    DrawPixel(x0, y0);
                } while (--deltaY != 0);
                return;
            }

            // line is not horizontal, diagonal, or vertical
            float gradient         = 0;
            float accumulatedError = 0;

            bool isYMajorLine = deltaY > deltaX;

            if (isYMajorLine)
            {
                gradient = (float)deltaX / deltaY;
                while (--deltaY != 0)
                {
                    accumulatedError += gradient;
                    y0++;

                    DrawPixelScale(x0 + xDir * (int)accumulatedError, y0, ReciprocalOfFractionalPart(accumulatedError));
                    DrawPixelScale(x0 + xDir * (int)accumulatedError + xDir, y0, FractionalPart(accumulatedError));
                }
            }
            else
            {
                gradient = (float)deltaY / deltaX;
                while (--deltaX != 0)
                {
                    accumulatedError += gradient;
                    x0 += xDir;

                    DrawPixelScale(x0, y0 + (int)accumulatedError, ReciprocalOfFractionalPart(accumulatedError));
                    DrawPixelScale(x0, y0 + (int)accumulatedError + 1, FractionalPart(accumulatedError));
                }
            }
            // Draw the final pixel, which is always exactly intersected by the line
            // and so needs no weighting
            DrawPixel(x1, y1);
        }
 public static void DrawPixel(this IScreenBuffer buffer, Point p, Color c) => buffer.DrawPixel(p.X, p.Y, c);