|

Grundlagen der Grafikprogrammierung - Teil 10 - by Delax
Tach!
Dieses Mal machen wir einen lockeren Teil und binden einfach nur unsere bisherigen Prozeduren in eine eigene Unit. Wieso das? Hauptsächlich der Übersicht wegen. Also auf!
Was ist eine Unit überhaupt? Eine Unit ist eine Art "Prozeduren-Sammlung". Einige Units kennt ihr schon: Windows z.B. - das sind nämlich genau jene, die ihr im Programmkopf einbindet. Sie enthalten lauter kleine Funktionen und Prozeduren, die wir dann von unserem Programm aus nutzen können.
Dennoch können wir nicht einfach "Unit" über unsere Prozeduren schreiben und gut ist. Eine Unit hat einen etwas anderen Aufbau als ein normales Pascal Programm. Eine leere Unit sieht so aus:
UNIT NAME;
INTERFACE
USES DATEINAME;
VAR VARIABLEN;
CONST KONSTANTEN;
IMPLEMENTATION
END.
Also als erstes wird der Name der Unit angegeben. Dieser muß identisch mit dem Dateinamen der abgespeicherten Unit sein. Wir nennen unsere mal "Toolbox". Dann im INTERFACE stehen alle öffentlich zugänglichen Daten. Jede Variable und Konstante, die hier angegeben wird ist automatisch global, d.h. alle Programme, die die Unit einbinden können sie nutzen. Umgekehrt ist es aber nicht so einfach möglich das eine Unit eine Variable eures Hauptprogrammes nutzt.
Im IMPLEMENTATION Teil steht all das, was intern in der Unit passiert - also auch die eigentlichen Prozeduren und Funktionen. Ohne große Vorrede nun hier unsere Unit "Toolbox":
UNIT toolbox;
INTERFACE
USES Windows, Sysutils;
VAR MaxX, MaxY : LongInt;
PROCEDURE PutPixel(destiny : pointer; x,y : longint; color1, color2 : byte);
PROCEDURE Line(destiny : pointer; x1,y1,x2,y2 : longint; color1, color2 : byte);
PROCEDURE Circle(destiny : pointer; x0,y0,radius : longint; color1, color2 : byte);
IMPLEMENTATION
PROCEDURE PutPixel(destiny : pointer; x,y : longint; color1, color2 : byte);
BEGIN
if (x<0) or (x>MaxX) or (y<0) or (y>MaxY) then exit;
ASM
mov edi,destiny
mov eax,x
mov ebx,2
imul ebx
add edi,eax
mov eax,MaxX
imul ebx
imul y
add edi,eax
mov al,color1
mov [edi],al
add edi,1
mov al,color2
mov [edi],al
END;
END;
PROCEDURE Line(destiny : pointer; x1,y1,x2,y2 : longint; color1, color2 : byte);
Var dx,dy,sx,sy,k : longint;
BEGIN
sx:=1;
sy:=1;
dx:=x2-x1;
if dx<0 then begin
dx:=-dx;
sx:=-1;
end;
dy:=y2-y1;
if dy<0 then begin
dy:=-dy;
sy:=-1;
end;
k:=-(dx shr 1);
PutPixel(destiny,x1,y1,color1, color2);
while (x1<>x2) or (y1<>y2) do
if (k>=0) and (y1<>y2) then begin
inc(y1,sy);
dec(k,dx);
PutPixel(destiny,x1,y1,color1, color2);
end
else begin
inc(x1,sx);
inc(k,dy);
PutPixel(destiny,x1,y1,color1, color2);
end;
END;
PROCEDURE Circle(destiny : pointer; x0,y0,radius : longint; color1, color2 : byte);
Var x,y,p : longint;
BEGIN
x:=0;
y:=-radius;
p:=y shl 1+3;
while x<=-y do begin
PutPixel(destiny,x0+x,y0+y,color1, color2);
PutPixel(destiny,x0-x,y0+y,color1, color2);
PutPixel(destiny,x0+x,y0-y,color1, color2);
PutPixel(destiny,x0-x,y0-y,color1, color2);
PutPixel(destiny,x0+y,y0+x,color1, color2);
PutPixel(destiny,x0-y,y0+x,color1, color2);
PutPixel(destiny,x0+y,y0-x,color1, color2);
PutPixel(destiny,x0-y,y0-x,color1, color2);
if p>=0 then begin
inc(y);
inc(p,(x+y)shl 2+6);
end else inc(p,x shl 2+6);
inc(x);
end;
END;
end.
Hier als Datei zum download
Hand hoch Leute, wem fällt etwas auf? Da oben stehen 2 Variablen namens MaxX und MaxY. Diese brauchen wir ja für unsere PutPixel Routine zum multiplizieren. Allerdings brauchen wir sie auch im Hauptprogramm, um die fenstergröße zu definieren. Da man aber Variablen vom Hauptprogramm schlecht in Units verwenden kann, deklarieren wir sie in der Unit und unser Programm kann sie auch nutzen - wir dürfen nur nicht vergessen sie am Anfang mit Werten zu versorgen!
Die Frage kommt da zwangsläufig auf: wieso sparen wir uns nicht die Angabe der Auflösung und nageln sie auf 640x480 fest? Vorteil: wir könnten uns das deklarieren sparen und außerdem: wenn wir genau den Multiplikator in der PutPixel Prozedur kennen würden könnten wir Binary Shifting nutzen, was sehr viel schneller wäre. Die Antwort lautet: es IST eine Überlegung wert, aber die einstellbare Auflösung hat auch Vorteile: man kann den User entscheiden lassen, welche er gerne hätte - einfach nur ein Auswahlmenu davor basteln.
Im Endeffekt ist das eine Zielfrage: Was will man machen? Genügen einem die 640x460 und will man den Geschwindigkeitsvorteil, dann sollte man die Auflösung fixieren, ansonsten sollte man sie lieber variabel halten.
Das nächste Mal wird etwas bewegt ;)
Delax/ Sundancer Inc.
[delax@sundancerinc.de]
Back to previous page
|