'How can I speed up Console Drawing in C#?

I'm currently working on a 2D game engine using the default windows Console with C#, Problem is I've noticed that once there are multiple objects moving around on the screen the Console updating method I created takes a bit too much time to execute.

    public void DrawScreen()
    {
        Console.CursorVisible = false;
        Image[] layers = GetAllLayers(true);

        for (int line = 0; line < Height; line++)
        {
            for (int index = 0; index < Width; index++)
            {
                Image? top = null;

                for (int i = 0; i < layers.Length; i++)
                {
                    top = layers[i];
                    if ((index - top.PosX >= 0) && (line - top.PosY >= 0) &&
                        (index <= top.PosX + top.Width - 1) && (line <= top.PosY + top.Height - 1) &&
                        !(top.Graphics[line - top.PosY, index - top.PosX].IsClear))
                    {
                        Pixel pixel = top.Graphics[line - top.PosY, index - top.PosX];

                        if (CurrentScreen.Graphics[line, index].Equals(pixel)) break;

                        CurrentScreen.Graphics[line, index] = pixel;
                        Console.SetCursorPosition(index, line);
                        DrawPixel(pixel);
                        break;
                    }
                    top = null;
                }

                if (top is not null)
                    continue;

                Console.SetCursorPosition(index, line);
                Console.Write(' ');
                continue;

            }
        }

        Console.SetCursorPosition(0, 0);
    }

    public static void DrawPixel(Pixel pixel)
    {
        if (Console.ForegroundColor != pixel.Color)
            Console.ForegroundColor = pixel.Color;

        Console.Write(pixel.Content);
    }

I'll try to explain how it works, the Console screen is represented by a 2D array of Pixels 'Pixel[,]' (I'll explain about the Pixel struct later) called "CurrentScreen", The Width variable equals Console.WindowWidth and the Height property equals Console.WindowHeight. Everything that is supposed to be drawn to the screen is stored inside a list where each index represents a different layer, the for loops here loop over each character position on the screen and checks for the top-layer Image that is supposed to be drawn at that character position, so that it doesn't draw pixels to the screen just for them to get covered immediately after. After it finds the top-layer image it checks to see if the current pixel is already drawn at the current Console position by checking if its already inside of the "CurrentScreen" array; if it is than it breaks out of the for loop and continues to the next position inside the Console, if it isn't already drawn than it draws it. If the for loop fails to layer with a pixel it needs to draw it just prints a space instead.

This Method does work as intended and already is efficient at drawing to the screen as it doesn't overlay the different layers and also only writes the pixels that have changed, problem is that even though this Method is pretty speedy it's not as speedy as I would have liked and I found that the thing that slows down this method the most is the Console.Write() method called inside of the DrawPixel() method, what I would like to know is if there is any faster way to draw characters to the screen than Conosle.Write() and if there is any thing I can do to fasten my DrawScreen() method.

To help you out I'll explain a bit about the Image class and the Pixel struct:

The pixel struct is a simple struct that contains a box drawing character '█' property called "Content" along side a ConsoleColor Foreground Color property called "Color", there is also another bool property called "IsClear" so that the DrawScreen() method would know not to draw that pixel but the pixel in the layer under it.

the Image class is a class that contains properties for it's location on the screen called "PosX" and "PosY" other than that it also has a Pixel[,] property called "Graphics", I think the name is pretty self-explanatory. The Width property is the Width of the Graphics array or Graphics.GetLength(1) and the Height property is Graphics.GetLength(0).

Update: I haven't done much to the function itself but I've been trying to run it on a separate thread automatically every set amount of time, problem is I wasn't able to get this to work because my "CurrentScreen" variable which the DrawScreen() Method uses was changing while the thread drawed off that, so I'm wondering is there any way for me to tell the thread to work of the variables at the time it was created?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source