home *** CD-ROM | disk | FTP | other *** search
- PROGRAM SpriteEditor;
- (* Programm zum Erstellen von Sprites für CGA-Karte im 320*200-Modus *)
-
- (* V.1.0.c - 12.10.88 *)
-
- {$R+,S+,I+,D+,T-,F+,V+,B+,N-,L+ }
- {$M 16384,0,655360 }
- (* die Compiler-Optionen werden mit CTRL-F7 in den Quelltext übernommen *)
-
- USES
- CRT, Graph, SpieleGraph;
- (* in Spielegraph GraphDir an die eigenen Verzeichnisse anpassen ! *)
- CONST
- StartX : INTEGER = 8; (* Editierfeld linke Linie *)
- Spalten : INTEGER = 24; (* max. 24 Spalten breit *)
- DeltaX : INTEGER = 8; (* 8 Pixel / Spalte *)
-
- StartY : INTEGER = 18; (* Editierfeld obere Linie *)
- Zeilen : INTEGER = 16; (* max. 16 Zeilen hoch *)
- DeltaY : INTEGER = 9; (* 9 Pixel / Zeile *)
-
- Offset : INTEGER = 4; (* Byte 1..4 = Sprite-Abmessungen *)
-
- TempFile : STRING = 'Sprite.TMP';
- (* ^ zur "Zwischenlagerung" beim Spiegeln; *)
- (* eine RamDisk ist hier recht nützlich *)
-
- VAR AktFarbe, (* aktuelle Farbe *)
- HgFarbe, (* Hintergrund-Farbe *)
- SprFLinks, (* Koordinaten des Sprite-Fensters .. *)
- SprFOben, (* .. = in der Ecke rechts unten .. *)
- SprFRechts, (* .. *)
- SprFUnten, (* .. *)
- AktSpalten, (* gewaehlte Abmessungen .. *)
- AktZeilen : INTEGER; (* .. des Sprites *)
- (*-----------------------------------------------*)
- PROCEDURE ViewPort (VPNummer : INTEGER);
- (* Feld-Grenzen festlegen *)
- BEGIN
- SetColor (MaxFarbe);
- CASE VPNummer OF
- 1: BEGIN (* EingabeFenster *)
- SetViewPort (StartX + 1, EndY + 5,
- EndX - 1, EndY + 13 + 2 * DeltaY, ClipOn);
- ClearViewPort;
- END;
- 2: BEGIN (* ges. Bildschirm *)
- SetViewPort (MinX, MinY, MaxX, MaxY, ClipOn);
- END;
- 3: BEGIN (* SpriteFenster *)
- SetViewPort (SprFLinks + 2, SprFOben + 2,
- SprFRechts - 2, SprFUnten - 2, ClipOn);
- END;
-
- END; (* CASE VPNummer *)
-
- END;
- (*-----------------------------------------------*)
- FUNCTION HolFileName (Ext : STRING) : STRING;
- (* Eingabe des Namens, eine Extension wird vorgegeben *)
- (* Beachten : bei einer UNIT (PRC MachUnit steht dieser Name in der ersten *)
- (* Zeile, ein hier ev. angegeb. Unterverzeichnis muss später "von Hand" *)
- (* gelöscht werden ! *)
- VAR Temp : STRING;
-
- BEGIN
- ViewPort (1);
- OutTextXY (10, 6, 'Filename : ');
- MoveTo (10,16);
- HolString (Temp, 20);
- IF Temp = '' THEN Beep (200,40);
- IF (POS( '.', Temp) = 0) AND (Temp <> '') THEN Temp := Temp + Ext;
- HolFileName := Temp;
- ClearViewPort;
- ViewPort (2);
- END;
- (*-----------------------------------------------*)
- FUNCTION Wirklich (Frage : STRING) : BOOLEAN;
- (* Ja oder Nein *)
- VAR Ch : CHAR;
-
- BEGIN
- ViewPort (1);
- OutTextXY (5, 6, Frage);
-
- REPEAT
- Ch := ReadKey
- UNTIL UpCase (Ch) IN ['J', 'N'];
- ClearViewPort;
- ViewPort (2);
- Wirklich := Ch IN ['J', 'j'];
- END;
- (*-----------------------------------------------*)
- PROCEDURE Abbruch;
- (* akustische Fehlermeldung, man könnte noch zusätzlich auf Text .. *)
- (* .. umschalten und den Fehler mitteilen *)
- BEGIN
- Beep (300,100); Beep (500,150);
- ViewPort (2);
- END;
- (*-----------------------------------------------*)
- PROCEDURE Dimensionierung (VAR Sprite : POINTER; VAR Groesse : INTEGER);
- (* Sprite mit akt. Abmessungen dimensionieren und Fensterinhalt speichern *)
- BEGIN
- Groesse := ImageSize (1, 1, AktSpalten, AktZeilen);
- GetMem (Sprite, Groesse);
- GetImage (1, 1, AktSpalten, AktZeilen, Sprite^);
- END;
- (*-----------------------------------------------*)
- PROCEDURE SaveEditSprite (Name : STRING);
- (* Sprite abspeichern *)
-
- VAR F : FILE;
- DatFehler,
- Size : INTEGER;
- Sprite : POINTER;
-
- BEGIN
- IF Name = '' THEN EXIT;
- ViewPort (3);
- Dimensionierung (Sprite, Size);
-
- ASSIGN (F, Name);
- {$I-} REWRITE (F,1); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- BlockWrite (F, Sprite^, Size);
- CLOSE (F);
- FreeMem (Sprite, Size);
- ViewPort (2);
- Beep (800,100);
- END;
- (*-----------------------------------------------*)
- PROCEDURE LoadEditSprite (Name : STRING);
- (* Laden eines Sprites, ein ev. vorhandenes Bild wird .. *)
- (* .. hierbei n i c h t gelöscht ! *)
- VAR F : FILE;
- DatFehler,
- Size,
- Ergebnis : INTEGER;
- Sprite : POINTER;
- Block : ARRAY [1..128] OF BYTE;
- (* ^ Sprite-Daten, nur zum Klötzchen-Setzen nötig *)
- (* die Pixels sind hier "komprimiert" gespeichert, .. *)
- (* .. d.h. Block [n] enthält den Wert von 4 Pixels ! *)
- (*---------------*)
- PROCEDURE ZeigKloetzchen;
- (* Aufbau des Editierbildes *)
- VAR Pixel,
- Breite,
- TempHoehe,
- Farbe, (* .. eines Pixels *)
- X, Y, (* Klötzchen-Koordinaten *)
- AktByte, (* akt. Byte mit 4 Pixels *)
- Bitt : INTEGER; (* 2 bit eines Bytes .. *)
- (* .. enthält die Farbe eines Pixels *)
-
- CONST Dual : ARRAY [1..4] OF BYTE = (6, 4, 2, 0);
- (* ^ zum schnellen Umrechnen der Zweierpotenzen *)
-
- BEGIN
- INC (Block [1], 1);
- (* im Sprite-Feld [1] werden die um 1 erniedrigten Spalten gespeichert *)
- AktSpalten := Block [1];
- (* ^ Breite des Sprites in Editier-Spalten = 1..24 *)
- Breite := (Block [1] DIV 4) + ORD (Block [1] MOD 4 > 0);
- (* ^ Breite des Sprites in 4er-Bytes = 1..6 *)
- (* 1 Byte kann 4 Pixel aufnehmen *)
-
- INC (Block [3], 1);
- (* im Sprite-Feld [3] werden die um 1 erniedrigten Zeilen gespeichert *)
- AktZeilen := Block [3];
- (* ^ Höhe des Sprites in Editier-Zeilen = 1..16 *)
-
- TempHoehe := 1;
-
- REPEAT
- FOR Pixel := 1 TO Breite DO
- BEGIN
- AktByte := Block [Offset + Pixel + Breite * (PRED (TempHoehe))];
- (* das erste Daten-Byte hat die Nr. 5 *)
- (* jetzt wird Block [n] in die 4 Pixels "zerlegt" *)
- FOR Bitt := 1 TO 4 DO
- BEGIN
- Farbe := AktByte SHR Dual [Bitt];
- X := StartX + 3 + (PRED (Pixel) * 4 + PRED (Bitt)) * DeltaX;
- Y := StartY + 3 + PRED (TempHoehe) * DeltaY;
-
- IF Farbe <> 0 THEN BEGIN
- SetFillStyle (SolidFill, Farbe);
- BAR (X, Y, X + DeltaX - 6, Y + DeltaY - 6);
- END; (* IF Farbe <> 0 *)
-
- AktByte := AktByte - (Farbe SHL (Dual [Bitt]));
- END; (* FOR Bitt := 1 TO 4 *)
- END; (* FOR Pixel := 1 TO Breite *)
- INC (TempHoehe, 1);
- UNTIL TempHoehe > AktZeilen;
- END; (* ZeigKloetzchen *)
- (*------------------*)
- BEGIN (* LoadEditSprite *)
- IF Name = '' THEN EXIT;
- (* ev. hier Sprite- u. Editierfenster löschen ! *)
- ViewPort (3);
- Size := ImageSize (1, 1, Spalten, Zeilen);
- GetMem (Sprite, Size);
- (* die Abmessungen des zu ladenden Sprites sind noch unbekannt .. *)
- (* .. also wird für die max. Abmessungen "dimensioniert" *)
- ASSIGN (F, Name);
- {$I-} RESET (F,1); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- BlockRead (F, Sprite^, Size, Ergebnis);
- CLOSE (F);
-
- PutImage (1, 1, Sprite^, XorPut);
- (* Überlagerung der Farben im SpriteFenster *)
- (* im EditierFenster Ueberlagerung mit "falschen" Farben *)
- (* erst nach Hor.- o. Vert.spiegeln stimmen hier die Farben ! *)
- (* Will man beide Fenster komplett neu aufbauen, dann vor .. *)
- (* .. dem Laden wie bei "NEU" alles löschen *)
-
- ViewPort (2);
-
- (* vom Pointer in das BYTE-ARRAY : *)
- MOVE (Sprite^, Block, Size);
- ZeigKloetzchen; (* .. im Editierfeld *)
- FreeMem (Sprite, Size);
- Beep (800,100);
- END;
- (*-----------------------------------------------*)
- PROCEDURE ZeigFarben;
- (* zeigt die 3 möglichen Farben auf dem Bildschirm, .. *)
- (* Wahl mit der entsprechenden Ziffern-Taste *)
-
- VAR Farbe : INTEGER;
- Temp : STRING;
-
- BEGIN
- SetColor (MaxFarbe);
- FOR Farbe := 0 TO MaxFarbe DO
- BEGIN
- SetFillStyle (SolidFill, Farbe);
- Bar (EndX + 72 + Farbe * 8, EndY + 12,
- EndX + 80 + Farbe * 8, EndY + 12 + DeltaY);
- Rectangle (EndX + 72 + Farbe * 8, EndY + 12,
- EndX + 80 + Farbe * 8, EndY + 12 + DeltaY);
- STR (Farbe, Temp);
- OutTextXY (EndX + 72 + Farbe * 8 + 1, EndY + 12 + DeltaY + 4, Temp);
- END;
-
- STR (GraphMode, Temp);
- OutTextXY (EndX + 60, EndY + 4 + DeltaY, Temp);
- END;
- (*-----------------------------------------------*)
- PROCEDURE Bildschirm;
- (* Bildschirm-Aufbau *)
- VAR Menue : INTEGER;
- CONST MaxMenue = 12;
- MenuePunkt : ARRAY [1..MaxMenue] OF STRING =
- ('<N>eu', '<G>rösse', '<P>alette', 'H<i>ntergr.',
- '<F>üllen', '<L>aden', '<S>peichern', '<U>nit',
- '<H>or.spieg.', '<V>er.spieg.', '<Z>usammenf.', '<E>nde');
-
- BEGIN
- MachRaster (StartX, Spalten, DeltaX, StartY, Zeilen, DeltaY, FALSE);
- Rectangle (MinX, MinY, MaxX, MaxY); (* Umrandung *)
-
- Rectangle (MinX + 2, MinY + 2, EndX, 12); (* Status *)
- OutTextXY (8, 4, 'X : -- Y :');
-
- Rectangle (EndX + 8, MinY + 2, MaxX - 2, 16); (* Titel *)
- OutTextXY (EndX + 11, 6, 'SPRITTY V.1.0');
-
- Rectangle (EndX + 8, StartY , MaxX - 2, EndY); (* Befehle *)
-
- (* Eingaben *)
- Rectangle (StartX, EndY + 4, EndX, EndY + 14 + 2 * DeltaY);
-
- SprFLinks := EndX + 8;
- SprFOben := EndY + 8;
- SprFRechts := SprFLinks + 2 + Spalten + 3;
- SprFUnten := SprFOben + 2 + Zeilen + 3;
- Rectangle (SprFLinks, SprFOben, SprFRechts, SprFUnten); (* Sprite *)
-
- FOR Menue := 1 TO MaxMenue DO
- BEGIN
- OutTextXY (EndX + 16, 20 + Menue * 10, MenuePunkt [Menue]);
- END;
-
- ZeigFarben;
- END;
- (*-----------------------------------------------*)
- PROCEDURE HolAbmessungen;
- (* Grösse des Arbeitsfeldes festlegen *)
- VAR Temp : STRING;
- Fehler : INTEGER;
-
- BEGIN
- ViewPort (1);
- OutTextXY (10, 6, 'Breite <1..24> : ');
-
- REPEAT
- SchreibSpace (148, 6);
- SchreibSpace (156, 6);
- MoveTo (148, 6);
- HolString (Temp, 2);
- VAL (Temp, AktSpalten, Fehler);
- UNTIL ((AktSpalten IN [1..24]) AND (Fehler = 0)) OR (Temp = '');
-
- IF Temp = '' THEN BEGIN Abbruch; EXIT; END;
-
- OutTextXY (10, 16, 'Höhe <1..16> : ');
- REPEAT
- SchreibSpace (148, 16);
- SchreibSpace (156, 16);
- MoveTo (148, 16);
- HolString (Temp, 2);
- VAL (Temp, AktZeilen, Fehler);
- UNTIL (AktZeilen IN [1..16]) AND (Fehler = 0);
-
- ViewPort (2);
- END;
- (*-----------------------------------------------*)
- PROCEDURE HolPalette;
- (* Palette 0..3 auswählen, kann n i c h t abgespeichert werden ! *)
- VAR Temp : STRING;
- Fehler : INTEGER;
-
- BEGIN
- ViewPort (1);
- OutTextXY (10, 6, 'Palette <0..3> : ');
-
- REPEAT
- SchreibSpace (148, 6);
- MoveTo (148, 6);
- HolString (Temp, 1);
- VAL (Temp, GraphMode, Fehler);
- UNTIL (GraphMode IN [0..3]) AND (Fehler = 0);
-
- ClearViewPort;
- ViewPort (2);
-
- ScreenToRam (2);
-
- InitGraph (GraphDriver, GraphMode, '');
- RamToScreen (2);
-
- SchreibSpace (EndX + 60, EndY + 4 + DeltaY);
- STR (GraphMode, Temp);
- OutTextXY (EndX + 60, EndY + 4 + DeltaY, Temp);
- END;
- (*-----------------------------------------------*)
- PROCEDURE HolFarbe;
- (* füllt den kompletten Sprite mit einer Farbe *)
- VAR Fehler, Farbe, Size : INTEGER;
- Temp : STRING;
- Sprite : POINTER;
-
- BEGIN
- ViewPort (1);
- OutTextXY (10, 6, 'Farbe <0..3> : ');
-
- REPEAT
- SchreibSpace (148, 6);
- MoveTo (148, 6);
- HolString (Temp, 1);
- VAL (Temp, Farbe, Fehler);
- UNTIL ((Farbe IN [0..3]) AND (Fehler = 0)) OR (Temp = '');
-
- ClearViewPort;
- IF Temp = '' THEN BEGIN Beep (200, 40); EXIT; END;
-
- ViewPort (3);
- SetFillStyle (SolidFill, Farbe);
- BAR (1, 1, AktSpalten, AktZeilen);
-
- SaveEditSprite (TempFile);
- IF Farbe = 0 THEN RamToScreen (1);
- (* bei Farbe 0 werden die Klötzchen nicht gesetzt ! *)
- ViewPort (3); ClearViewPort; (* wg. XorPut bei LoadEditSprite ! *)
- LoadEditSprite (TempFile);
- END;
- (*-----------------------------------------------*)
- PROCEDURE HorizontalSpiegeln;
- (* spiegelt am nächsten Byte = 4 Pixels *)
- (* Abmessungen beachten ! *)
- VAR Block, Temp : ARRAY [1..128] OF BYTE;
- DatFehler,
- Pixel,
- Size,
- TempHoehe,
- Breite,
- Ziel,
- Ursprung,
- Quelle,
- Hilf, Bitt: INTEGER;
- Sprite : POINTER;
- F : File;
- Farbe : ARRAY [1..4] OF BYTE;
-
- CONST Dual : ARRAY [1..4] OF BYTE = (6, 4, 2, 0);
- (* zum schnellen Umrechnen der Zweierpotenzen *)
-
- BEGIN
- FillChar (Temp, SizeOF (Temp), 0); (* Zwischenspeicher *)
- FillChar (Block, SizeOF (Block), 0);
-
- ViewPort (3);
- Dimensionierung (Sprite, Size);
-
- ViewPort (2);
- MOVE (Sprite^, Block, Size); (* vom Sprite ins ARRAY *)
- INC (Block [1]);
- Breite := (Block [1] DIV 4) + ORD (Block [1] MOD 4 > 0);
- DEC (Block [1]);
- TempHoehe := 1;
-
- REPEAT
- Ursprung := TempHoehe * Breite + Offset + 1;
- FOR Pixel := 1 TO Breite DO
- BEGIN
- Ziel := (TempHoehe - 1) * Breite + Pixel + Offset;
- Quelle := Ursprung - Pixel;
- Temp [Ziel] := Block [Quelle];
-
- Hilf := Temp [Ziel];
- FOR Bitt := 1 TO 4 DO (* Byte --> 4 Farben *)
- BEGIN
- Farbe [5 - Bitt] := Hilf SHR Dual [Bitt];
- Hilf := Hilf - (Farbe [5-Bitt] SHL (Dual [Bitt] ));
- END;
- Hilf := 0;
- FOR Bitt := 1 TO 4 DO
- Hilf := Hilf + Farbe [Bitt] SHL Dual [Bitt];
- Temp [Ziel] := Hilf;
- END; (* FOR Pixel := 1 TO Breite *)
-
- INC (TempHoehe, 1);
- UNTIL TempHoehe > AktZeilen;
-
- FillChar (Block, SizeOF (Block), 0);
- Block := Temp;
- Block [1] := PRED (AktSpalten); Block [3] := PRED (AktZeilen);
- MOVE (Block, Sprite^, Size); (* .. und wieder zurück *)
-
- (* das Editierbild muss jetzt neu aufgebaut werden, warum sollen wir .. *)
- (* .. uns die Arbeit machen ? Beim Laden eines Bildes erledigt das der *)
- (* .. Rechner, also wird im TempFile zwischengelagert ! Eine Ramdisk .. *)
- (* .. beschleunigt das Ganze erheblich ! .. *)
-
- ASSIGN (F, TempFile);
- {$I-} REWRITE (F,1); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- BlockWrite (F, Sprite^, Size);
- CLOSE (F);
-
- RamToScreen (1);
- LoadEditSprite (TempFile); (* Laden und somit Editierbild aufbauen ! *)
- END;
- (*-----------------------------------------------*)
- PROCEDURE VertikalSpiegeln;
- (* analog HorizontalSpiegeln *)
- (* gewählte Abmessungen beachten ! *)
- VAR Block, Temp : ARRAY [1..128] OF BYTE;
- DatFehler,
- Pixel,
- Size,
- TempHoehe,
- Breite,
- Ziel, Quelle : INTEGER;
- Sprite : POINTER;
- F : File;
-
- BEGIN
- FillChar (Temp, SizeOF (Temp), 0);
- FillChar (Block, SizeOF (Block), 0);
-
- ViewPort (3);
- Dimensionierung (Sprite, Size);
-
- ViewPort (2);
- MOVE (Sprite^, Block, Size);
- INC (Block [1], 1);
- Breite := (Block [1] DIV 4) + ORD (Block [1] MOD 4 > 0);
- DEC (Block [1], 1);
- TempHoehe := 1;
-
- REPEAT
- FOR Pixel := 1 TO Breite DO
- BEGIN
- Ziel := (TempHoehe - 1) * Breite + Pixel + Offset;
- Quelle := (AktZeilen - TempHoehe) * Breite + Pixel + Offset;
- Temp [Ziel] := Block [Quelle];
- END; (* FOR Pixel := 1 TO Breite *)
-
- INC (TempHoehe, 1);
- UNTIL TempHoehe > AktZeilen;
-
- FillChar (Block, SizeOF (Block), 0);
- Block := Temp;
- Block [1] := PRED (AktSpalten); Block [3] := PRED (AktZeilen);
- MOVE (Block, Sprite^, Size);
- ASSIGN (F, TempFile);
- {$I-} REWRITE (F, 1); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- BlockWrite (F, Sprite^, Size);
- CLOSE (F);
-
- RamToScreen (1);
- LoadEditSprite (TempFile);
- END;
- (*-----------------------------------------------*)
- PROCEDURE MachUnit (DateiName : STRING);
- (* Sprite-Daten in UNIT speichern *)
- (* ev. nachzubearbeiten : *)
- (* - VAR Sprite u. SpriteFeld : Variablennamen ändern *)
- (* - Name der UNIT *)
-
- VAR Datei : TEXT;
- DatFehler,
- Size,
- I, J : INTEGER;
- Sprite : POINTER;
- Block : ARRAY [1..128] OF BYTE;
-
- BEGIN
- IF DateiName = '' THEN EXIT;
-
- ViewPort (3);
- Dimensionierung (Sprite, Size);
-
- ViewPort (2);
- Size := Size - 2; (* die ominösen letzten beiden Bytes ausblenden *)
- MOVE (Sprite^, Block, Size);
-
- ASSIGN (Datei, DateiName);
- {$I-} REWRITE (Datei); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- DEC (DateiName [0], 4); (* DateiName ohne Extension *)
- (* ev. Dir.pfad später im UNIT-Namen löschen !! *)
- WRITELN (Datei, 'UNIT ', DateiName, ';');
- WRITELN (Datei, 'INTERFACE');
- WRITELN (Datei, 'USES CRT, Graph, SpieleGraph;');
- WRITELN (Datei);
- WRITELN (Datei, 'VAR Sprite : POINTER;');
- (* bei mehreren Sprites natürlich den Namen der Variablen ändern ! *)
- WRITELN (Datei, 'CONST Size : INTEGER = ', Size, ';');
- WRITELN (Datei, 'CONST SpriteFeld : ARRAY [1..', Size, '] OF BYTE =');
- WRITE (Datei, '(');
- FOR I := 1 TO Offset DO
- WRITE (Datei, Block [I], ',' );
- (* Breite und Höhe des Sprites *)
- WRITELN (Datei);
-
- (* Anzahl der Spalten in Bytes *)
- J := (Block [1] + 1) DIV 4;
- IF ((Block [1] + 1) MOD 4) > 0 THEN INC (J, 1);
-
- (* 1..4 = Abmessungen, letztes Byte mit ')' *);
- FOR I := 1 TO (Size - Offset - 1) DO
- BEGIN
- WRITE (Datei, Block [(I + Offset)]);
- IF I MOD J = 0 THEN WRITELN (Datei, ',') ELSE WRITE (Datei, ',')
- END;
- WRITE (Datei, Block [I + Offset + 1]); (* beim letzten Byte ')' statt ',' *)
- WRITELN (Datei, ');');
- WRITELN (Datei);
- WRITELN (Datei, 'IMPLEMENTATION');
- WRITELN (Datei, 'BEGIN');
- WRITELN (Datei, ' GetMem (Sprite, Size);');
- WRITELN (Datei, ' MOVE (SpriteFeld, Sprite^, Size);');
- (* die nächsten beiden Zeilen sind nur "Gedächtnisstütze" und *)
- (* können gelöscht werden *)
- WRITELN (Datei, ' { GraphikInit; }');
- WRITELN (Datei, ' { PutImage (100, 100, Sprite^, XorPut); }');
- WRITELN (Datei, 'END.');
- CLOSE (Datei);
- Beep (800,100);
- END;
- (*-----------------------------------------------*)
- PROCEDURE MachGrossenSprite;
- (* max. 9 Bilder lassen sich zusammenfassen *)
- (* einiges liesse sich mit den vorigen Routinen zusammenfassen *)
- (* aber so ist es etwas übersichtlicher ! *)
- VAR Taste : CHAR;
- Nummer : INTEGER;
-
- CONST StartPixX : INTEGER = 51;
- StartPixY : INTEGER = 51;
- AktBreite : INTEGER = 24;
- AktHoehe : INTEGER = 16;
- (*---------------*)
- PROCEDURE Initialisierung;
- (* Bildschirm-Aufbau *)
- VAR Menue : INTEGER;
- CONST MaxMenue = 6;
- MenuePunkt : ARRAY [1..MaxMenue] OF STRING =
- ('<N>eu', '<G>rösse',
- '<L>aden', '<S>peichern', '<U>nit',
- '<Z>urück');
-
- BEGIN
- ScreenToRam (2);
-
- SetColor (PRED (MaxFarbe));
-
- SetViewPort (MinX + 3, MinY + 3, EndX - 1, 11, ClipOn); (* Status *)
- ClearViewPort;
- OutTextXY (35,1, 'Sprite-Kollektor');
-
- ViewPort (1);
- SetColor (MaxFarbe);
- SetViewPort (StartX + 1, StartY + 1, EndX - 1, EndY -1, ClipOn);
- ClearViewPort; (* EditierFeld *)
-
- SetViewPort (EndX + 9, StartY + 1, MaxX - 3, EndY -1, ClipOn); (* Befehle *)
- ClearViewPort;
-
- ViewPort (2);
-
- FOR Menue := 1 TO MaxMenue DO
- BEGIN
- OutTextXY (EndX + 16, 20 + Menue * 10, MenuePunkt [Menue]);
- END;
-
- OutTextXy (EndX + 35, 100, 'Blöcke :');
- OutTextXy (EndX + 40, 110, '1 2 3');
- OutTextXy (EndX + 40, 120, '4 5 6');
- OutTextXy (EndX + 40, 130, '7 8 9');
- END; (* Initialisierung *)
- (*---------------*)
- PROCEDURE HolGroesse;
- (* Grösse des Arbeitsfeldes in Pixeln festlegen *)
- VAR Temp : STRING;
- Fehler : INTEGER;
-
- BEGIN
- ViewPort (1);
- OutTextXY (10, 6, 'Breite <1..72> : ');
-
- REPEAT
- SchreibSpace (148, 6);
- SchreibSpace (156, 6);
- MoveTo (148, 6);
- HolString (Temp, 2);
- VAL (Temp, AktBreite, Fehler);
- UNTIL ((AktBreite IN [1..72]) AND (Fehler = 0)) OR (Temp = '');
-
- IF Temp = '' THEN BEGIN Abbruch; EXIT; END;
-
- OutTextXY (10, 16, 'Höhe <1..48> : ');
- REPEAT
- SchreibSpace (148, 16);
- SchreibSpace (156, 16);
- MoveTo (148, 16);
- HolString (Temp, 2);
- VAL (Temp, AktHoehe, Fehler);
- UNTIL (AktHoehe IN [1..48]) AND (Fehler = 0);
- ClearViewPort;
- ViewPort (2);
- END;
- (*---------------*)
- PROCEDURE HolFeld (VAR Nummer : INTEGER);
- (* Nummer des Blocks, der besetzt werden soll *)
- VAR Temp : STRING;
- Fehler : INTEGER;
-
- BEGIN
- ViewPort (1);
- OutTextXY (10, 6, 'Nummer <1..9> : ');
-
- REPEAT
- SchreibSpace (148, 6);
- MoveTo (148, 6);
- HolString (Temp, 1);
- VAL (Temp, Nummer, Fehler);
- UNTIL ((Nummer IN [1..9]) AND (Fehler = 0)) OR (Temp = '');
- ClearViewPort;
- ViewPort (2);
- END; (* HolNummer *)
- (*---------------*)
- PROCEDURE LoadSprite (Name : STRING);
- (* Sprite laden *)
- VAR F : FILE;
- DatFehler,
- Size,
- Ergebnis : INTEGER;
- Sprite : POINTER;
-
- CONST StartX : ARRAY [0..2] OF BYTE = (99, 51, 75);
- StartY : ARRAY [0..2] OF BYTE = (51, 67, 83);
-
- BEGIN
- IF Name = '' THEN EXIT;
-
- Size := ImageSize (0, 0, 72, 48);
- GetMem (Sprite, Size);
- (* die Abmessungen des zu ladenden Sprites sind unbekannt .. *)
- (* .. also wird fuer die max. Grösse "dimensioniert" *)
- (* .. und zwar so, dass man auch einen 3 * 3-Sprite testweise laden kann *)
- (* .. ev. wird dann allerdings der ViewPort überschritten ! *)
-
- ASSIGN (F, Name);
- {$I-} RESET (F,1); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- BlockRead (F, Sprite^, Size, Ergebnis);
- CLOSE (F);
-
- ViewPort (2);
- PutImage
- (StartX [Nummer MOD 3], StartY [PRED (Nummer) DIV 3],
- Sprite^, NormalPut);
- Beep (800,100);
- END; (* LoadSprite *)
- (*---------------*)
- PROCEDURE SaveSprite (Name : STRING);
- (* grossen Sprite abspeichern *)
- VAR F : FILE;
- DatFehler,
- Size,
- Breite,
- Hoehe : INTEGER;
- Sprite : POINTER;
-
- BEGIN
- IF Name = '' THEN EXIT;
-
- Breite := StartPixX + AktBreite;
- Hoehe := StartPixY + AktHoehe;
-
- SetViewPort (StartPixX, StartPixY, Breite, Hoehe, ClipOn);
-
- DEC (AktBreite); DEC (AktHoehe);
- Size := ImageSize (0, 0, AktBreite, AktHoehe);
- GetMem (Sprite, Size);
- GetImage (0, 0, AktBreite, AktHoehe, Sprite^);
- INC (AktBreite); INC (AktHoehe);
- ASSIGN (F, Name);
- {$I-} REWRITE (F,1); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- BlockWrite (F, Sprite^, Size);
- CLOSE (F);
- FreeMem (Sprite, Size);
- ViewPort (2);
- Beep (800,100);
- END; (* SaveSprite *)
- (*---------------*)
- PROCEDURE MachGrUnit (DateiName : STRING);
- (* grosser Sprite als UNIT *)
- VAR Datei : TEXT;
- DatFehler,
- Size,
- I, J,
- Breite,
- Hoehe : INTEGER;
- Sprite : POINTER;
- Block : ARRAY [1..870] OF BYTE;
-
- BEGIN
- IF DateiName = '' THEN EXIT;
-
- Breite := StartPixX + AktBreite;
- Hoehe := StartPixY + AktHoehe;
-
- SetViewPort (StartPixX, StartPixY, Breite, Hoehe, ClipOn);
-
- DEC (AktBreite); DEC (AktHoehe);
- Size := ImageSize (0, 0, AktBreite, AktHoehe);
- GetMem (Sprite, Size);
- GetImage (0, 0, AktBreite, AktHoehe, Sprite^);
- INC (AktBreite); INC (AktHoehe);
- Size := Size - 2; (* die ominösen letzten beiden Bytes ausblenden *)
- MOVE (Sprite^, Block, Size);
-
- ASSIGN (Datei, DateiName);
- {$I-} REWRITE (Datei); {$I+}
- DatFehler := IOResult;
- IF DatFehler <> 0 THEN BEGIN Abbruch; EXIT; END;
-
- DEC (DateiName [0], 4); (* DateiName ohne Extension *)
- (* ev. Dir.pfad im UNIT-Namen löschen ! *)
- WRITELN (Datei, 'UNIT ', DateiName, ';');
- WRITELN (Datei, 'INTERFACE');
- WRITELN (Datei, 'USES CRT, Graph, SpieleGraph;');
- WRITELN (Datei);
- WRITELN (Datei, 'VAR Sprite : POINTER;');
- WRITELN (Datei, 'CONST Size : INTEGER = ', Size, ';');
- WRITELN (Datei, 'CONST SpriteFeld : ARRAY [1..', Size, '] OF BYTE =');
- WRITE (Datei, '(');
- FOR I := 1 TO Offset DO
- WRITE (Datei, Block [I], ',' );
- (* Breite und Hoehe des Sprites *)
- WRITELN (Datei);
-
- (* Anzahl der Spalten in Bytes *)
- J := (Block [1] + 1) DIV 4;
- IF ((Block [1] + 1) MOD 4) > 0 THEN INC (J, 1);
-
- (* 1..4 = Abmessungen, letztes Byte mit ')' *);
- FOR I := 1 TO (Size - Offset - 1) DO
- BEGIN
- WRITE (Datei, Block [(I + Offset)]);
- IF I MOD J = 0 THEN WRITELN (Datei, ',') ELSE WRITE (Datei, ',')
- END;
- WRITE (Datei, Block [I + Offset + 1]); (* beim letzten Byte ')' statt ',' *)
- WRITELN (Datei, ');');
- WRITELN (Datei);
- WRITELN (Datei, 'IMPLEMENTATION');
- WRITELN (Datei, 'BEGIN');
- WRITELN (Datei, ' GetMem (Sprite, Size);');
- WRITELN (Datei, ' MOVE (SpriteFeld, Sprite^, Size);');
- WRITELN (Datei, ' { GraphikInit; }');
- WRITELN (Datei, ' { PutImage (100, 100, Sprite^, XorPut); }');
- WRITELN (Datei, 'END.');
- CLOSE (Datei);
- FreeMem (Sprite, Size);
- ViewPort (2);
- Beep (800,100);
- END; (* MachGrUnit *)
- (*---------------*)
- BEGIN (* MachGrossenSprite *)
- Initialisierung;
- RamToScreen (3);
-
- REPEAT
- HolZeichen (Taste);
-
- CASE UpCase (Taste) OF
-
- 'N' : BEGIN (* Neu --> alles loeschen *)
- IF Wirklich ('Löschen <J> / <N>') THEN
- BEGIN
- SetViewPort
- (StartX + 1, StartY + 1, EndX - 1, EndY - 1, ClipOn);
- ClearViewPort;
- END; (* IF Neu *)
- END;
-
- 'G' : (* Abmessungen festlegen *)
- HolGroesse;
-
- 'S' : (* Sprite in FILE (OF BYTE) speichern *)
- SaveSprite (HolFilename ('.GSP'));
-
- 'L' : BEGIN (* Sprite laden *)
- HolFeld (Nummer);
- IF Nummer > 0 THEN LoadSprite (HolFilename ('.SPR'))
- ELSE BEGIN Beep (200,40); END;
- END;
-
- 'U' : (* Sprite in UNIT speichern *)
- MachGrUnit (HolFilename ('.PAS'));
-
- 'Z' : IF Wirklich ('Zurück <J> / <N>') THEN Taste := 'Z';
-
- END; (* CASE Taste OF *)
- UNTIL Taste = 'Z';
-
- ViewPort (2);
- ScreenToRam (3); (* akt. Bildschirm speichern .. *)
- RamToScreen (2); (* .. und Editierbild zurückholen *)
- END; (* MachGrossenSprite *)
- (*-----------------------------------------------*)
- (*-----------------------------------------------*)
- PROCEDURE Bewegung;
- (* die Schaltzentrale *)
- VAR Taste : CHAR;
- X_Alt, Y_Alt,
- X_Neu, Y_Neu,
- Delta : INTEGER; (* 0..1 *)
- (*-----------------*)
- PROCEDURE SetzCursor (X, Y : INTEGER; Loeschen : BOOLEAN);
- (* Cursor bewegen *)
- BEGIN
- X := StartX + 1 + PRED (X) * DeltaX;
- Y := StartY + 1 + PRED (Y) * DeltaY;
- IF Loeschen THEN SetColor (0) ELSE SetColor (MaxFarbe);
-
- Rectangle (X, Y, X + DeltaX - 2, Y + DeltaY - 2);
- END;
- (*-----------------*)
- PROCEDURE Farbe (X, Y : INTEGER);
- (* Farbe 0..3 setzen *)
- BEGIN
- X := StartX + 3 + PRED (X) * DeltaX;
- Y := StartY + 3 + PRED (Y) * DeltaY;
- SetFillStyle (SolidFill, AktFarbe);
- BAR (X, Y, X + DeltaX - 6, Y + DeltaY - 6);
-
- (* SpriteFenster *)
- ViewPort (3);
- PutPixel (X_Neu, Y_Neu, AktFarbe);
-
- ViewPort (2);
- END;
- (*-----------------*)
- PROCEDURE ZeigerWechsel;
- (* Cursor-Verwaltung u. Koordinaten-Angabe *)
- VAR Hilf : STRING;
-
- BEGIN
- SetzCursor (X_Alt, Y_Alt, TRUE);
- SetzCursor (X_Neu, Y_Neu, FALSE);
- (* löschen des alten Wertes ginge auch mit SchreibSpace ! *)
- STR (X_ALt, Hilf); SetColor (0); OutTextXY (40, 4, Hilf);
- STR (X_Neu, Hilf); SetColor (1); OutTextXY (40, 4, Hilf);
- STR (Y_ALt, Hilf); SetColor (0); OutTextXY (128, 4, Hilf);
- STR (Y_Neu, Hilf); SetColor (1); OutTextXY (128, 4, Hilf);
- END;
- (*-----------------*)
- BEGIN (* Bewegung *)
-
- AktSpalten := Spalten; AktZeilen := Zeilen;
- X_Alt := 1; Y_Alt := 1;
- X_Neu := 1; Y_Neu := 1;
- SetzCursor (X_Alt, Y_Alt, FALSE); ZeigerWechsel;
- ScreenToRam (1);
- HgFarbe := 0; SetBkColor (HgFarbe);
-
- REPEAT
- X_Alt := X_Neu; Y_Alt := Y_Neu;
- HolZeichen (Taste);
-
- CASE UpCase (Taste) OF
- ^D : BEGIN (* Rechts *)
- Delta := ORD ((X_Alt + 1 <= AktSpalten));
- X_Neu := X_Alt + Delta;
- ZeigerWechsel;
- END;
-
- ^S : BEGIN (* Links *)
- Delta := ORD ((X_Alt - 1 >= 1));
- X_Neu := X_Alt - Delta;
- ZeigerWechsel;
- END;
-
- ^E : BEGIN (* Oben *)
- Delta := ORD ((Y_Alt - 1 >= 1));
- Y_Neu := Y_Alt - Delta;
- ZeigerWechsel;
- END;
-
- ^X : BEGIN (* Unten *)
- Delta := ORD ((Y_Alt + 1 <= AktZeilen));
- Y_Neu := Y_Alt + Delta;
- ZeigerWechsel;
- END;
-
- ^W : BEGIN (* Links oben *)
- X_Neu := 1; Y_Neu := 1;
- ZeigerWechsel;
- END;
-
- ^C : BEGIN (* Rechts unten *)
- X_Neu := AktSpalten; Y_Neu := AktZeilen;
- ZeigerWechsel;
- END;
-
- '0'..'3' : BEGIN (* Farben *)
- AktFarbe := ORD (Taste) - 48;
- Farbe (X_Neu, Y_Neu);
- END;
-
- 'N' : BEGIN (* Neu --> alles löschen *)
- IF Wirklich ('Löschen <J> / <N>') THEN
- BEGIN
- GraphMode := CGAC0;
- InitGraph (GraphDriver, GraphMode, GraphDir);
- RamToScreen (1);
- X_Neu := 1; Y_Neu := 1;
- AktSpalten := Spalten; AktZeilen := Zeilen;
- END; (* IF Neu *)
- END;
-
- 'G' : BEGIN (* Abmessungen festlegen *)
- HolAbMessungen;
- X_Neu := 1; Y_Neu := 1; ZeigerWechsel;
- END;
-
- 'S' : BEGIN (* Sprite in FILE (OF BYTE) speichern *)
- SaveEditSprite (HolFilename ('.SPR'));
- X_Neu := 1; Y_Neu := 1; ZeigerWechsel;
- END;
-
- 'L' : BEGIN (* Sprite laden *)
- LoadEditSprite (HolFilename ('.SPR'));
- X_Neu := 1; Y_Neu := 1; ZeigerWechsel;
- END;
-
- 'U' : (* Sprite in UNIT speichern *)
- MachUnit (HolFilename ('.PAS'));
-
- 'P' : (* Palette wechseln *)
- HolPalette;
-
- 'F' : (* Sprite komplett mit Farbe füllen *)
- HolFarbe;
-
- 'H' : BEGIN
- HorizontalSpiegeln;
- X_Neu := 1; Y_Neu := 1;
- END;
-
- 'V' : BEGIN
- VertikalSpiegeln;
- X_Neu := 1; Y_Neu := 1;
- END;
-
- 'I' : BEGIN (* Hintergrundfarbe wechseln *)
- INC (HgFarbe, 1); SetBkColor (HgFarbe MOD 15);
- END;
-
- 'D' : BEGIN (* Directory, Grafik --> Text *)
- {
- (* hier nur die Angabe der Routinen *)
- ScreenToRam (2);
- TextMode (C80); (* nicht RestoreCrtMode wg. 40-Zeichen ! *)
- WRITELN ('Directory-Unit s. PASCAL 6/7 88 !');
- WRITE ('Zurück zur Grafik mit einem beliebigen Tastendruck...');
- REPEAT UNTIL KeyPressed;
- SetGraphMode (GetGraphMode);
- RamToScreen (2);
- }
- END;
-
- 'Z' : (* grosser Sprite *)
- MachGrossenSprite;
-
- 'E' : IF Wirklich ('Programm-Ende <J> / <N>') THEN Taste := 'E';
-
- END; (* CASE Taste OF *)
- UNTIL Taste = 'E';
-
- END; (* Bewegung *)
- (*-----------------------------------------------*)
- BEGIN
- GraphDriver := CGA; GraphMode := 0;
- GraphikInit (GraphDriver, GraphMode);
- Bildschirm;
- Bewegung;
- GraphikEnde;
- END.
-