Уроки, алгоритмы, программы, примеры

Материалы по разделам

Построения
на плоскости (2D)
Графика
в пространстве (3D)
Вычислительная
геометрия
Физическое
моделирование
Фрактальная
графика

Новые комментарии

У меня проблема вот с этим: gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);. Вылезает ошибка: CS1061 "object" не содержит определения "GL_COLOR_BUFFER_BIT", и не удалось найти доступный метод расширения "GL_COLOR_BUFFER_BIT",...
Большое спасибо. Единственный код который прошел без каких либо ошибок. Ура!!!
Скажите пожалуйста, подскажите алгоритм по которому по заданным точкам можно определить тип многогранника, скажем это куб или прямоугольный параллелепипед. Нашел теорию по этим фигурам: https://www.mat... https://www.mat... Акцентировать внимание...
Всем у кого не работает. файл wizard.script Ещё одно упоминание Glut32 в строке "if (!VerifyLibFile(dir_nomacro_lib, _T("glut32"), _T("GLUT's"))) return false;" меняем на "if (!VerifyLibFile(dir_nomacro_lib, _T("freeglut"), _T("GLUT's"))) return...
Не получается, емаё

Счетчики и рейтинг

Рейтинг@Mail.ru Яндекс.Метрика
Среда программирования: 
Microsoft C#

Если после прочтения предыдущего урока Вы попытались сделать анимацию, состоящую из небольшого количества элементов, то никаких проблем с анимацией не должно было возникнуть.
Но если картинка будет состоять из множества элементов или будет необходимость закрашивать весь фон, или будет анимация по неоднородному фону, а следовательно потребуется прорисовка большого количества элементов, то метод описанный в предыдущем уроке уже работать не будет и возникнут проблемы с «миганием» анимации. Например, как показано на гифке ниже, которая самую малость мерцает. (код данной анимации будет чуть ниже, уже в исправленном виде.)

Перейдем к решению этой проблемы.

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

Для того, чтобы избавиться от мигания, нам необходимо будет завести некий буфер, на котором мы будем рисовать, а потом уже его в готовом виде отображать на pictureBox по тику таймера. В роли такого буфера выступит Bitmap.
Следовательно, всё что нам потребуется – это объявить объект типа Bitmap Bitmap myBitmap;(как глобальную переменную) и объект типа Graphics Graphics gr; .

Затем инициализируем Bitmap, указав размеры (ширину и высоту) myBitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height); И привязываем графику не к PictureBox, как было ранее, а к созданному буферу – Bitmap gr = Graphics.FromImage(myBitmap);

Далее почти весь процесс рисования аналогичен процессу, приведенному в предыдущем уроке, но добавляется одна строчка, которая нужна для вывода Bitmap на PictureBox - pictureBox1.Image = myBitmap; Эта строчка указывает, какое изображение, должен отображать PictureBox.

Ниже приведен код исправленной не мигающей анимации.
Из-за того, что код вышел немножко большим, то советую обратить внимание лишь на работу с графикой - объявление и инициализация Bitmap, Graphics и вывод изображения на форму, а определения классов просто скопировать (начиная с class chset и по class circles).

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace Lesson_Animation_Part2
{
    public partial class Form1 : Form
    {
        // объявляем объект типа Bitmap, который будет буфером для хранения
        // и прорисовки изображений
        Bitmap myBitmap; 
 
        // объявляем "средства" рисования - графику, перо и заливку
        Graphics gr; 
        Pen pen;
        SolidBrush brush;
 
        // объявляем переменные для храения центра рисуемого изображения
        // и смещения его относительно заданного центра
        int centerX;
        int centerY;
        int offsetX;
        int offsetY;
 
        // переменные для движения в анимации
        int movX;
        int movY;
 
        // объявляем объекты - части тела, рисуемого изображения
        // писание соответствующих классов будет ниже
        Circles circ;
        Chest ch;
        Shirt sh;
        Pants pa;
        Legs le;
        Cuffs cu;
        LHand lha;
        RHand rha;
        Eye bEye;
        Eye fEye;
        Mouth mo;
 
        // описание функции, для задания смещения изображения
        // при анимации, которая использует функции-методы определенных классов
        void setOffset(int x, int y)
        {
            ch.setOffset(x, y);
            bEye.setOffset(x, y);
            fEye.setOffset(x, y);
            mo.setOffset(x, y);
            lha.setOffset(x, y);
            rha.setOffset(x, y);
        }
 
 
 
        //класс - туловище изображения
        // так как само содержимое классов не сильно отличается, то 
        // только данный класс будет описан подробно
        // остальным будет дано лишь описание рисуемой части "тела"
        public class Chest
        {
            // переменные для хранения центра и смещения изображения
            int cenX;
            int cenY;
            int offsX;
            int offsY;
            // заливка туловища
            SolidBrush BrChest = new SolidBrush(Color.Yellow);
 
            // конструктор класса, который определеяем центр и смещение
            public Chest(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx;
                cenY = Cy;
                offsX = offX;
                offsY = offY;
            }
 
            // функция, для задания смещения при анимации
            public void setOffset(int x, int y)
            {
                offsX += x;
                offsY += y;
            }
 
            // функция для прорисовка данной части "тела"
            // принимает графику, которой рисует и перо
            public void Draw(Graphics b, Pen p)
            {
                // рисуем переднюю часть туловища
                Rectangle Chest1 = new Rectangle(cenX - 150 + offsX, cenY - 175 + offsY, 220, 175);
                b.FillRectangle(BrChest, Chest1);
                b.DrawRectangle(p, Chest1);
 
                // определяем многоугольник для того, чтобы придать
                // ощущение объемного тела изображения
                Point[] Chest2 = new Point[]{
                new Point(cenX - 150 + offsX, cenY - 175 + offsY), 
                new Point(cenX - 175 + offsX, cenY - 160 + offsY),
 
                new Point(cenX - 175 + offsX, cenY + 15 + offsY),
                new Point(cenX - 150 + offsX, cenY + offsY)
            };
                // заливаем полученную фигуру
                b.FillPolygon(BrChest, Chest2);
                b.DrawPolygon(p, Chest2);
 
            }
        }
 
        //класс для рисования рубашки (слой между телом и штанами)
        //никуда не сдвигается при анимации
        public class Shirt
        {
            int cenX;
            int cenY;
            int offsX;
            int offsY;
            SolidBrush BrShirt = new SolidBrush(Color.LightSteelBlue);
 
            public Shirt(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx;
                cenY = Cy;
                offsX = offX;
                offsY = offY;
            }
            public void Draw(Graphics b, Pen p)
            {
                Rectangle Shirt1 = new Rectangle(cenX - 150 + offsX, cenY + offsY, 220, 50);
                b.FillRectangle(BrShirt, Shirt1);
                b.DrawRectangle(p, Shirt1);
 
                Point[] Shirt2 = new Point[]{
                    new Point(cenX - 150 + offsX, cenY + offsY), 
                    new Point(cenX - 175 + offsX, cenY  + 15 + offsY),
 
                    new Point(cenX - 175 + offsX, cenY + 65 + offsY),
                    new Point(cenX - 150 + offsX, cenY + 50 + offsY)
            };
                b.FillPolygon(BrShirt, Shirt2);
                b.DrawPolygon(p, Shirt2);
 
 
            }
        }
 
        //класс для рисования штанов
        //никуда не сдвигается при анимации
        public class Pants
        {
            int cenX;
            int cenY;
            int offsX;
            int offsY;
            SolidBrush BrPants = new SolidBrush(Color.SaddleBrown);
 
            public Pants(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx;
                cenY = Cy;
                offsX = offX;
                offsY = offY;
            }
 
            public void Draw(Graphics b, Pen p)
            {
                Rectangle Pants1 = new Rectangle(cenX - 150 + offsX, cenY + 50 + offsY, 220, 50);
                b.FillRectangle(BrPants, Pants1);
                b.DrawRectangle(p, Pants1);
 
                Point[] Pants2 = new Point[]{
                    new Point(cenX - 150 + offsX, cenY  + 50 + offsY), 
                    new Point(cenX - 175 + offsX, cenY  + 65 + offsY),
 
                    new Point(cenX - 175 + offsX, cenY   + 115 + offsY),
                    new Point(cenX - 150 + offsX, cenY  + 100 + offsY)
            };
                b.FillPolygon(BrPants, Pants2);
                b.DrawPolygon(p, Pants2);
 
                Point[] Pants3 = new Point[]{
                    new Point(cenX - 175  + offsX, cenY   + 115 + offsY),
                    new Point(cenX - 150 + offsX, cenY  + 100 + offsY),
 
                    new Point(cenX + 70 + offsX, cenY  + 100 + offsY),
                    new Point(cenX + 45 + offsX, cenY  + 115 + offsY),
                    new Point(cenX - 175 + offsX, cenY   + 115 + offsY)
            };
                b.FillPolygon(BrPants, Pants3);
                b.DrawPolygon(p, Pants3);
 
            }
 
        }
 
        //класс для рисования ног
        //никуда не сдвигается при анимации
        public class Legs
        {
            int cenX;
            int cenY;
            int offsX;
            int offsY;
            SolidBrush BrLegs = new SolidBrush(Color.SaddleBrown);
            SolidBrush BrFoot = new SolidBrush(Color.Black);
            public Legs(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx;
                cenY = Cy;
                offsX = offX;
                offsY = offY;
            }
 
            public void Draw(Graphics b, Pen p)
            {
                Rectangle Leg1 = new Rectangle(cenX - 130 + offsX, cenY + 110 + offsY, 40, 40);
                Rectangle Leg2 = new Rectangle(cenX - 10 + offsX, cenY + 110 + offsY, 40, 40);
                b.FillRectangle(BrLegs, Leg1);
                b.FillRectangle(BrLegs, Leg2);
                b.DrawRectangle(p, Leg1);
                b.DrawRectangle(p, Leg2);
 
                Point leg1_1 = new Point(cenX - 110 + offsX, cenY + 150 + offsY);
                Point leg1_2 = new Point(cenX - 110 + offsX, cenY + 210 + offsY);
 
                Point leg2_1 = new Point(cenX + 10 + offsX, cenY + 150 + offsY);
                Point leg2_2 = new Point(cenX + 10 + offsX, cenY + 210 + offsY);
 
                b.DrawLine(p, leg1_1, leg1_2);
                b.DrawLine(p, leg2_1, leg2_2);
 
                Rectangle leg1_3 = new Rectangle(cenX - 160 + offsX, cenY + 190 + offsY, 70, 30);
                b.FillEllipse(BrFoot, leg1_3);
                b.DrawEllipse(p, leg1_3);
 
                Rectangle leg2_3 = new Rectangle(cenX - +10 + offsX, cenY + 190 + offsY, 70, 30);
                b.FillEllipse(BrFoot, leg2_3);
                b.DrawEllipse(p, leg2_3);
            }
 
        }
 
        //класс для рисования манжетов и галстука
        //никуда не сдвигается при анимации
        public class Cuffs
        {
            int cenX;
            int cenY;
            int offsX;
            int offsY;
            SolidBrush BrCuffs = new SolidBrush(Color.White);
 
            public Cuffs(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx;
                cenY = Cy;
                offsX = offX;
                offsY = offY;
            }
 
            public void Draw(Graphics b, Pen p)
            {
                Point[] Cuffs1 = new Point[]{
                new Point(cenX + offsX - 90, cenY + offsY ), 
                new Point(cenX + offsX - 70, cenY + offsY  + 25),
 
                new Point(cenX + offsX - 50, cenY + offsY  ),
                //new Point(cenX + offsX - 150, cenY + offsY  + 50)
 
            };
                b.FillPolygon(BrCuffs, Cuffs1);
                b.DrawPolygon(p, Cuffs1);
 
                Point[] Cuffs2 = new Point[]{
                new Point(cenX + offsX + 10, cenY + offsY ), 
                new Point(cenX + offsX - 10, cenY + offsY  + 25),
 
                new Point(cenX + offsX - 30, cenY + offsY  ),
                //new Point(cenX + offsX - 150, cenY + offsY  + 50)
 
            };
                b.FillPolygon(BrCuffs, Cuffs2);
                b.DrawPolygon(p, Cuffs2);
 
                SolidBrush BrCuffs3 = new SolidBrush(Color.Red);
                Point[] Cuffs3_1 = new Point[]{
                new Point(cenX + offsX - 50, cenY + offsY ), 
                new Point(cenX + offsX - 40, cenY + offsY  + 15),
 
                new Point(cenX + offsX - 30, cenY + offsY  ),
                //new Point(cenX + offsX - 150, cenY + offsY  + 50)
            };
 
                b.FillPolygon(BrCuffs3, Cuffs3_1);
                b.DrawPolygon(p, Cuffs3_1);
 
                Point[] Cuffs3_2 = new Point[]{ 
                new Point(cenX + offsX - 40, cenY + offsY  + 15),
                new Point(cenX + offsX - 50, cenY + offsY + 60), 
                new Point(cenX + offsX - 40, cenY + offsY  + 75),
                new Point(cenX + offsX - 30, cenY + offsY + 60 )
            };
 
                b.FillPolygon(BrCuffs3, Cuffs3_2);
                b.DrawPolygon(p, Cuffs3_2);
            }
        }
 
        //классы для рисования левой и правой руки
        //задействованы в анимации
        public class LHand
        {
            int cenX;
            int cenY;
 
            SolidBrush BrHand = new SolidBrush(Color.Yellow);
 
            public LHand(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx + offX - 155;
                cenY = Cy + offY - 20;
            }
            public void setOffset(int x, int y)
            {
                cenX += x;
                cenY += y;
            }
            public void Draw(Graphics b, Pen p)
            {
                Point[] shoulder = new Point[]{
                    new Point(cenX, cenY),
                    new Point(cenX - 15, cenY - 5),
                    new Point(cenX - 40, cenY + 40),
                    new Point(cenX, cenY + 50)
                };
                b.FillPolygon(BrHand, shoulder);
                b.DrawPolygon(p, shoulder);
 
                Point Hand1 = new Point(cenX - 20, cenY + 45);
                Point Hand2 = new Point(cenX - 35, cenY + 100);
 
                Point Palm1 = new Point(cenX - 50, cenY + 110);
                Point Palm2 = new Point(cenX - 30, cenY + 115);
                Point Palm3 = new Point(cenX - 45, cenY + 120);
                b.DrawLine(p, Hand1, Hand2);
                b.DrawLine(p, Hand2, Palm1);
                b.DrawLine(p, Hand2, Palm2);
                b.DrawLine(p, Hand2, Palm3);
            }
        }
 
        public class RHand
        {
            int cenX;
            int cenY;
 
            SolidBrush BrHand = new SolidBrush(Color.Yellow);
 
            public RHand(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx + offX + 70;
                cenY = Cy + offY - 30;
            }
            public void setOffset(int x, int y)
            {
                cenX += x;
                cenY += y;
            }
            public void Draw(Graphics b, Pen p)
            {
                Point[] shoulder = new Point[]{
                    new Point(cenX, cenY),
                    new Point(cenX, cenY - 15),
                    new Point(cenX + 40, cenY - 40),
                    new Point(cenX + 45, cenY - 5)
                };
                b.FillPolygon(BrHand, shoulder);
                b.DrawPolygon(p, shoulder);
 
                Point Hand1 = new Point(cenX + 43, cenY - 20);
                Point Hand2 = new Point(cenX + 93, cenY - 50);
 
                Point Palm1 = new Point(cenX + 105, cenY - 65);
                Point Palm2 = new Point(cenX + 110, cenY - 35);
                Point Palm3 = new Point(cenX + 110, cenY - 50);
                b.DrawLine(p, Hand1, Hand2);
                b.DrawLine(p, Hand2, Palm1);
                b.DrawLine(p, Hand2, Palm2);
                b.DrawLine(p, Hand2, Palm3);
            }
        }
 
        //класс для рисования глаз
        //двигается вместе с туловищем
        public class Eye
        {
            int cenX;
            int cenY;
            int r1, r2, r3;
 
            SolidBrush e1 = new SolidBrush(Color.Black);
            SolidBrush e2 = new SolidBrush(Color.Cyan);
            SolidBrush e3 = new SolidBrush(Color.White);
 
            public Eye(int Cx, int Cy, int offX, int offY, int ra1, int ra2, int ra3)
            {
                cenX = Cx + offX - 40;
                cenY = Cy + offY - 150;
                r1 = ra1;
                r2 = ra2;
                r3 = ra3;
            }
            public void setOffset(int x, int y)
            {
                cenX += x;
                cenY += y;
            }
 
            public void Draw(Graphics b, Pen p)
            {
                b.FillEllipse(e3, cenX, cenY, r3, r3);
                b.DrawEllipse(p, cenX, cenY, r3, r3);
 
                b.FillEllipse(e2, cenX + r3 / 4 - 1, cenY + r3 / 4 - 1, r2, r2);
                b.DrawEllipse(p, cenX + r3 / 4 - 1, cenY + r3 / 4 - 1, r2, r2);
 
                b.FillEllipse(e1, cenX + r3 / 3 + 4, cenY + r3 / 3 + 4, r1, r1);
                b.DrawEllipse(p, cenX + r3 / 3 + 4, cenY + r3 / 3 + 4, r1, r1);
 
                Point b1 = new Point(cenX, cenY - 5);
                Point b2 = new Point(cenX + 10, cenY + 10);
                Point b3 = new Point(cenX + 20, cenY - 5);
                Point b4 = new Point(cenX + 30, cenY - 5);
 
                b.DrawBezier(p, b1, b2, b3, b4);
            }
 
        }
 
        //класс дли рисования рта
        //двигается вместе с туловищем
        public class Mouth
        {
            int cenX;
            int cenY;
            SolidBrush BrTongue = new SolidBrush(Color.Salmon);
            SolidBrush BrTooth = new SolidBrush(Color.White);
            SolidBrush BrNose = new SolidBrush(Color.Gold);
            public Mouth(int Cx, int Cy, int offX, int offY)
            {
                cenX = Cx + offX - 20;
                cenY = Cy + offY - 50;
 
            }
 
            public void setOffset(int x, int y)
            {
                cenX += x;
                cenY += y;
            }
            public void Draw(Graphics b, Pen p)
            {
                Point p1 = new Point(cenX - 50, cenY - 20);
                Point p2 = new Point(cenX - 10, cenY + 20);
                Point p3 = new Point(cenX + 20, cenY + 5);
                Point p4 = new Point(cenX + 40, cenY - 10);
 
                Point p5 = new Point(cenX - 50, cenY - 20);
                Point p6 = new Point(cenX - 20, cenY + 60);
                Point p7 = new Point(cenX + 40, cenY + 70);
                Point p8 = new Point(cenX + 40, cenY - 10);
 
 
                b.DrawBezier(p, p1, p2, p3, p4);
                b.DrawBezier(p, p5, p6, p7, p8);
 
                b.FillPie(BrTongue, cenX - 30, cenY + 20, 40, 40, 15, -150);
                b.DrawPie(p, cenX - 30, cenY + 20, 40, 40, 15, -150);
 
                Point[] tooth = new Point[]{
                 new Point(cenX - 10, cenY +5),
                 new Point(cenX - 10, cenY + 15),
                 new Point(cenX + 5, cenY + 15),
                 new Point(cenX + 5, cenY + 5)
             };
 
                b.FillPolygon(BrTooth, tooth);
                b.DrawPolygon(p, tooth);
 
                Rectangle nose = new Rectangle(cenX - 20, cenY - 35, 50, 30);
                b.FillEllipse(BrNose, nose);
                b.DrawEllipse(p, nose);
 
 
            }
 
        }
 
        //класс для обрамления рисуемой области
        //хранит центры и радиус кругов
        //функция рисования реализуется при помощи двух циклов,
        //которые рисуют кружки на противоположных сторонах PictureBox
        public class Circles
        {
 
            public int radius;
            public int x;
            public int y;
 
 
            SolidBrush crlB = new SolidBrush(Color.Green);
 
            public Circles()
            {
                radius = 20;
                x = 5;
                y = 5;
            }
            public void Draw(Pen p, Graphics b, PictureBox pBox)
            {
                while (x <= pBox.Width - radius)
                {
                    b.FillEllipse(crlB, x, y, radius, radius);
                    b.DrawEllipse(p, x, y, radius, radius);
                    b.FillEllipse(crlB, x, pBox.Height - radius, radius, radius);
                    b.DrawEllipse(p, x, pBox.Height - radius, radius, radius);
                    x += radius;
                }
 
                x -= radius;
                while (y <= pBox.Height - radius)
                {
                    b.FillEllipse(crlB, x, y, radius, radius);
                    b.DrawEllipse(p, x, y, radius, radius);
                    b.FillEllipse(crlB, 5, y, radius, radius);
                    b.DrawEllipse(p, 5, y, radius, radius);
                    y += radius;
                }
                x = 5;
                y = 5;
            }
 
 
 
 
 
        }
 
        public Form1()
        {
            InitializeComponent();
        }
 
        //функция обработки нажатия клавиши
        private void button1_Click(object sender, EventArgs e)
        {
            //инициализируем Bitmap, задав его размеры, на которых будем рисовать
            myBitmap = new Bitmap(pictureBox1.Width, pictureBox1.Height);
            //привязываем графику к нашему Bitmap
            gr = Graphics.FromImage(myBitmap);
            // gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            //инициализируем перо и фоновую заливку
            pen = new Pen(Color.Black);
            brush = new SolidBrush(Color.Aqua);
 
            // задаем центр рисуемого изображения и смещение
            centerX = pictureBox1.Width / 2;
            centerY = pictureBox1.Height / 2;
            offsetX = 0;
            offsetY = 0;
 
 
            //закрашиваем фон
            gr.FillRectangle(brush, 0, 0, pictureBox1.Width, pictureBox1.Height);
 
            //инициализируем объекты, в соответствии с описанными конструкторами
            //передав центр и смещение относительно центра
            circ = new Circles();
            ch = new Chest(centerX, centerY, offsetX, offsetY);
            sh = new Shirt(centerX, centerY, offsetX, offsetY);
            pa = new Pants(centerX, centerY, offsetX, offsetY);
            le = new Legs(centerX, centerY, offsetX, offsetY);
            cu = new Cuffs(centerX, centerY, offsetX, offsetY);
            lha = new LHand(centerX, centerY, offsetX, offsetY);
            rha = new RHand(centerX, centerY, offsetX, offsetY);
            bEye = new Eye(centerX, centerY, offsetX, offsetY, 20, 40, 70);
            fEye = new Eye(centerX - 50, centerY, offsetX, offsetY, 20, 40, 70);
            mo = new Mouth(centerX, centerY, offsetX, offsetY);
 
            //рисуем НА БУФЕРЕ!:
 
            // кружочки
            circ.Draw(pen, gr, pictureBox1);
 
            // тело
            ch.Draw(gr, pen);
 
            // Рубашка
            sh.Draw(gr, pen);
 
            //Штаны
            pa.Draw(gr, pen);
 
            // Ноги
            le.Draw(gr, pen);
 
            // манжеты
            cu.Draw(gr, pen);
 
            // руки
            lha.Draw(gr, pen);
            rha.Draw(gr, pen);
 
            // глаза
            bEye.Draw(gr, pen);
            fEye.Draw(gr, pen);
 
            //рот
            mo.Draw(gr, pen);
 
            //переносим изображение с буфера на PictureBox
            pictureBox1.Image = myBitmap;
 
            // обнуляем переменные для анимации
            movX = 0;
            movY = 0;
 
            //запускаем таймер (тик опять указан на 150мс)
            timer1.Enabled = true;
 
        }
 
        //обработка тика таймера (анимация)
        private void timer1_Tick(object sender, EventArgs e)
        {
            //присваиваем значение смещения  анимации
            movX += 5;
            movY -= 2;
            if (movX > 40) // контролируем перемещение
            {
                movX = -40;
                movY = 16;
            }
 
            //задаем смещение для анимации
            setOffset(movX, movY);
 
            // опять закрашиваем фон
            gr.FillRectangle(brush, 0, 0, pictureBox1.Width, pictureBox1.Height);
 
            // аналогично рисуем картинку по частям
            // и в конце "переносим" изображение с Bitmap на PictureBox
            // кружочки
            circ.Draw(pen, gr, pictureBox1);
 
            // тело
            ch.Draw(gr, pen);
 
            // Рубашка
            sh.Draw(gr, pen);
 
            //Штаны
            pa.Draw(gr, pen);
 
            // Ноги
            le.Draw(gr, pen);
 
            // манжеты
            cu.Draw(gr, pen);
 
            // руки
            lha.Draw(gr, pen);
            rha.Draw(gr, pen);
 
            // глаза
            bEye.Draw(gr, pen);
            fEye.Draw(gr, pen);
 
            //рот
            mo.Draw(gr, pen);
 
 
            pictureBox1.Image = myBitmap;
 
        }
 
    }
}

И вот полученный результат, в котором мы избавились от мигания.

Но наш Спанч Боб получился какой-то корявенький, поэтому можно добавить что-то вроде улучшенной графики, в которой включено сглаживание и регулировка прозрачности для цвета.
Это делается добавлением строчки
gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Сразу после инициализации графики (в приведенном выше кода данная строка закомментирована)

Вот теперь уже самый последний результат

Проект прикреплен ниже

Прикрепленный файлРазмер
Skopinskiy_LessonAnimationPart2.zip70.44 кб