Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.08.26;
Скачать: [xml.tar.bz2];

Вниз

Рисование движущегося прямоугольника   Найти похожие ветки 

 
Юра   (2007-07-30 14:13) [0]

Задача: Создать движение прямоугольника.
Что сделал: Реализовал движение очень просто: стирание и рисование в новых координатах, однако при таком способе рисования происходит моргание изображения.
Вопрос: Как от него избавиться?


 
Инс ©   (2007-07-30 14:18) [1]

Вместо стирания всего, делай только стирание прямоугольника. См. режим рисования XOR или в крайнем случае можно ClipRegion-ом поиграться


 
Юра   (2007-07-30 14:24) [2]

Я и стираю только прямоугольник, когда вызываю Rectangle с теми же координатами, только цветом фона?


 
Инс ©   (2007-07-30 14:32) [3]

Тогда код приведите


 
Юра   (2007-07-30 14:37) [4]

...
//Стирание
Canvas.Pen.Color := clBtnColor;
Canvas.Rectangle(endLeft,50,endRight,300);
dec(endLeft);
//Рисование
Canvas.Pen.Color := clBlack;
Canvas.Rectangle(endLeft,50,endRight,300);
...


 
oxffff ©   (2007-07-30 14:39) [5]


> Вопрос: Как от него избавиться?


Использовать двойную буферизацию.

DoubleBuffered:=TRUE;


 
Юра   (2007-07-30 14:40) [6]

Пробовал


 
Инс ©   (2007-07-30 14:43) [7]

И с какой частотой такое рисование/стирание происходит?


 
Юра   (2007-07-30 14:45) [8]

в цикле while true do begin
           рисование/стирание
           sleep(50);
           end;
Судите о частоте.


 
oxffff ©   (2007-07-30 14:55) [9]


> Судите о частоте.


А как?


 
Юра   (2007-07-30 14:58) [10]

а вот так: смотришь на код и понимаешь какая частота.


 
Darvin ©   (2007-07-30 15:01) [11]

Рисуешь сначала на невидимой канве, а потом ВСЕ ИЗОБРАЖЕНИЕ копируешь на видимую. Плюс DoubleBuffered.


 
oxffff ©   (2007-07-30 15:04) [12]


> Юра   (30.07.07 14:58) [10]
> а вот так: смотришь на код и понимаешь какая частота.


Может вставить GetTickCount?
Вдруг получиться?


 
Юра   (2007-07-30 15:07) [13]

Darvin, пожалуйста покажи код...


 
Инс ©   (2007-07-30 15:18) [14]


> Рисуешь сначала на невидимой канве, а потом ВСЕ ИЗОБРАЖЕНИЕ
> копируешь на видимую. Плюс DoubleBuffered.

DoubleBuffered именно так и делает: рисует сначала во временный битмап, потом целиком его копирует. Плюс подавляет обработку WM_ERASEBKGND по умолчанию. Так что - масло масляное, к тому же не даст никакого эффекта. DoubleBuffered включается в работу только когда приходят сообщения WM_PAINT и WM_ERASEBKGND, а тут мы просто рисуем на контроле.

Я бы делал так:
1. Поставил бы DoubleBuffered форме
2. Рисовал бы в OnPaint
3. По таймеру, увеличивал бы циферку, означающую смещение прямоугольника, и вызывал Invalidate


 
Darvin ©   (2007-07-30 15:19) [15]

>Darvin, пожалуйста покажи код...
А сам, слабо?

var
 Bitmap : TBitmap;
 R : TRect;

begin
 Bitmap := TBitmap.Create;
 Bitmap.Height := Height;
 Bitmap.Width  := Width;
 with Bitmap.Canvas do begin
   ...
 end;

 R.Left := 0;
 R.Top := 0;
 R.Right := Width;
 R.Bottom := Height;
 Canvas.CopyRect ( R, BitMap.Canvas, R );
end;


Разжевал, в рот положил, тебе осталось проглотить ;-)


 
Darvin ©   (2007-07-30 15:23) [16]

>Инс ©   (30.07.07 15:18) [14]
>DoubleBuffered именно так и делает: рисует сначала во временный битмап, >потом целиком его копирует
Он это делает только при сбытиях WM_PAINT (при перекрытии окна и т.д.), а когда он САМ ручками двигает прямоугольник, двойная буферизация не работает


 
Инс ©   (2007-07-30 15:25) [17]


> Он это делает только при сбытиях WM_PAINT (при перекрытии
> окна и т.д.), а когда он САМ ручками двигает прямоугольник,
>  двойная буферизация не работает

Ты мой пост до конца дочитал? Я об этом говорю. А при перекрытии окна прямоугольник вообще сотрется, так как рисуется вне обработки WM_PAINT


 
DVM ©   (2007-07-30 15:51) [18]


unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls;

type
 TForm1 = class(TForm)
   Timer1: TTimer;
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure FormPaint(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
 private
   { Private declarations }
   Bmp: TBitmap;
   x: integer;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
 Bmp := TBitmap.Create;
 Bmp.Width := Width;
 Bmp.Height := Height;
 Bmp.PixelFormat := pf24bit;
 x := 0;
 Bmp.Canvas.Brush.Style := bsSolid;
 Bmp.Canvas.Brush.Color := clWhite;
 Bmp.Canvas.Pen.Color := clBlack;
 DoubleBuffered := true;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
 Bmp.Free;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
 Bmp.Canvas.FillRect(rect(0, 0, bmp.Width, bmp.Height));
 Bmp.Canvas.Rectangle(x, 0, x + 50, 50);
 inc(x, 5);
 if x > bmp.Width - 50 then x := 0;
 Canvas.Draw(0, 0, Bmp);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Form1.Invalidate;
end;

end.



 
Инс ©   (2007-07-30 15:54) [19]


> DVM ©   (30.07.07 15:51) [18]


Не, x не в FormPaint лучше инкрементировать, а в Timer1Timer. Мало ли из-за чего будет вызвана перерисовка.


 
DVM ©   (2007-07-30 15:55) [20]


> Инс ©   (30.07.07 15:54) [19]

точно!


 
Инс ©   (2007-07-30 16:00) [21]

В общем, все куда проще:

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls;

type
 TForm1 = class(TForm)
   Timer1: TTimer;
   procedure FormCreate(Sender: TObject);
   procedure Timer1Timer(Sender: TObject);
   procedure FormPaint(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

var
 x: Integer;

procedure TForm1.FormCreate(Sender: TObject);
begin
 DoubleBuffered:=true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Inc(x);
 if x > Width then
   x:=0;
 Invalidate;
end;

procedure TForm1.FormPaint(Sender: TObject);
begin
 Canvas.Rectangle(x,10,x + 100,80);
end;

end.


 
Инс ©   (2007-07-30 16:27) [22]

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

unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls;

type
 TForm1 = class(TForm)
   Timer1: TTimer;
   procedure Timer1Timer(Sender: TObject);
   procedure FormPaint(Sender: TObject);
 private
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

var
 Angle: Single;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Angle:=Angle + 2;
 Invalidate;
end;

procedure TForm1.FormPaint(Sender: TObject);
var
 p: XFORM;
begin
 SetGraphicsMode(Canvas.Handle, GM_ADVANCED);
 p.eM11 := 1;
 p.eM12 := 0;
 p.eM21 := 0;
 p.eM22 := 1;
 p.eDx  := -160;
 p.eDy  := -160;
 SetWorldTransform(Canvas.Handle, p);
 p.eM11 := sin(Angle*pi/180);
 p.eM12 := cos(Angle*pi/180);
 p.eM21 := -cos(Angle*pi/180);
 p.eM22 := sin(Angle*pi/180);
 p.eDx  := 0;
 p.eDy  := 0;
 ModifyWorldTransform(Canvas.Handle,p,MWT_RIGHTMULTIPLY);
 p.eM11 := 1;
 p.eM12 := 0;
 p.eM21 := 0;
 p.eM22 := 1;
 p.eDx  := 160;
 p.eDy  := 160;
 ModifyWorldTransform(Canvas.Handle,p,MWT_RIGHTMULTIPLY);
 Canvas.Rectangle(110,110,210,210);
end;

end.


 
Юра   (2007-07-30 17:23) [23]

Спасибо всем. :)


 
Юра   (2007-07-30 22:36) [24]

Инс, попробовал предпоследний вариант, результат тот же...


 
Юра   (2007-07-30 22:41) [25]

Работает вариант Дарвина ;)


 
Юра   (2007-07-30 23:03) [26]

А как задать фон в Bitmap? (FloodFill не работает)


 
Инс ©   (2007-07-31 00:19) [27]


> Инс, попробовал предпоследний вариант, результат тот же...

Позволь тебе не поверить ;)


 
Юра   (2007-07-31 12:25) [28]

Позволяю ;)


 
{RASkov} ©   (2007-07-31 12:47) [29]

> [26] Юра   (30.07.07 23:03)
> А как задать фон в Bitmap? (FloodFill не работает)

Меняй цвет кисти перед рисованием прямоугольника на нужный......


 
Юра   (2007-07-31 12:57) [30]

А почему все-таки при движении есть какие-то глюки уже не мерцание, а что-то не понятное, какое-то искажение изображения. Как это исправить?


 
{RASkov} ©   (2007-07-31 12:58) [31]

> [30] Юра   (31.07.07 12:57)

Что за искажения? Покажи текущий твой код...


 
Jeer ©   (2007-07-31 13:37) [32]


> Юра   (31.07.07 12:57) [30]


А ты в курсе, что на экране ты видишь оцифрованное изображение ?


 
Юра   (2007-07-31 13:56) [33]

Jeer я в курсе и что?


 
Jeer ©   (2007-07-31 18:35) [34]


> Юра   (31.07.07 13:56) [33]


То, что прямая - на самом деле не прямая, а ломанная и в процессе смещения/вращения меняется ее вид, что вполне может тобой (и не только) восприниматься как артефакт.



Страницы: 1 вся ветка

Форум: "Начинающим";
Текущий архив: 2007.08.26;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.54 MB
Время: 0.051 c
4-1173117533
Альберт
2007-03-05 20:58
2007.08.26
почему не обновляется окно?


15-1185835085
DEMP
2007-07-31 02:38
2007.08.26
ОГРОМНАЯ Проблема


15-1185433278
record
2007-07-26 11:01
2007.08.26
Поиск


2-1185985576
Ruffian
2007-08-01 20:26
2007.08.26
Генератор списков паролей


1-1181888482
JanMihail
2007-06-15 10:21
2007.08.26
Смена иконки папки под Vista





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский