Анимация в c#

Здравствуйте. У меня такое задание: Создайте программу, показывающую движение окружности вдоль многоугольника. Число вершин вводится пользователем до анимации. Все работает, но есть недочеты. Помогите, пожалуйста, избавится от мигания анимации. Также при открытии формы, в верхнем углу видно часть окружности. Помогите ее как то сдвинуть, пожалуйста.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace WindowsFormsApp8
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private PointF tek_pt;// int x = 130, y = 20;
        private PointF start_pos = new Point(230, 50);
        private int tek_ind;
        private double v = 1;
        private int rad = 20;//радиус окружности
        List<PointF> points = new List<PointF>();
        Graphics g;

        private void buttonStart_Click(object sender, EventArgs e)
        {
            points.Clear();
            try
            {
                int length = 50;//размер
                int count = int.Parse(textBox1.Text);
                if (count < 3)
                {
                    MessageBox.Show("Количество вершин должно быть не менее тёрх! ");
                    Application.Exit();
                }
                if (count > 20)
                {
                    MessageBox.Show("Очень большое количество вершин. ");
                    Application.Exit();
                }
                if (count < 0) count = -count;//если введено отрицательное число                          
                double R = length / (2 * Math.Sin(Math.PI / count));
                for (double angle = 0.0; angle <= 2 * Math.PI; angle += 2 * Math.PI / count)
                {
                    int x = (int)(R * Math.Cos(angle));
                    int y = (int)(R * Math.Sin(angle));
                    points.Add(new PointF((int)R + x + start_pos.X, (int)R + y + start_pos.Y));
                }
                this.Invalidate();
                tek_pt = new PointF(points[0].X, points[0].Y);
                tek_ind = 1;
                timer1.Start();
            }
            catch
            {
                MessageBox.Show("Данные введены не корректно!");
            }
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            g = e.Graphics;
            e.Graphics.FillEllipse(Brushes.Red, tek_pt.X - (rad / 2), tek_pt.Y - (rad /2), rad, rad);
            if (points.Count >= 3)
                e.Graphics.DrawPolygon(Pens.Blue, points.ToArray());
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (tek_ind != points.Count - 1)
            {
                PointF A = tek_pt;
                PointF B = points[tek_ind];
                if (Math.Sqrt(((B.X - A.X) * (B.X - A.X)) + ((B.Y - A.Y) * (B.Y - A.Y))) <= v)
                {
                    tek_pt = points[tek_ind];
                    B = points[tek_ind + 1];
                    tek_ind += 1;
                }
                double k1 = B.X - A.X;
                double k2 = B.Y - A.Y;
                double h = Math.Sqrt((A.X - B.X) * (A.X - B.X) + (A.Y - B.Y) * (A.Y - B.Y)) / v;
                double x = A.X + (k1 / h);
                double y = A.Y + (k2 / h);
                tek_pt = new PointF((float)x, (float)y);
                Invalidate();
            }
            else
            {
                tek_ind = 1;
            }
        }
    }
}

https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-reduce-graphics-flicker-with-double-buffering-for-forms-and-controls

Спасибо, помогло)

Что-то оно перепрыгивает одну вершину :spinningparrot:

Peek 2020-06-02 17-25

Можно контрол NumericUpDown вместо этого.
И зачем всю программу закрывать при ошибке ввода?) Можно например return; из функции.

Так где рисуете, там и есть )

Во втором и третьем параметрах — позиция, которая видимо инициализирована в (0, 0) по умолчанию:

Если надо скрыть её до запуска, то можно например завести какой-нибудь флаг bool isStarted = false, проверять его в OnPaint, присваивать true при нажатии кнопки.

ЗЫ если tek это tekushiaia, то чтобы не смешивать русский с английским можно использовать слово current )

1 лайк

Вот несколько поменяла:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace WindowsFormsApp8
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private PointF tek_pt;
        private PointF start_pos = new Point(200, 50);
        private int tek_ind;
        private double v = 1;
        private float rad = 20f;
        List<PointF> points = new List<PointF>();

        private void buttonStart_Click(object sender, EventArgs e)
        {
            points.Clear();

            int count = (int)numericUpDown1.Value;
            int length = 50;//размер

            double R = length / (2 * Math.Sin(Math.PI / count));
            for (double angle = 0.0; angle <= 2 * Math.PI; angle += 2 * Math.PI / count)
            {
                int x = (int)(R * Math.Cos(angle));
                int y = (int)(R * Math.Sin(angle));
                points.Add(new PointF((int)R + x + start_pos.X, (int)R + y + start_pos.Y));
            }
            Invalidate();
            tek_pt = new PointF(points[0].X, points[0].Y);
            tek_ind = 1;
            timer1.Start();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            e.Graphics.FillEllipse(Brushes.Red, tek_pt.X - (rad / 2.0f), tek_pt.Y - (rad /2.0f), rad, rad);
            if (points.Count >= 3)
                e.Graphics.DrawPolygon(Pens.Blue, points.ToArray());
            DoubleBuffered = true;
        }
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (tek_ind != points.Count)
            {
                PointF A = tek_pt;
                PointF B = points[tek_ind];
                if (Math.Sqrt(((B.X - A.X) * (B.X - A.X)) + ((B.Y - A.Y) * (B.Y - A.Y))) <= v)
                {
                    tek_pt = points[tek_ind];
                    B = points[tek_ind];
                    tek_ind += 1;
                }
                double k1 = B.X - A.X;
                double k2 = B.Y - A.Y;
                double h = Math.Sqrt((A.X - B.X) * (A.X - B.X) + (A.Y - B.Y) * (A.Y - B.Y)) / v;
                double x = A.X + (k1 / h);
                double y = A.Y + (k2 / h);
                tek_pt = new PointF((float)x, (float)y);
                Invalidate();
            }
            else
            {
                tek_ind = 1;
            }
        }

        private void buttonvihod_Click(object sender, EventArgs e)
        {
            this.Close();
        }       
        private void buttonStart_MouseHover(object sender, EventArgs e)
        {
            toolTip1.SetToolTip(buttonStart, "Нажмите \"Ок\", чтобы увидеть анимацию");
        }
        private void buttonvihod_MouseHover(object sender, EventArgs e)
        {
            toolTip2.SetToolTip(buttonvihod, "Нажмите \"Выход\", чтобы закрыть текущую форму");
        }
    }
}

Спасибо, за ваши советы) Только не могу разобраться с этой окружностью,как ее скрыть до запуска

Так я ж написал самый простой вариант:

"проверять его в OnPaint" ==

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            if (!isStarted)
            {
                return;
            }
1 лайк

Спасибо вам огромное!

Можешь сам проект готовый скинуть ?
Can you drop the project ?

Да выше ж есть большая часть кода, можно начать с этого )
Какие компоненты и события кинуть на форму тут легко понять.

why are you writing in English on a Russian forum? :thinking: