Анимация в C # с использованием нескольких PNG

#c# #animation #png #sprite #picturebox

#c# #Анимация #png #спрайт #picturebox

Вопрос:

Я пытаюсь создать событие щелчка, которое запускает анимацию. Я нарисовал все кадры и сохранил их в виде отдельных файлов PNG (все они имеют длину 38 пикселей и ширину 56 пикселей), но я не могу понять, как запустить их через PictureBox.

Я просмотрел множество сообщений (здесь и в других местах), где люди говорят о таймерах, но я не смог понять, как вызвать любой из этих длинных примеров из моего события click. В качестве альтернативы я экспортировал кадры как один анимированный GIF, но GIF-файлы всегда зацикливаются, и я хочу, чтобы анимация воспроизводилась только один раз.

Вот что у меня есть:

 private void btnStart_Click(object sender, EventArgs e)
{
    int delay = 100;
    box1.Image = Project.Properties.Resources.frame1;
    System.Threading.Thread.Sleep(delay);
    box1.Image = Project.Properties.Resources.frame2;
    System.Threading.Thread.Sleep(delay);
    box1.Image = Project.Properties.Resources.frame3;
    System.Threading.Thread.Sleep(delay);
    box1.Image = Project.Properties.Resources.frame4;
    System.Threading.Thread.Sleep(delay);
    box1.Image = Project.Properties.Resources.frame5;
    System.Threading.Thread.Sleep(delay);
    box1.Image = Project.Properties.Resources.frame6;
    System.Threading.Thread.Sleep(delay);
    box1.Image = Project.Properties.Resources.frame7;
    System.Threading.Thread.Sleep(delay);
    box1.Image = Project.Properties.Resources.frame8;
    //(and so on)
}
 

Это ожидает около секунды, а затем резко переключается на последний кадр (frame8 в этом примере), независимо от того, какова переменная задержки.

Вероятно, я подхожу к этому совершенно неправильно. Что вы, ребята, думаете?

Ответ №1:

Обработчик событий блокирует основной поток. Пользовательский интерфейс обновляется в основном потоке.

Итак, вы нажимаете на кнопку, обработчик событий блокирует поток и выполняется, и все, что вы изменяете, не будет затронуто в пользовательском интерфейсе до тех пор, пока обработчик событий не завершит работу — это именно то, что вы испытываете.

Итак, в вашем обработчике событий нажатия кнопки вам нужно инициировать процесс, но сам процесс должен быть в отдельном потоке. Самый простой способ, если вы используете покадровую анимацию, — это использовать таймеры.

Вам нужно установить интервал в таймере, а в случае отметки таймера вам нужно загрузить новое изображение в поле изображения. Вам нужно отслеживать текущий индекс кадра с помощью отдельной переменной. Если внутри события tick вы понимаете, что это было последнее изображение — установите таймер в положение disabled. Сбросьте таймер и переменную кадра в событии нажатия кнопки.

Комментарии:

1. В этом есть смысл. Однако я ничего не знаю о таймерах. Я просмотрел это — dotnetperls.com/timer — но я не знаю, что все это значит.

2. Я предполагаю, что вы используете winforms, поэтому все, что вам нужно, это добавить компонент Timer в свою форму, а затем дважды щелкнуть по нему, чтобы создать обработчик таймера. Затем вам нужно создать переменную класса для обработки индекса фрейма.

3. Все в порядке. Я вставил все команды Image и delay в новое событие timer1_Tick и поместил «timer1_Tick ();» в событие click. Он подчеркнул эту ссылку, как будто ему нужны какие-то входные переменные.

4. Вы не должны звонить timer_Tick напрямую, вы должны сделать его активным ИЛИ неактивным. Когда таймер активен (его свойство Enabled равно True ), он генерирует timer_Tick событие по его ссылке через Interval в ms (что является еще одним свойством таймера). Таким образом, таймер должен быть отключен по умолчанию, при нажатии кнопки вам нужно включить его, а при последнем тике таймера вам нужно снова отключить таймер.

5. Извините, что я не ответил раньше, мне нужно было идти спать. Я помещаю «timer1.Start ();» в событие щелчка и «timer1.Stop ();» после всего, что было раньше. Он все еще останавливается на секунду и переходит к последнему кадру. Что я делаю не так?

Ответ №2:

Что я в конечном итоге сделал, так это поискал в Google подсказку «сам процесс должен быть в отдельном потоке» в первом ответе и последовал этому видеоуроку. То, что я сделал, было помещено

 using System.Threading;
 

в начале моего кода поместите

 Thread animationThread;
 

перед всеми основными событиями поставьте

 animationThread = new Thread(back2front_card1);
animationThread.Start();
 

в событии щелчка и поместите все команды box1.Image и delay в это:

 public void back2front_card1()
{
}
 

Это отлично запускает анимацию!