Я пытаюсь сделать простой проект на C#, но, поскольку я в нем как бы новый, у меня много проблем. Что я хочу сделать, это имитировать движение мухи внутри круга. Он должен работать с щелчками мыши - сначала нажмите, вы выбрали центр круга. Второй щелчок, вы выбрали радиус круга и нарисуете его. На третьем клике (внутри круга) вы должны нарисовать муху (давайте сделаем ее маленькой, заполненной Ellipse), и она должна немедленно начать движение.Перемещение по выделенному кругу в C#
Я пытался сделать эту работу более недели, но без почти никакого результата.
Я использую панель в качестве холста.
Вот то, что я до сих пор:
private int start_x = 0;
private int start_y = 0;
private int end_x = 0;
private int end_y = 0;
private int fly_x = 0;
private int fly_y = 0;
private int clicks = 0;
private int distance = 0;
public Form1()
{
InitializeComponent();
}
private void panel1_MouseDown(object sender, MouseEventArgs e)
{
clicks++;
if (clicks == 1)
{
start_x = e.X;
start_y = e.Y;
}
else if (clicks == 2)
{
end_x = e.X;
end_y = e.Y;
}
else if (clicks == 3)
{
fly_x = e.X;
fly_y = e.Y;
}
else if (clicks == 4)
{
}
this.panel1.Refresh();
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Random r = new Random();
Thread t = new Thread(new ThreadStart(Fly));
if (clicks == 1)
{
e.Graphics.DrawEllipse(Pens.Black, start_x - 2, start_y - 2, 4, 4);
}
else if (clicks == 2)
{
distance = Distance(start_x, start_y, end_x, end_y);
e.Graphics.DrawEllipse(Pens.Black, start_x - 2, start_y - 2, 4, 4);
e.Graphics.DrawEllipse(Pens.Black, start_x - distance, start_y - distance, distance * 2, distance * 2);
}
else if (clicks == 3)
{
t.Start();
}
else if (clicks == 4)
{
t.Abort();
clicks = 0;
}
}
private int Distance(int a_x, int a_y, int b_x, int b_y)
{
int a, b;
a = a_x - b_x;
b = a_y - b_y;
return (Convert.ToInt32(Math.Sqrt(a * a + b * b)));
}
private void Fly()
{
Random r = new Random();
Graphics e = CreateGraphics();
distance = Distance(start_x, start_y, end_x, end_y);
while (clicks < 4)
{
e.DrawEllipse(Pens.Black, start_x - 2, start_y - 2, 4, 4);
e.DrawEllipse(Pens.Black, start_x - distance, start_y - distance, distance * 2, distance * 2);
e.FillEllipse(Brushes.Red, fly_x - 3, fly_y - 3, 6, 6);
fly_x = fly_x - 5 + r.Next(1, 11);
fly_y = fly_y - 5 + r.Next(1, 11);
Invalidate();
if (Distance(start_x, start_y, fly_x, fly_y) > distance - 1)
{
if (fly_x < start_x)
{
fly_x = fly_x + 5;
}
else
{
fly_x = fly_x - 5;
}
if (fly_y < start_y)
{
fly_y = fly_y + 5;
}
else
{
fly_y = fly_y - 5;
}
}
}
}
Но, очевидно, это не работает. Я могу нарисовать круг, но как только я снова нажму на панель, кружок исчезнет. Не могли бы вы указать мне в правильном направлении? Я имею в виду, что я делаю неправильно? Я попытался сделать это без использования потоков, и я дошел до того, что рисовал даже муху, но в этот момент все это застыло. EDIT: я удалил нить и поставить таймер:
private void panel1_Paint(object sender, PaintEventArgs e)
{
Random r = new Random();
this.DoubleBuffered = true;
if (clicks == 1)
{
e.Graphics.DrawEllipse(Pens.Black, start_x - 2, start_y - 2, 4, 4);
}
else if (clicks == 2)
{
distance = Distance(start_x, start_y, end_x, end_y);
e.Graphics.DrawEllipse(Pens.Black, start_x - 2, start_y - 2, 4, 4);
e.Graphics.DrawEllipse(Pens.Black, start_x - distance, start_y - distance, distance * 2, distance * 2);
}
else if (clicks == 3)
{
e.Graphics.DrawEllipse(Pens.Black, start_x - 2, start_y - 2, 4, 4);
e.Graphics.DrawEllipse(Pens.Black, start_x - distance, start_y - distance, distance * 2, distance * 2);
e.Graphics.FillEllipse(Brushes.Red, fly_x - 3, fly_y - 3, 6, 6);
}
else if (clicks == 4)
{
clicks = 0;
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Random r = new Random();
fly_x = fly_x - 5 + r.Next(1, 11);
fly_y = fly_y - 5 + r.Next(1, 11);
if (Distance(start_x, start_y, fly_x, fly_y) > distance - 1)
{
if (fly_x < start_x)
{
fly_x = fly_x + 5;
}
else
{
fly_x = fly_x - 5;
}
if (fly_y < start_y)
{
fly_y = fly_y + 5;
}
else
{
fly_y = fly_y - 5;
}
}
panel1.Invalidate();
}
Сейчас он работает, но до сих пор, изображение мерцает много, хотя я использовал двойную буферизацию. У меня есть решение от моего коллеги, и почему-то его не мерцает. Есть ли другой способ исправить это, чем двойной буфер?
Вам не нужна нить, в которой вам нужен таймер. – TaW
Вы можете использовать таймер, или вы можете просто вызвать panel.Invalidate() в конце вашего метода Paint, чтобы он постоянно перерисовывался. Я также рекомендую вам использовать настраиваемый элемент управления вместо панели. Это позволит вам включить стиль OptimizedDoubleBuffer в вашем конструкторе. Без него вы увидите некоторое уродливое мерцание, поскольку Windows продолжает стирать ваши рисунки с цветом фона перед каждым вызовом Paint. – RogerN
Я попытался использовать таймер, но ничего не сделал. Однако более вероятно, что я использовал его неправильно. Есть ли что-нибудь, что я должен знать при использовании таймера? – martin