На просторах интернета нашел реализацию Матричного дождя (падающие строки как в фильме Матрица). Реализация консольная и я решил попробовать перенести ее на WPF. В консоли символы дождя ставятся сразу в нужную позицию:
Console.SetCursorPosition(x, y);
Перед каждой вставкой может меняться цвет текста.
Решил сделать через массив в который заносятся символы, а потом этот массив "печатается" в TextBox (реализация изменения цвета пока додумана, потом добавлю для каждого символа цвет и перейду на RichTextBox)
tb.Clear();
string s = "";
for (int i = 0; i < mh; i++)
{
for (int j = 0; j < mw; j++)
{
s += MatrixArray[i, j];
}
s += "
";
tb.Text += s;
}
В консоли было так:
public static void MatrixStep(int width, int height, int[] y, int[] l)
{
int x;
thistime = !thistime;
for (x = 0; x < width; ++x)
{
if (x % 11 == 10)
{
if (!thistime)
continue;
Console.ForegroundColor = ConsoleColor.White;
}
else
{
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.SetCursorPosition(x, inBoxY(y[x] - 2 - (l[x] / 40 * 2), height));
Console.Write(R);
Console.ForegroundColor = ConsoleColor.Green;
}
Console.SetCursorPosition(x, y[x]);
Console.Write(R);
y[x] = inBoxY(y[x] + 1, height);
Console.SetCursorPosition(x, inBoxY(y[x] - l[x], height));
Console.Write(' '); // Основной фоновый символ в потоке
}
Символы стразу выводились в консоль, а у меня сначала с массив.
При выводе дождя наблюдается мерцание текста:
Подскажите как можно оптимизировать данную задачу, или может есть более подходящий метод?
Воспользовался предложенным кодом с Canvas
private void PrintMatrix(int x, int y, char r)
{
this.Dispatcher.Invoke((Action)(() =>
{
AddText(x, y, r);
foreach (object myCanvasChild in cConsole.Children)
{
var tb = myCanvasChild as TextBlock;
if (tb == null) return;
var top = (double)tb.GetValue(Canvas.TopProperty);
Canvas.SetTop(tb, top);
}
}));
}
private void AddText(int x, int y, char r)
{
Rectangle rct = new Rectangle();
rct.Fill = Brushes.Black;
rct.Height = 19;
rct.Width = 17;
Canvas.SetTop(rct, 21 * x + 4);
Canvas.SetLeft(rct, 18 * y);
cConsole.Children.Add(rct);
var txt = new TextBlock
{
Text = r.ToString(),
Foreground = tc,
FontSize = 18,
FontWeight = FontWeights.Bold,
FontFamily = new FontFamily("Courier New")
};
Canvas.SetTop(txt, 21 * x + 5);
Canvas.SetLeft(txt, 18 * y + 3);
cConsole.Children.Add(txt);
}
Но картинка на canvas подвисает:
Ответ
code behind:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace matrix
{
///
public MainWindow()
{
InitializeComponent();
Task.Factory.StartNew(()=>
{
while (true)
{
Application.Current.Dispatcher.Invoke(()=>
{
AddText();
foreach (object myCanvasChild in MyCanvas.Children)
{
var tb = myCanvasChild as TextBlock;
if (tb == null) return;
var top = (double) tb.GetValue(Canvas.TopProperty);
Canvas.SetTop(tb, top + 50);
}
});
Thread.Sleep(TimeSpan.FromMilliseconds(300));
}
});
}
private void AddText()
{
var txt = new TextBlock
{
Text = $"some message value ={rnd.Next()}",
Foreground = new SolidColorBrush(Colors.Green)
};
Canvas.SetTop(txt, 0);
MyCanvas.Children.Add(txt);
}
}
}
XAML
PS надо бы еще почистить ненужные элементы
Комментариев нет:
Отправить комментарий