home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / spezial / 06 / sprite.doc < prev   
Encoding:
Text File  |  1988-10-18  |  11.1 KB  |  230 lines

  1.                    Sprite-Editor in Turbo-Pascal
  2.  
  3. Sprites, benutzerdefinierte Zeichen also, sind vielen sicherlich
  4. noch aus den Tagen der Heim-Computer bekannt. Auch mit modernen
  5. Programmiersprachen lassen sich diese Gebilde auf dem Bildschirm
  6. darstellen, welche Befehle dazu nötig sind und wie man sich die
  7. Arbeit, diese Sprites zu gestalten, wesentlich erleichtern können,
  8. soll Ihnen der folgende Beitrag am Beispiel von Turbo-Pascal 4.0
  9. aufzeigen. Verwendet wird dabei eine CGA-Graphik-Karte in der 320
  10. *200-Punkte-Auflösung (4 Farben), jedoch wurde versucht, das
  11. Programm so allgemein wie möglich zu halten, so daß es mit
  12. möglichst wenig Aufwand auch an andere Graphik-Karten bzw.
  13. Auflösungen angepasst werden kann.
  14.  
  15. Turbo 4.0 stellt ja in der UNIT Graph eine beachtliche Menge an
  16. Graphik-Befehlen zur Verfügung. Die UNIT wurde leider nach
  17. Abschluss des Handbuches nochmals überarbeitet, so daß man sich vor
  18. dem Arbeiten hiermit auf jeden Fall das File "Graph.DOC", das
  19. wesentliche Ergänzungen und Erläuterungen enthält, ausdrucken
  20. lassen sollte. Etwas leichter tun sich sich hier die Besitzer des
  21. zusätzlichen Handbuches (Addendum) zu Turbo-C, V.1.5, in dem die im
  22. Prinzip gleichen Graphik-Befehle übersichtlich zusammengefasst
  23. sind. BGI, das Borland-Graphics-Interface, ist ja gleichermassen
  24. bei Turbo-C und Turbo-Pascal vorhanden, lediglich der Turbo-Basic-
  25. Compiler benutzt die zum GW-Basic kompatiblen Graphik-Befehle.
  26.  
  27.  
  28. Betrachten wir zunächst die Befehle, die uns die UNIT Graph für die
  29. Sprite-Gestaltung und -Bewegung zur Verfügung stellt :
  30.  
  31. - mit GetImage (links, oben, rechts, unten, Puffer) wird ein
  32.   rechteckiger Bildausschnitt in eine Puffervariable kopiert,
  33. - mit PutImage (x, y, Puffer, Operand) wird der Inhalt einer
  34.   Puffervariablen in einen rechteckigen Bildausschnitt kopiert,
  35.   wobei logische Verknüpfungen mit dem Inhalt dieses Ausschnitts
  36.   über "operand" möglich sind.
  37. -  mit ImageSize (links, oben, rechts, unten) wird die Grösse der
  38.   Puffervariablen bestimmt.
  39.  
  40. Viel ist das ja nun gerade nicht, und zu allem Überfluss ist die
  41. Puffervariable auch noch vom Typ POINTER, d.h. ein untypisierter
  42. Vertreter der berühmt-berüchtigten Zeiger. Ungünstig ist auch, daß
  43. jeder Sprite erst auf dem Bildschirm gezeichnet und "eingefangen"
  44. werden muss. Das könnte man zwar mit einem "Programm-Vorspann"
  45. lösen, in dem alle verwendeten Figuren dargestellt und so nebenbei
  46. mit GetImage erfasst werden, bei vielen, ev. noch aufwendigen
  47. Figuren kann das aber auf Dauer auch ganz schön nerven. Abgesehen
  48. davon, daß bei der Programmentwicklung jede Figur recht mühsam
  49. pixelweise am Bildschirm entworfen werden muß, muß das Programm
  50. alle Befehle zum Zeichnen der Figuren enthalten, was auch einiges
  51. an Speicherplatz kosten kann. Viel einfacher wäre doch, die
  52. fertigen Figuren aus einer Datei zu laden ! Nehmen wir also
  53. zunächst einmal die Puffervariable unter die Lupe und sehen, was
  54. sich damit alles anstellen läßt.
  55.  
  56. Welche Daten enthält ein Sprite-Pointer ? Der Pointer selbst
  57. enthält bekanntlich nur eine Speicher-Adresse (er zeigt auf diese
  58. Speicherstelle) und ab dieser Adresse sind die maßgebenden Werte
  59. abgelegt. Nicht ganz einfach also, hier direkt den Pointer zu
  60. "knacken", mit WRITE können die Werte auch nicht ausgegeben werden,
  61. also überlisten wir den Zeiger und speichern ihn ganz einfach ab.
  62. Hierzu dient die folgende Function :
  63.  
  64. LISTING 1 :
  65.  
  66. (*-----------------------------------------------*)
  67. FUNCTION SaveGraphikScreen (Links, Oben, Rechts, Unten : INTEGER;
  68.                             DateiName : STRING) : INTEGER;
  69.  
  70. VAR   BildGroesse : INTEGER;
  71.       BildPtr     : POINTER;
  72.       Hilf        : INTEGER;
  73.       Datei       : FILE;
  74. (*------------------*)
  75. PROCEDURE ScreenToZeiger;
  76.  
  77. BEGIN
  78.   BildGroesse := ImageSize (Links, Oben, Rechts, Unten);
  79.   (* Grösse der Sprites festlegen *)
  80.   GetMem (BildPtr, BildGroesse);
  81.   (* entsprechend dimensioniern *)
  82.   GetImage (Links, Oben, Rechts, Unten, BildPtr^);
  83.   (* vom Bildschirm ins RAM *)
  84. END;
  85. (*------------------*)
  86. BEGIN (* SaveGraphikScreen *)
  87.   ScreenToZeiger;
  88.   ASSIGN (Datei, DateiName);
  89.   {$I-} REWRITE (Datei, 1); {$I+}
  90.   (* untyp. Datei mit RECORD-Grösse "1" *)
  91.   Hilf := IOResult;  SaveGraphikScreen := Hilf;
  92.   IF Hilf <> 0 THEN EXIT;
  93.   BlockWrite (Datei, BildPtr^, BildGroesse);
  94.   (* vom RAM auf Diskette *)
  95.   CLOSE (Datei);
  96. END;
  97. (*-----------------------------------------------*)
  98.  
  99.  
  100. In diesem Programm ist bereits ein Teil der grundlegenden Routinen
  101. zur Sprite-Verwaltung enthalten. Das Ergebnis unserer Bemühungen
  102. kann mit einem Disketten-Editor (z.B. "Dump", PASCAL 8/87)
  103. betrachtet werden, ein Beispiel sehen wir in Bild 1. Die ersten 4
  104. Bytes enthalten die um jeweils 1 erniedrigten Grössen von Breite
  105. und Höhe des Bildschirmausschnitts, sie werden von der ImageSize-
  106. Prozedur automatisch reserviert und ermittelt. Im Turbo-Handbuch
  107. wird bei ImageSize auch erläutert, wie sich der erforderliche
  108. Speicherplatz ergibt :
  109.  
  110.            Bytezahl = (Breite * Höhe * Bits/Pixel) DIV 8
  111.  
  112. Der Wert von Bits/Pixel gibt an, wieviel Bits zur Speicherung eines
  113. Pixels nötig sind und hängt von der jeweiligen Auflösung der
  114. Graphik- Karte ab. Bei der CGA-Karte in der niedrigen Auflösung hat
  115. Bits/Pixel den Wert 2, in einem Byte (= 8 bit) können also
  116. Informationen für 4 Pixels abgelegt werden. Ein wenig
  117. experimentieren mit einem kleinen Programm ergibt, daß die
  118. Farbnummer jedes Pixels als Faktor berücksichtigt wird und daß der
  119. Inhalt eines Bytes bei Farbe "1" die Werte (von links) 2 hoch 6
  120. (=64), 2 hoch 4 (=16), 2 hoch 2 (=4) und 2 hoch 0 (=1) betragen
  121. kann. Ist in einer Vierergruppe nur der Pixel ganz links gesetzt,
  122. so ist der Byte-Inhalt bei Farbe 1 gleich 64, bei Farbe 3 gleich
  123. 192. Wie sich leicht nachrechnen läßt, beträgt also der höchste
  124. Wert, der sich darstellen läßt, 255, und mehr ist ja bekanntlich
  125. auch nicht möglich mit einem Byte. Nicht ermitteln konnte ich
  126. allerdings, warum am Ende der Datei grundsätzlich immer noch 2
  127. Bytes zusätzlich angehängt werden, bei der Umwandlung der Daten in
  128. eine UNIT werden diese beide überzähligen Bytes dann auch ohne
  129. Schaden ausgeblendet. Zwar abgespeichert und als Klötzchen wieder
  130. dargestellt, jedoch nicht mehr als Sprite abgebildet wird eine
  131. Figur die nur eine Höhe von einem Pixel hat ! Und als letzte
  132. Einschränkung musste ich feststellen, daß der gesetzte ViewPort
  133. entgegen den Angaben in GRAPH.DOC von PutImage nicht berücksichtigt
  134. wird, d.h. ein Sprite wird auch über die von ViewPort gesetzten
  135. Grenzen hinaus gezeigt. Ein weiterer wichtiger Befehl für den
  136. Umgang mit Pointer-Variablen ist - zumindest bei unserem Editor -
  137. der "MOVE"-Befehl, mit
  138.  
  139.                     MOVE (Sprite^, Block, Size)
  140.  
  141. wird der von der Variablen "Sprite" angezeigte Speicherbereich in
  142. ein zuvor festgelegtes ARRAY OF BYTE transportiert, der
  143. Speicherinhalt, d.h. unsere Sprite-Daten können so auf üblichem
  144. Wege ausgewertet werden. (bitte nicht das "^"-Zeichen vergessen,
  145. mit "Sprite" alleine wird nur die Adresse angegeben, ab der die
  146. Daten im RAM abgelegt sind. Eine Verwechslung von Adresse und
  147. Inhalt garantiert Ihnen mit Sicherheit einen Warmstart Ihres
  148. Computers.)
  149.  
  150. Mit dieser Möglichkeit, Sprite-Daten von Diskette zu laden, steht
  151. der Programmierung eines Sprite-Editors nichts mehr im Wege. Bevor
  152. wir einige der Hauptroutinen betrachten, seien die Möglichkeiten
  153. und Grenzen unseres Editors kurz aufgezeigt :
  154.  
  155. - Pixelweises Zeichnen eines Sprites mit max. 24 Pixeln Breite und
  156.   16 Pixeln Höhe. Die jeweilige Länge und Breite kann im Editor
  157.   festgelegt werden.
  158. - Für grössere Figuren können max. 9 Sprites zu einem grossen
  159.   Sprite zusammengefasst werden. Der so zusammengefasste Sprite
  160.   kann bis zu 72 Pixels breit und 48 Pixels hoch sein (immer
  161.   ausgehend von der linken oberen Ecke).
  162. - Die Pixels im Editierfeld können in horizontaler und vertikaler
  163.   Richtung gespiegelt werden, wobei die ursprüngliche Form gelöscht
  164.   wird (es müsste statt "spiegeln" wohl besser "drehen" heissen.
  165.   Will man spiegeln und die Ausgangsfigur dabei beibehalten, kann
  166.   man die Ausgangsfigur einfach auf Diskette zwischenlagern und
  167.   wieder dazuladen.
  168. - Der Sprite kann im späteren Hauptprogramm entweder aus einer
  169.   (untypisierten) Datei eingelesen werden oder als UNIT aufgerufen
  170.   werden. Max. 4 Farben stehen zur Verfügung (Wahl mit den Tasten
  171.   0..3); Hintergrundfarbe und Palette können im Hauptprogramm
  172.   beliebig geändert werden, die beiden letztgenannten werden beim
  173.   Abspeichern nicht berücksichtigt.
  174.  
  175. Einige der wichtigsten Routinen sind im folgenden kurz erläutert,
  176. im Listing sind ebenfalls ausführliche Kommentare enthalten, so daß
  177. das Verständniss des Programmes wohl wenig Probleme bereiten
  178. dürfte.
  179. Betrachten wir zunächst die UNIT GraphV1, eine Zusammenstellung der
  180. allgemeingültigen Routinen, die auch in ihren eigenen Programmen
  181. Verwendung finden könnten. Die Routine zum Abspeichern und Laden
  182. des Sprites ist gleich so gehalten, daß auch ein kompletter
  183. Bildschirminhalt erfaßt werden kann. Sie könnten somit also mit
  184. einem Pascal-Programm auch den Bildhintergrund entwerfen, mit
  185. SaveGraphicScreen abspeichern und im späteren Hauptprogramm mit
  186. LoadGraphicScreen hinzuladen. Vielleicht ebenfalls ganz nützlich
  187. für andere Programme sind die Routinen, um den Bildschirminhalt
  188. nicht auf Diskette, sondern im RAM zu speichern (RamToScreen und
  189. ScreenToRam). Mit "Holstring" lassen sich im Graphikmodus Eingaben
  190. (mit einer vorgegebenen Länge) vornehmen. SchreibSpace schliesslich
  191. behebt den Mißstand, daß ein gesetzter Buchstabe zur Korrektur
  192. bislang in der Hintergrundfarbe überschrieben werden musste, das
  193. Space-Zeichen selbst ist natürlich auch als Sprite definiert.
  194.  
  195. Die "Schalt-Zentrale" des Hauptprogrammes bildet die Prozedur
  196. "Bewegung". Hierin werden sämtliche Eingaben vorgenommen und
  197. ausgewertet. Die möglichen Eingaben sind auf dem Bildschirm in
  198. einem Fenster dargestellt und im Quelltext (hoffentlich
  199. ausreichend) kommentiert. In der Prozedur "MachGrossenSprite"
  200. befinden sich einige Routinen des übergeordneten Programmteils in
  201. leicht veränderter Form; hier könnte man ev. einiges
  202. zusammenfassen, aber ich glaube, so ist es übersichtlicher. Die
  203. Inhalte der beiden Eingabebildschirme bleiben übrigens bei einem
  204. Wechsel erhalten, so kann man problemlos ein kleines Bild editieren
  205. und gleich zu einem grossen Bild zusammenfassen.
  206.  
  207. Der eigenen Kreativität sind nicht nur beim Entwerfen der Figuren
  208. keine Grenzen gesetzt, auch das Programm lässt sich noch in einigen
  209. Punkten ergänzen. Zwei Vorschläge :
  210.  
  211. - Den bereits im Menue enthaltenen, aber nicht ausgearbeiteten
  212.   Punkt "<D>irectory" mit dem in PASCAL 6/7 1988 enthaltenen und
  213.   zur UNIT umgeschriebenen Programm "DatWahl" ausarbeiten.
  214. - Grosse Sprites pixelgenau zusammenfügen.
  215.  
  216. Sicher fallen Ihnen noch einige weitere Punkte zur Verbesserung
  217. beim Studium des Listings ein. - Einstweilen viel Spaß beim Sprite-
  218. Zeichnen wünscht die Redaktion.
  219.  
  220.  
  221. Programm : Sprite-Editor
  222. Funktion : Toolbox     zum    Entwerfen    und    Darstellen    von
  223.            benutzerdefinierten    Figuren    (Sprites)    für   den
  224.            CGA-320*200-Punkte-Modus
  225. Hardware : IBM-kompatibler Rechner mit CGA-Graphik
  226. Software : Turbo-Pascal 4.0
  227.  
  228.  
  229. (Gerd Kraus)
  230.