Dynamic drawing ants in winforms during execution of ant colony

拜拜、爱过 提交于 2019-12-13 17:20:25

问题


After this question (Show trail of moving pixel in C# WinForm project) for my personal ant colony project in c#, I'm trying to apply the solution second suggested solution: the one that combines drawing the trail into a bitmap and the new ants onto the surface.

[...]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++;
            }
        }
    }
}

The code above shows the graphic attempt to draw the ant movement into a winform. It works perfectly, but it shows only the final result. I would like to show the step by step evolution keeping the graphical trail information without reparsing my map info.

Please consider that a working console project on which I' developing this "graphic interface" already exists so:

  • some variables are set elsewhere (i.e.: food) in the project;
  • the `a.Move(j);` refers to the ant logic itself (analysis, decision, new cell movement referring to the map array);
  • the `j` counter is used to count steps and to set an arbitrary stop, but has no real use;
  • I'm already storing into map array and some other variables all informations concerning pheromone, movement, positions etc.

回答1:


Looking at your code and also the comments of the previous question, it seems that you are missing the part that would animate the movement. Instead you are looping inside what seems to be the Paint event.

Here is a quick fix for that. It adds a Timer that triggers the RenderAnts event, which seems to be hooked up to the pictureBox1.Paint handler..:

A few class level variables:

 int counter = 0;
 int limit = 1000;
 Timer antTimer = new Timer(); 

Start code:

 antTimer.Interval = 50;   // <-- pick your speed !!
 antTimer.Tick += (ss, ee) =>
 { pictureBox1.Invalidate(); counter++; if (counter > limit) antTimer.Stop(); };
 antTimer.Start();

The speed is 50ms, which means 20 Ticks per second.

The Tick event is inlined with a tiny Lambda epression and has only one statement plus the loop logic. By Invalidating the pictureBox1 control its Paint event and thereby the RenderAnts event is triggered.

Also note that I called it a 'quick fix'. Usually you would discern between the rendering and the moving code of an animation; but in this case this fine difference doesn't matter much.

Now we change the RenderAnts method, taking out the loop:

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);
        }
    }
}

You also may want to add a Start/Stop Button. Also a TrackBar to change the speed..

Now you should be able to watch the progress of your ants at 20Hz, leaving grey trails.



来源:https://stackoverflow.com/questions/38044137/dynamic-drawing-ants-in-winforms-during-execution-of-ant-colony

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!