Programowanie w języku Pascal » FAQ

Co zrobić aby nie skakał obraz w trybie graficznym przy animacji

Jeżeli korzysta sie z modułu graph to służą do tego komendy
Ustawienie strony aktywnej ekranu: SetActivePage(strona);
Ustawienie wizualizowanej strony  ekranu: SetVisualPage(strona);

Działają one tylko w tedy gdy zainicjowany tryb graficzny ma przynajmniej 2 strony graficzne (czyli VGAhi odpada :)-bo ma jedną).

Innym (dla mnie leprzym)  rozwiazaniem jest stworzenie bufora ekranu. Najłatwiej jest to zrobić w trybie 13h (320X200X256) poniewaz akurat rozdzielczosc 320*200=64000 pixel jest opisany jednym bajtem czyli cały ekran mieści się w jednym segmencie, a to bardzo ułatwia sprawe w pascalu. Deklarujemy bufor.

var bufor:array[1..64000] of byte;

Załóżmy ze procedura stawiania pixla jest (kompatybilnie z graph.tpu) putpixel(x,y,kolor), zatem nasza procedura stawiająca pixel w naszym buforze ekranu wygląda następująco:

Procedure PixelBufor(x,y:word;kolor:byte);
begin
bufor[320*y+x]:=kolor;
end;

Oczywiście na ekranie nie ma tego punktu jest on w naszym wirtualnym ekranie wiec trzeba odswierzac (czyli wszystkie punkty na ekranie zamalowac na odpowiednie kolory punktów w buforze ekranu).  Procedurka moze wygladac tak:

Procedure Odswiez;
var i,j:integer;
begin
for i:=1 to 320 do
 begin
 for j:=1 to 200 do
   begin
   putpixel(i,j,bufor[320*j+i]);
   end;
 end;
end;

Opisałem najważniejsze , można sie pobawic i w zależności od potrzeb wyprodukować inne procedury czy też funkcje bazujące na tym buforze

8 komentarzy

movax13h 2006-11-25 11:58

W BGI najlepiej po prostu wczytać obraz Procedurą GetImage (dobrze zapamiętać też kilka pikseli obok obrazka -takich czarnych bez rysunku) i wyświetlać PutImage ale blisko siebie albo zamiast blisko siebie podzielić obraz na kwadraciki i je zastępować innymi. Ma to dużo wad. Za to w module graph.

Zamieszczam link ze swoją starą grą na bazie modułu graph, z animacją bez migotania. Jest to popularna dżdżownica, zajmuje 199KB. Jest razem z kodem źródłowym, ale proszę go nie komentować - to było dawno :)  :

http://www.programowanie.vsz.p[...]anie/download/dzdzowniczka.rar

PoOm 2006-04-25 10:35

niech ktos napisze jak w BGI zrobic animacje bez "migania" bedzie dobry

ŁF 2004-02-27 00:53

Skalniak: Ty chyba nie rozumiesz, co się do ciebie mówi. sformatuj kod!! a delay nie ma nic wspólnego z synchronizacją z monitorem:

procedure sync; assembler;
asm
  mov dx,03DAh
@1:
  in al,dx
  test al,1000b
  jz @1
end;
- tak się to robi, chłopcze :-P

Milka: movsw jeszcze szybciej, a najszybciej movsd (owszem, movsd pójdzie w Turbo Pascalu, patrz moduł tcrt).

AklimX 2004-02-23 13:51

ta wskazówka to lipa :D
tylko trochę pomaga, bo można np. użyć procedury asm'a movsb(w) i działa wiele szybciej.
Poza tym jak coś piszesz to optymalizacja mile widziana (mnożenie razy 320 byś się wstydził <fe>)

skalniak 2004-02-23 08:55

ŁF - to sie sprawdza a pause to sobie Delay wklep - nic trudnego

ŁF 2004-02-23 02:18

aha - można (łatwo) wyłapać moment rozpoczęcia odświeżania ekranu i wtedy rysować - inaczej samo buforowanie nie pomoże. w module tcrt, który siedzi gdzieś na 4p, jest takowa procedurka, pauzująca program do momentu rozpoczęcia odświeżania ekranu.

ŁF 2004-02-23 02:15

brak formatowania kodu, brak wcięć, błędy ortograficzne i nie tylko - popraw to. a procedura Odswiez mogła by być dużo bardziej optymalna - wystarczy zamiast całego jej ciała coś takiego:
move(bufor,mem[$A000:0],64000);

AnteQ 2007-07-03 10:17

Istnieje coś takiego jak powrót pionowy monitora :)
To można wykorzystać do usunięcia efektu migotania:
1.Tworzymy bufor roboczy.
2.Rysujemy w nim klatkę animacji.
3.Czekamy na powrót pionowy (bardzo dobrą procedurę napisał wam ŁF),
4.Szybciutko kopiujemy bufor roboczy do bufora ekranu :),
5.Jesteśmy happy.

A propos pkt 3. i procedurki pana ŁF. Jeżeli chcecie wyeliminować migotanie w 100% możecie jeszcze dodać pare linijek. Niestety - wiąże się to z lekkim spowolnieniem wykonywania animacji:

procedure powrotPionowy;
begin
 asm
  mov dx, 03dah           
@jest:            {czekanie konca obecnego powrotu pionowego}
  in  al, dx             
  test al, 00001000b     
  jnz @jest      
 
@nie_ma:        {czekanie poczatku powrotu pionowego}
  in al, dx            
  test al, 00001000b    
  jz @nie_ma      
 end;
end;