Цветной вывод в консоль с помощью функции WriteConsoleOutputCharacter (C#)
Разрабатываю консольную ASCII-игру на C#. Мне нужно максимально быстро выводить матрицу символов на экран. Узнал про функцию WriteConsoleOutputCharacter из WinAPI, и она действительно оказалась самым оптимизированным вариантом. Вот только мне непонятно, как настроить для каждого символа его собственный цвет и цвет его фона. Я реализовал этот момент с помощью 24-битной версии ANSI-color: "\x1b[48;2;" + 100 + ";" + 0 + ";" + 0 + "m\x1b[38;2;" + 0 + ";" + 200 + ";" + 0 + "m" + "~"
. Console.Write правильно это выводит, а WriteConsoleOutputCharacter не понимает управляющие последовательности ANSI. Как можно изменить цвет каждого символа матрицы/его фона по отдельности, не теряя сильно в производительности?
P.S. Меня устроит решение и с меньшим количеством цветов, главное избавиться от одноцветности.
Ключевые для задачи фрагменты кода:
public static class Output
{
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern bool SetConsoleMode( IntPtr hConsoleHandle, int mode );
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern bool GetConsoleMode( IntPtr handle, out int mode );
[DllImport( "kernel32.dll", SetLastError = true )]
public static extern IntPtr GetStdHandle( int handle );
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
private static extern bool WriteConsoleOutputCharacter(IntPtr hConsoleOutput, string lpCharacter, uint nLength, Point16 dwWriteCoord, out uint lpNumberOfCharsWritten);
private const int STD_OUTPUT_HANDLE = -11;
private const int STD_INPUT_HANDLE = -10;
private const int STD_ERROR_HANDLE = -12;
private static readonly IntPtr _stdOut = GetStdHandle(STD_OUTPUT_HANDLE);
[StructLayout(LayoutKind.Sequential)]
private struct Point16
{
public short X;
public short Y;
public Point16(short x, short y)
=> (X, Y) = (x, y);
}
public static string[,] matrix;
public static StringBuilder sb;
public static void Init()
{
int mode;
GetConsoleMode( _stdOut, out mode );
SetConsoleMode( _stdOut, mode | 0x4 );
matrix = new string[Console.WindowHeight, Console.WindowWidth];
sb = new StringBuilder();
}
public static void WriteToBufferAt(string text, int x, int y)
{
WriteConsoleOutputCharacter(_stdOut, text, (uint)text.Length, new Point16((short)x, (short)y), out uint _);
}
public static void Map()
{
// *инициализация всех элементов матрицы*
foreach (string s in matrix)
{
sb.Append(s);
}
WriteToBufferAt(sb.ToString(), 0, 0);
sb.Clear();
Console.SetCursorPosition(0, 0);
}
}
public static class Game
{
static void Main( string[] args )
{
Output.Init();
Output.Map();
}
}