Динамическое рисование муравьев в winforms во время исполнения колонии муравьев
После этого вопроса ( Показать след движущегося пикселя в проекте C# WinForm) для моего личного проекта колонии муравьев в C# я пытаюсь применить второе предложенное решение: решение, которое объединяет рисование следа в растровое изображение и новых муравьев на поверхность.
[...]Application.Run(new ShowAnts());[...]
public partial class ShowAnts : Form
{
Bitmap bmp;
int j = 0;
public ShowAnts()
{
InitializeAntProgram();
InitializeComponent();
bmp = new Bitmap(pictureBox1.ClientSize.Width, pictureBox1.ClientSize.Height);
pictureBox1.Image = bmp;
}
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
while (j < 1000)
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c;
c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(Brushes.DarkBlue, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
j++;
}
}
}
}
Код выше показывает графическую попытку нарисовать движение муравья в форме win. Работает отлично, но показывает только конечный результат. Я хотел бы показать пошаговую эволюцию, сохраняя графическую информацию трассы без повторного анализа информации моей карты.
Обратите внимание, что рабочий консольный проект, над которым я разрабатываю этот "графический интерфейс", уже существует, поэтому:
- некоторые переменные установлены в другом месте (например, еда) в проекте;
- `a.Move(j);` относится к самой логике муравья (анализ, решение, перемещение новой ячейки в соответствии с массивом карты);
- счетчик `j` используется для подсчета шагов и установки произвольной остановки, но не имеет реального применения;
- Я уже храню в массиве карты и некоторых других переменных всю информацию, касающуюся феромона, движения, положения и т. Д.
1 ответ
Глядя на ваш код, а также на комментарии предыдущего вопроса, кажется, что вам не хватает той части, которая оживила бы движение. Вместо этого вы зацикливаетесь на том, что кажется Paint
событие.
Вот быстрое решение для этого. Добавляет Timer
что вызывает RenderAnts
событие, которое, кажется, подключено к pictureBox1.Paint
Обработчик..:
Несколько переменных уровня класса:
int counter = 0;
int limit = 1000;
Timer antTimer = new Timer();
Начальный код:
antTimer.Interval = 50; // <-- pick your speed !!
antTimer.Tick += (ss, ee) =>
{ pictureBox1.Invalidate(); counter++; if (counter > limit) antTimer.Stop(); };
antTimer.Start();
Скорость составляет 50 мс, что означает 20 Ticks
в секунду.
Tick
событие подчеркнуто с крошечной Lambda
Выражение и имеет только одно утверждение плюс логика цикла. От Invalidating
pictureBox1
контролировать его Paint
событие и тем самым RenderAnts
событие сработало.
Также обратите внимание, что я назвал это "быстрое решение". Обычно вы различаете рендеринг и движущийся код анимации; но в этом случае эта тонкая разница не имеет большого значения.
Теперь мы меняем RenderAnts
Метод, вынимающий цикл:
public void RenderAnts(object sender, PaintEventArgs e)
{
using (Graphics G = Graphics.FromImage(pictureBox1.Image))
{
Map.EvaporatesPheromones();
foreach (Vector2D food in foodSrcs)
{
Map.SetMapPoint(food, 500);
}
foreach (Ant a in ants)
{
Brush c = Brushes.DarkBlue;
if (a.role == AntRole.Scout)
{
a.Move(j);
c = Brushes.Red;
}
e.Graphics.FillRectangle(c, a.position.x, a.position.y, 1, 1);
G.FillRectangle(Brushes.Gray, a.position.x, a.position.y, 1, 1);
}
}
}
Вы также можете добавить старт / стоп Button
, Также TrackBar
изменить скорость..
Теперь вы сможете наблюдать за прогрессом ваших муравьев на частоте 20 Гц, оставляя серые следы.