GrafikProgrammierung in Pascal - Teil 2 Zuallererst ne ganz wichtige Mitteilung: Ich hab vergessen, die Compiler- "Schalter" zum FPK anzugeben. Deswegen hier und jetzt der "richtige" Aufruf zum Start meiner Progs: ppc386 -Scg -Xs -OG5 x.pas Heute also mein Beitrag zum Thema: Linien und Kreise... Zu Recht wird sich der eine oder andere fragen: Wieso macht der Kerl eigentlich all die Funktionen, die eh schon bei Pascal dabei sind ?? Ganz einfach: Erstmal lernt man dabei die Funktionsweise "einfacherer" Grafik-Spielereien und kann dann spter auf diesem Wissen aufbauen. Auerdem sind diese Routinen um ein Vielfaches schneller als die Beigelegten. Das mag im Pentium II Zeitalter vielleicht nicht mehr eine ganz so groe Rolle spielen, aber schliesslich gilts auch schwchere Rechner optimal zu nutzen. Jetze aber zu den Routinen... Wer in Mathe aufgepasst hat, wei, das eine Linie in folgender Form beschrieben werden kann: Y=M*X+C. Dabei gibt M die Steigung an und C den "Schnittpunkt" mit der Y-Achse (Der X-Wert is dabei logischerweise 0). Will man nun darauf aufbauend eine Linie zeichnen, wrde man also die Steigung mit den 2 Koordinaten ausrechnen: M=(y2-y1)/(x2-x1). Jetzt beginnt man damit an x1/y1 einen Punkt zu setzen. Jetzt nhert man x1 immer in Einserschritten an x2 an (+1 bzw.-1) und rechnet mit obiger Formel die Y-Koordinate aus. Das ganze Spielchen zieht sich dann solange bis x1 gleich x2 wird. Das Hauptmanko dabei is aber folgendes: Erstma mu man mit Kommazahlen arbeiten (langsam), dann mu das alles auch noch in "normale" Zahlen umgerechnet werden, weil nen Punkt an 1,53/100,6 zu setzen packt der PC nich ganz... Wenn das Alles also ohne Kommazahlen gehen soll, brauchen wir nen komplett anderen Ansatz. Ebendiesen hat ein Herr Bresenham geliefert. Seine Idee sieht so aus: Er berechnet grob gesagt die Anzahl von Punkten, die am Stck in X-Richtung gezeichnet werden knnen. Anschliessend wird y um 1 erhht/erniedrigt und das Spielchen wird wiederholt. Eine detailiertere Auflistung erspar ich euch lieber... PROCEDURE Line(destiny : pointer; x1,y1,x2,y2 : longint; col : byte); Var dx,dy,sx,sy,k : longint; BEGIN sx:=1; sy:=1; dx:=x2-x1; { X-Steigung } if dx<0 then begin { Wenn negativ, dann nich X erhhen sondern erniedrigen (mit SX) } dx:=-dx; sx:=-1; end; dy:=y2-y1; { Y-Steigung } if dy<0 then begin { s.o } dy:=-dy; sy:=-1; end; k:=-(dx shr 1); { dx shr 1 = dx div 2 } pixel(destiny,x1,y1,col); { 1.Pixel setzen } while (x1<>x2) or (y1<>y2) do { Schleife von x1 nach x2 / y1 nach y2 } if (k>=0) and (y1<>y2) then begin { Knnen noch Pixel in x-Richtung gesetzt werden? } inc(y1,sy); { Nope! Also y erhhen/erniedrigen } dec(k,dx); pixel(destiny,x1,y1,col); end else begin inc(x1,sx); { Yup! Also x erhhen/erniedrigen } inc(k,dy); pixel(destiny,x1,y1,col); end; END; Jetzt der zweite Brocken: Kreise... Und wieder gibts den einfachen (langsamen) Ansatz und nen schnellen. Der einfache beruht darauf, mit Sinus/Cosinus und Pi die Koordinaten der Punkte herauszufinden. Problem: Sinus/Cosinus is lahm. Auerdem wiedermal Hantieren mit Kommazahlen (auch lahm)... Also nun der schnelle Ansatz (auch von Bresenham): Er berechnet nur ein Achtel des Kreises und setzt den Rest der Pixel durch Spiegelungen,etc. Der Kreis selbst wird dabei als eine Art "mutierende" Linie betrachtet, soll heissen die Steigung dieser Linie verndert sich whrend des Malens. Die Steigungen erhlt man dadurch, das man Tangenten an die jeweiligen Punkte anlegt. Das ganze noch optimiert und gut durchdacht sieht dann so aus: PROCEDURE Circle(destiny : pointer; x0,y0,radius : longint; col : byte); Var x,y,p : longint; BEGIN x:=0; y:=-radius; p:=y shl 1+3; { y shl 1 = y*2 } while x<=-y do begin pixel(destiny,x0+x,y0+y,col); { Die angesprochenen Spiegelungen } pixel(destiny,x0-x,y0+y,col); pixel(destiny,x0+x,y0-y,col); pixel(destiny,x0-x,y0-y,col); pixel(destiny,x0+y,y0+x,col); pixel(destiny,x0-y,y0+x,col); pixel(destiny,x0+y,y0-x,col); pixel(destiny,x0-y,y0-x,col); if p>=0 then begin inc(y); inc(p,(x+y)shl 2+6); { obiges 3 bzw. 6 dienen zur Schnheits-Korrektur } end else inc(p,x shl 2+6); { keine Ahnung wie Bresenham gerade auf diese Zahlen kam } inc(x); end; END; Nchstes Mal wirds wohl Sprites (ihr wisst schon: rechteckige Bildbereiche, die "durchsichtig" sind (Bsp. Panzer/Gebude/Mnnchen in Command & Conquer) geben und ne ordentliche Struktur um sie auch verwalten zu knnen... See ya next time... Carsten aka Toxic Avenger/Ainc.