Podwójne buforowanie

gacek999

Załóżmy, że chcesz zaprogramować poruszający się prostokąt wzdłuż ekranu:

const
  Szerokosc = 20;
  Wysokosc = 20;
 
var
  Pozycja: Integer;
 
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Canvas.Pen.Color := clWhite;
  Canvas.Brush.Color := clWhite;
  Canvas.Rectangle(Pozycja, 100, Pozycja + Szerokosc, 100 + Wysokosc);
  Pozycja := Pozycja + 1;
end;

W rezultacie program będzie rysował grubą linię po środku ekranu
Dobrym sposobem będzie rysowanie linii w kolorze tla za kwadratem.

  Canvas.MoveTo(Pozycja - 1, 100);
  Canvas.LineTo(Pozycja - 1 , 100 + Wysokosc);

Ale co zrobić, gdy animacja będzie zawierała wiele rożnych figur, a tło nie będzie w postaci jednolitego koloru tylko bitmapy?

Własnie w takich momentach warto wykorzystać "Double Buffering"
Wystarczy zadeklarować dodatkową zmienną TCanvas

var
  Buf: TCanvas;

i tło jako bitmapę:

  Bitmap: TBitmap;

Inicjalizujemy Bufor:

  Buf := TBitmap.Create(Self);
  Buf.Width := Form1.Canvas.Width;
  Buf.Height := Form1.Canvas.Height;

a nastepnie wczytujemy tlo:

  Bitmap := TBitmap.Create;
  Bitmap.LoadFromFile('obrazek.bmp');

wtedy procedura wygląda tak:

procedure TForm1.Timer1Timer(Sender: TObject);
var
  l: Integer;
begin
  Buf.Draw(0, 0, Bitmap); {rysujemy tlo}
  Buf.Pen.Color := clWhite;
  Buf.Brush.Color := clWhite;
  Buf.Rectangle(Pozycja, 100, Pozycja + Szerokosc, 100 + Wysokosc);
  Pozycja := Pozycja + 1;
  {kopiujemy Buf na ekran}
  Form1.Canvas.CopyRect(Form1.Canvas.ClipRect, Buf, Buf.ClipRect);
end;

W efekcie prostokąt porusza się bez migotania i na tle które wczytaliśmy.

Zasada jest prosta. Pierw rysujemy całą animację w pamięci (zmienna Buf), a następnie kopiujemy ją na ekran (procedure CopyRect) , co daje efekt płynności i wrażenia, że całość rysuje się naraz.

5 komentarzy

A nie lepiej tak:
DoubleBuffered := True;

bez jaj.... ale ten artykuł jest strasznie pokręcony ... i wyskakują błędy. Może jestem początkujący ale na necie znalazłem banalne rozwiązanie ... i piszę je dla tych co się załamali usiłując przepisać ten kod:
Problem: mruganie obrazka podczas przesuwania po formie
Rozwiązanie: Forma > OnCreate > wklepać ..... DoubleBuffered := True

Nie ma prawa migać ... Pozdrawiam

Pokolorowanie składni. Odrazu zachęca do przeczytania.

Juz mam ok.

//****
// Tworzymy bufor dla obrazka
//****
backgroundImage := TImage.Create( Self );
backgroundCanvas := TCanvas.Create;

//zaladuj obrazek
backgroundImage.Picture.LoadFromFile('obrazek.bmp');

Warto spojrzeć, jak to jest zrobione w demie Delphi - Demos\EarthPng\

Tu mi sie wywala, ze argumenty złe:
Buf := TBitmap.Create(Self); <------- [Error] ClockZ.pas(185): Too many actual parameters

Co mam zrobić?