Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.53/19: Рейтинг темы: голосов - 19, средняя оценка - 4.53
1 / 1 / 0
Регистрация: 17.02.2011
Сообщений: 17
1

Как убрать моргание при реализации анимации?

22.04.2011, 05:20. Просмотров 3675. Ответов 7
Метки нет (Все метки)

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
 
namespace Compound_Pendulum
{
    class Pendulum
    {
        public int x, y; // координаты шарика
        public int x0, y0; // координаты подвеса
        public int q; // угол отклонения маятника от равновесия
        public int a; // начальный угол отклонения маятника
        public double m; // масса маятника
        public double h; // расстояние от точки подвеса до центра тяжести маятника
        public double r; // радиус инерции относительно оси, проходящей через центр тяжести
        public double g; // ускорение свободного падения
        public double l; // приведённая длина физического маятника
        public Color BorderColor; // цвет контура
        public Color BallColor; // цвет шарика
        public PictureBox pictureBox; // поверхность рисования
        public int BallSize; // размер шарика
        public int MaxSize; // максимальный размер
        public double Radius;
 
        public Pendulum(int a, double m, double h, double g, Color BallColor, PictureBox pictureBox, int MaxSize)
        {
            this.a = a;
            this.m = m;
            this.h = h;
            this.g = g;
            this.BorderColor = Color.Black;
            this.BallColor = BallColor;
            this.pictureBox = pictureBox;
            this.MaxSize = MaxSize;
            BallSize = Convert.ToInt32(m);
            pictureBox.BackColor = Color.PeachPuff;
            Radius = h;
            x = (int)Math.Round(Radius * Math.Cos(Math.PI * a / 180) + MaxSize / 2) - BallSize / 2;
            y = (int)Math.Round(MaxSize / 2 - Radius * Math.Sin(Math.PI * a / 180)) - BallSize / 2;
            x0 = MaxSize / 2;
            y0 = MaxSize / 2;
            PendulumShow(pictureBox);
        }
 
        public void PendulumShow(PictureBox pictureBox)
        {
            Pen borderPen = new Pen(BorderColor, 2);
            SolidBrush limeSolidBrush = new SolidBrush(Color.Lime);
            SolidBrush redSolidBrush = new SolidBrush(Color.Red);
            Graphics graphics = pictureBox.CreateGraphics();
            graphics.DrawLine(borderPen, x0, y0, x + BallSize / 2, y + BallSize / 2);
            graphics.DrawEllipse(borderPen, x, y, BallSize, BallSize);
            graphics.FillEllipse(limeSolidBrush, x, y, BallSize, BallSize);
            graphics.DrawEllipse(borderPen, MaxSize / 2 - 10, MaxSize / 2 - 10, MaxSize / 25, MaxSize / 25);
            graphics.FillEllipse(redSolidBrush, MaxSize / 2 - 10, MaxSize / 2 - 10, MaxSize / 25, MaxSize / 25);
        }
 
        public void PendulumHide(PictureBox pictureBox)
        {
            Pen borderPen = new Pen(pictureBox.BackColor, 2);
            SolidBrush redSolidBrush = new SolidBrush(pictureBox.BackColor);
            Graphics graphics = pictureBox.CreateGraphics();
            graphics.DrawLine(borderPen, x0, y0, x + BallSize / 2, y + BallSize / 2);
            graphics.DrawEllipse(borderPen, x, y, BallSize, BallSize);
            graphics.FillEllipse(redSolidBrush, x, y, BallSize, BallSize);
        }
 
        public void PendulumMove()
        {
            PendulumHide(pictureBox);
            x = (int)Math.Round(Radius * Math.Cos(Math.PI * a / 180) + MaxSize / 2) - BallSize / 2;
            y = (int)Math.Round(MaxSize / 2 - Radius * Math.Sin(Math.PI * a / 180)) - BallSize / 2;
            PendulumShow(pictureBox);
        }
    }
}
Движение реализовано через таймер. Но у меня при перерисовке сильно моргают перерисовываемые объекты. В таймере стоит интервал 1 мс. Я так понимаю что изображение не успевает быстро перерисовываться, из-за этого видно моргание. Компьютер с дискретной видеокартой.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.04.2011, 05:20
Ответы с готовыми решениями:

Убрать моргание при движении картинки
Здравствуйте, сегодня у меня 2 вопроса. Когда картинка движется, то всё начинает моргать, при чём...

Как убрать лаги анимации при мультиплеере в unity3d?
Как убрать лаги анимации при мультиплеере в unity3d ? То есть создаю сервер, подключаюсь клиентом,...

что за полоски слева на слайде при проигрывании анимации и как их убрать?
Не знаю как убрать этот глюк. Слева тонкие белые полоски. И это не чать фона это глюк.Помогите....

Как в Image отрубить моргание при рисовании?
Как в Image отрубить моргание при рисовании? К примеру в VB можно было установить свойство...

7
6212 / 3513 / 899
Регистрация: 28.10.2010
Сообщений: 5,926
22.04.2011, 08:43 2
Рисовать в нескольких потоках. И задержку больше поставить.
0
Заблокирован
22.04.2011, 08:44 3
1 мс - сильно часто, поставте ~1000/24(24 кадра в секунду, зачем чаще?)
возможно поможет в свойствах формы
C#
1
            this.DoubleBuffered = true;
если не станет программа вылетать, поставьте в функциях
C#
1
graphics.Dispose();
1
1 / 1 / 0
Регистрация: 17.02.2011
Сообщений: 17
22.04.2011, 10:36  [ТС] 4
Цитата Сообщение от Петррр Посмотреть сообщение
Рисовать в нескольких потоках. И задержку больше поставить.
Можете поподробнее, пожалуйста? Я не знаю как это сделать.

Цитата Сообщение от Dzhej-Dzhej Посмотреть сообщение
1 мс - сильно часто, поставте ~1000/24(24 кадра в секунду, зачем чаще?)
возможно поможет в свойствах формы
C#
1
            this.DoubleBuffered = true;
если не станет программа вылетать, поставьте в функциях
C#
1
graphics.Dispose();
Вроде чуть-чуть получше стало, но все равно сильно мерцает!
1
1300 / 973 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
22.04.2011, 12:03 5
не пользуйся CreateGraphics!! отрисовка должна происходить тогда и только тогда, когда контрол это позволяет

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
 
namespace Compound_Pendulum {
    public class Pendulum {
        private int _x, _y; // координаты шарика
        private int _x0, _y0; // координаты подвеса
        //private int q; // угол отклонения маятника от равновесия
        private int _a; // начальный угол отклонения маятника
        private double _m; // масса маятника
        private double _h; // расстояние от точки подвеса до центра тяжести маятника
        //private double r; // радиус инерции относительно оси, проходящей через центр тяжести
        private double g; // ускорение свободного падения
        //private double l; // приведённая длина физического маятника
 
        private Pen _borderPen = new Pen(Color.Black, 2);
 
        private Color _ballColor; // цвет шарика
        private double _radius; // радиус
        private int _ballSize; // размер шарика
        private int _maxSize; // максимальный размер
 
        public Pendulum(int a, int m, double h, double g, Color BallColor, int MaxSize) {
            this._a = a;
            this._m = m;
            this._h = h;
            this.g = g;
            this._ballColor = BallColor;
            this._maxSize = MaxSize;
            _ballSize = m;
            _radius = h;
            _x = (int)Math.Round(_radius * Math.Cos(Math.PI * a / 180) + MaxSize / 2) - _ballSize / 2;
            _y = (int)Math.Round(MaxSize / 2 - _radius * Math.Sin(Math.PI * a / 180)) - _ballSize / 2;
            _x0 = MaxSize / 2;
            _y0 = MaxSize / 2;
        }
 
        public void Draw(Graphics graphics) {
            graphics.DrawLine(_borderPen, _x0, _y0, _x + _ballSize / 2, _y + _ballSize / 2);
            graphics.DrawEllipse(_borderPen, _x, _y, _ballSize, _ballSize);
            graphics.FillEllipse(Brushes.Lime, _x, _y, _ballSize, _ballSize);
            graphics.DrawEllipse(_borderPen, _maxSize / 2 - 10, _maxSize / 2 - 10, _maxSize / 25, _maxSize / 25);
            graphics.FillEllipse(Brushes.Red, _maxSize / 2 - 10, _maxSize / 2 - 10, _maxSize / 25, _maxSize / 25);
        }
 
        public void Move() {
            _x = (int)Math.Round(_radius * Math.Cos(Math.PI * _a / 180) + _maxSize / 2) - _ballSize / 2;
            _y = (int)Math.Round(_maxSize / 2 - _radius * Math.Sin(Math.PI * _a / 180)) - _ballSize / 2;
        }
    }
}
пример вызова
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
using System;
using System.Drawing;
using System.Windows.Forms;
 
namespace Compound_Pendulum {
    public partial class Form1 : Form {
 
        private Timer _timer;
        private Pendulum _pendulum;
        private PictureBox _pictureBox;
 
        public Form1() {
            this.SuspendLayout();
            _pictureBox = new PictureBox();
            _pictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
            _pictureBox.BackColor = Color.BlanchedAlmond;
 
            _timer = new Timer();
            _timer.Interval = 50;
            _timer.Enabled = true;
 
            Controls.Add(this._pictureBox);
            this.ResumeLayout(false);
 
            _pendulum = new Pendulum(45, 1, 50, 9.81, Color.Green, 200);
 
            _pictureBox.Paint += new PaintEventHandler(_pictureBox_Paint);
            _timer.Tick += new System.EventHandler(this.timer1_Tick);
        }
 
        private void _pictureBox_Paint(object sender, PaintEventArgs e) {
            _pendulum.Draw(e.Graphics);
        }
 
        private void timer1_Tick(object sender, EventArgs e) {
            _pendulum.Move();
            _pictureBox.Invalidate();
        }
 
 
 
    }
}
а вот тут можно подумать, почему у тебя не работает метод Move: всегда X и Y одинаковы, _а не меняется. И отрисовка (само расположение объектов) неправильна

Добавлено через 2 минуты
аххах, у тебя, наверное "а" (и другие переменные) меняется извне класса)) это очень плохо с точки зрения ООП. залатай метод Move или сделай еще один метод на пересчёт координат

Добавлено через 3 минуты
короче, самое главное - передавать объект graphics в отрисовки из обработчика отрисови pictureBox
2
1 / 1 / 0
Регистрация: 17.02.2011
Сообщений: 17
22.04.2011, 13:02  [ТС] 6
Спасибо огромное за советы, но прошу объяснить кое-что.

Цитата Сообщение от Mikant Посмотреть сообщение
не пользуйся CreateGraphics!! отрисовка должна происходить тогда и только тогда, когда контрол это позволяет
Чем же так плох CreateGraphics?

Цитата Сообщение от Mikant Посмотреть сообщение
Добавлено через 2 минуты
аххах, у тебя, наверное "а" (и другие переменные) меняется извне класса)) это очень плохо с точки зрения ООП. залатай метод Move или сделай еще один метод на пересчёт координат
Я меняю начальные параметры маятника с главной формы. Это не рационально что-ли?

Цитата Сообщение от Mikant Посмотреть сообщение
Добавлено через 3 минуты
короче, самое главное - передавать объект graphics в отрисовки из обработчика отрисови pictureBox
В этом была причина мерцания?

Заранее спасибо!
0
Почетный модератор
Эксперт .NET
8668 / 3620 / 404
Регистрация: 14.06.2010
Сообщений: 4,513
Записей в блоге: 9
23.04.2011, 02:34 7
Цитата Сообщение от slakho90 Посмотреть сообщение
Чем же так плох CreateGraphics?
Тем что контекст устройства (на котором всё это дело рисуется, в данном случае форма) постоянно обновляется. Вызывая CreateGraphics ты получаешь контекст устройства в текущий момент, рисовать ты на нём можешь, но при первом обновлении он будет затерт, и тут уже никакая двойная буферизация не поможет. В таких случаях (когда нужно частое обновление) используют Bitmap как буфер, сначала рисуют на нём, а потом выводят его, тогда косяков в виде мерцаний не будет (если обновление не сверх быстрое).

Не по теме:

Мне, если честно, очень интересно откуда все новички вычитывают данный метод, руки бы автору книги/статьи оторвать за это. После этого всегда идут вопросы: "а почему мерцает?" или "почему ничего не видно?".

2
1300 / 973 / 127
Регистрация: 08.12.2009
Сообщений: 1,299
24.04.2011, 01:28 8
1) SSTREGG, ты не совсем корректен, ведь, уважаемый, можно же 3 раза воззвав к устройству нарисовать 3 разные вещи не затирая предыдущих. а, запретив при этом локальные обновления, вообще творить черт знает что... но в целом ты прав. (по поводу отрывания рук: найдешь - помогу=) )
2) да. это нарушение одного из трех столпов ООП - инкапсуляции. см. хотя бы вики (зы. тут имеется ввиду, что с главной формы менять - это нормально, но императивно менять состояние удаленного объекта строго запрещено)
3) из-за этого, в этом случае, в первую очередь!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.04.2011, 01:28

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Как убрать след от анимации
program q1; uses crt, GraphABC; var x: integer; begin lockdrawing; ...

Как убрать паузу между исполнением одной и той же анимации, @keyframes
Хочу, что бы у меня при наведении на кнопку стрелочка крутилась в infinity, но она почему то делает...

Кнопка для реализации анимации
Вообщем, пишу игру для Oculus Quest , есть кнопка в канвасе, есть луч реагирующий на неё, нужно...

Проблема с реализации анимации в CSS
Доброго времени суток, нужна ваша помощь. Пытаюсь реализовать анимацию появления блока при клике....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.