Динамическое рисование муравьев в 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 Гц, оставляя серые следы.

Другие вопросы по тегам