home *** CD-ROM | disk | FTP | other *** search
- (* ------------------------------------------------------ *)
- (* SPACEWAR.PAS *)
- (* (c) 1990 R.Reichert & TOOLBOX *)
- (* ------------------------------------------------------ *)
- PROGRAM SpaceWar;
-
- USES Graph, Crt;
-
- CONST
- NrRockets = 6; { Anzahl gegnerischer Raketen }
- HOCR = 1; { Zyklus für Raketen }
- MaxShots = 5; { Max. Anz. Schüsse der Rak. }
- CDCons = 150;
- { Für Zufallswert der Richtungsänderung }
- CDMin = 30;
- { Mind. Anz. Beweg. vor Richtungsänderung }
- NSCons = 10;
- { Für Zufallswert für Zeit bis neuschießen }
- NSMin = 5;
- { Frühestens alle NSMin-Einheiten schießen }
- BSpace = 30; { Leerraum unten }
- LSpace = 5; { Leerraum links }
- RSpace = 5; { Leerraum rechts }
- TSpace = 10; { Leerraum oben }
- { Dasselbe für den Spieler... }
- PBSpace = 30; { Leerraum unten }
- PLSpace = 5; { Leerraum links }
- PRSpace = 5; { Leerraum rechts }
- PTSpace = 110; { Leerraum oben }
- PlSMax = 20; { Max. Schüsse für Spieler }
-
- TYPE
- { "Einfangen" und Freigeben von Bildschirmausschnitten. }
- ImageRec = RECORD
- Size : INTEGER;
- Img : POINTER
- END;
-
- OneShot = OBJECT { Objekttyp eines Schusses }
- x, y, { X- und Y-Positionen }
- Bottom, Left,
- Right, Top : INTEGER; { Sichtbare Grenzen }
- Im : ImageRec; { Das Bild }
- DifY : INTEGER;
- { Verschiebung um DifY-Punkte }
- visible : BOOLEAN; { Sichtbar ? }
- xl, yl : INTEGER;
- { X- und Y-Ausdehnung des Bildes }
-
- CONSTRUCTOR Init; { Initialisiert }
- PROCEDURE SetStartPos(nx, ny : INTEGER);
- { Setzt das 1. Schußbild an nx, ny und }
- { visible = true, x = nx, y = ny }
- PROCEDURE Move;
- { Bewegt Schuß um DifY Punkte nach }
- { unten, wenn HowOften = 0, testet, }
- { ob Bottom überschritten wurde und }
- { setzt dementsprechend Visible }
- END;
-
- OneRocket = OBJECT(OneShot) { Obj. einer Rakete }
- ChangeDir, { Neue Richtung ? }
- HowOften, { Zur Geschw. Regulierung }
- DifX, { Verschiebung auf X-Achse }
- NewShot : INTEGER; { Neuer Schuß ? }
- Shots : ARRAY [1..MaxShots] OF ^OneShot;
- { Alle Schüsse einer Rakete }
-
- CONSTRUCTOR Init;
- PROCEDURE Move;
- { Bewegt, auch alle Schüsse, prüft }
- { auf Untergrenze und Richtungs- }
- { änderung, "schießt" }
- DESTRUCTOR Done;
- { Für Speicherfreigabe der Schüsse }
- END;
-
- OnePlShot = OBJECT(OneShot) { Ein Spielerschuß }
- CONSTRUCTOR Init;
- PROCEDURE Move;
- { bewegt nach oben, prüft auf Grenze }
- END;
-
- PlayerObj = OBJECT(OneShot) { Spielerobjekt }
- DifX, DifxCons, DifyCons : INTEGER;
- { Verschiebungen }
- ch : CHAR; { für Tastaturabfrage }
-
- CONSTRUCTOR Init;
- PROCEDURE ReadKeybord;
- { Wertet Tastatureingaben aus }
- PROCEDURE Move;
- DESTRUCTOR Done;
- { Für Speicherfreigabe der Schüsse }
- END;
-
- VAR
- AllRockets : ARRAY [1..NrRockets] OF ^OneRocket;
- i,
- GraphMode,
- GraphDriver : INTEGER;
- Player : PlayerObj;
- PlShots : ARRAY [1..PlsMax] OF ^OnePlShot;
- { Alle Schüsse des Spielers }
- px1, py1,
- px2, py2 : INTEGER; { Position des Spielers }
- Quit : BOOLEAN; { Spiel fertig }
- Lifes : INTEGER; { Anz. Leben f. Spiel }
- Points : INTEGER; { Punktstand }
- Again : BOOLEAN;
- ch : CHAR;
-
- (* ---------------------------------------------------- *)
- (* "Fängt" einen rechteckigen Bildschirmausschnitt in *)
- (* ImgVar ein. *)
- PROCEDURE CatchImage(x1, y1, x2, y2 : INTEGER;
- VAR ImgVar : ImageRec);
- BEGIN
- ImgVar.Size := ImageSize(x1, y1, x2, y2);
- GetMem(ImgVar.Img, ImgVar.Size);
- GetImage(x1, y1, x2, y2, ImgVar.Img^);
- END;
-
- (* ---------------------------------------------------- *)
- (* Gibt den durch ImgVar belegten Speicher frei *)
- PROCEDURE FreeImage(VAR ImgVar : ImageRec);
- BEGIN
- IF ImgVar.Img <> NIL THEN BEGIN
- FreeMem(ImgVar.Img, ImgVar.Size);
- ImgVar.Size := 0;
- ImgVar.Img := NIL;
- END;
- END;
-
- (* ---------------------------------------------------- *)
- (* Zeigt die Anzahl Leben des Spielers an, bzw. *)
- (* löscht ein "Leben" vom Bildschirm. *)
- PROCEDURE Status;
- BEGIN
- WITH Player DO
- PutImage(200 + (Lifes + 1) * (xl + 3),
- GetMaxY - yl - 5, Im.Img^, XorPut);
- END;
-
- (* ---------------------------------------------------- *)
- (* Zeichnet im unsichtbaren Bildschirm das Bild einer *)
- (* Rakete (ACHTUNG: Wer eine niedrigere Auflösung als *)
- (* Hercules hat, der muß x und y anpassen. Nicht mit *)
- (* den anderen 'Zeichnungen' durcheinanderbringen !) *)
- PROCEDURE RocketImage(VAR Im : ImageRec);
- CONST
- l1 = 5; l2 = 3; l3 = 1;
- b1 = 2; b2 = 6; b3 = 3; b4 = 1;
- x = 400; y = 100;
- BEGIN
- SetLineStyle(1, 0, 3); SetActivePage(1);
- MoveTo(x, y+2); LineTo(x, y);
- LineTo(x-b1, y-l1); LineTo(x-b1-b2, y-l1-l2);
- LineTo(x+b1+b2, y-l1-l2); LineTo(x+b1+1, y-l1);
- LineTo(x, y); MoveTo(x+b4, y-l1-l2);
- LineTo(x+b3, y-l1-l2-l3); LineTo(x-b3, y-l1-l2-l3);
- LineTo(x+b4, y-l1-l2);
- Line(x-b1, y-l1, x-b1-b2+4, y-l1-l2);
- Line(x+b1, y-l1, x+b1+b2-4, y-l1-l2);
- CatchImage(x-b1-b2-b3, y+3,
- x+b1+b2+b3, y-l1-l2-l3-2, Im);
-
- SetLineStyle(0, 0, 1); SetActivePage(0)
- END;
-
- (* ---------------------------------------------------- *)
- (* Setzt den Grafikmodus, zeichnet den Titelbildschirm, *)
- (* initialisiert das SpielerObjekt und die Raketen und *)
- (* setzt sie irgendwo auf den Bildschirm in eine *)
- (* Startposition. *)
- PROCEDURE InitGame;
- BEGIN
- Quit := FALSE; Lifes := 10; Points := 0;
- GraphDriver := Detect;
- InitGraph(GraphDriver, GraphMode, '');
- Rectangle(0, 0, GetMaxX, GetMaxY);
- Rectangle(LSpace, TSpace,
- GetMaxX-RSpace, getmaxY-BSpace);
- OutTextXY(151, 1, 'S P A C E W A R');
- OutTextXY(150, 2, 'S P A C E W A R');
- OutTextXY(300, 2, '(c) 1990 R.Reichert & TOOLBOX');
- FOR i := 1 TO 2000 DO
- PutPixel(LSpace + Random(GetMaxX-LSpace-RSpace),
- TSpace + Random(GetMaxY-TSpace-BSpace),
- Random(MaxColors));
- OutTextXY(100, GetMaxY-12, 'Anzahl Leben: ');
- SetWriteMode(XorPut);
- Player.Init;
- FOR i := 1 TO Lifes DO
- WITH Player DO
- PutImage(200 + i * (xl + 3),
- GetMaxY-yl-5, Im.Img^, XorPut);
- FOR i := 1 TO NrRockets DO BEGIN
- New(AllRockets[i], Init);
- AllRockets[i]^.SetStartPos
- ((GetMaxX-RSpace-LSpace) DIV
- NrRockets*(i-1)+LSpace,
- Random(GetMaxY-TSpace)+TSpace)
- END;
- END;
-
- (* ---------------------------------------------------- *)
- (* Beendet das Spiel, gibt die gemachten Punkte aus *)
- PROCEDURE QuitGame;
- VAR
- ps : STRING;
- BEGIN
- SetTextStyle(GothicFont, HorizDir, 5);
- SetWriteMode(CopyPut);
- Str(points:10, ps);
- OutTextXY(50, 80, 'Erreicht: ' + ps + ' Punkte');
- OutTextXY(50, 180, 'Ende... ');
- OutTextXY(50, 280, 'Noch ein Spiel (J/N): ');
- REPEAT
- ch := ReadKey; ch := UpCase(ch);
- UNTIL (ch = 'N') OR (ch = 'J');
- IF UpCase(ch) = 'N' THEN
- Again := FALSE
- ELSE
- Again := TRUE;
- END;
-
- (* ---------------------------------------------------- *)
- (* Titelbild mit Informationen *)
- PROCEDURE FirstInit;
- BEGIN
- GraphDriver := Detect;
- InitGraph(GraphDriver, GraphMode, '');
- FOR i := 1 TO 5000 DO
- PutPixel(Random(GetMaxX),
- Random(GetMaxY), Random(MaxColors));
- SetTextStyle(GothicFont, HorizDir, 5);
- OutTextXY(50, 40, 'S P A C E W A R');
- OutTextXY(30, 90, '────────────────────');
- SetTextStyle(GothicFont, Horizdir, 1);
- OutTextXY(30, 200, 'Gesteuert wird mit Cursortasten'+
- ', geschossen mit Space.');
- OutTextXY(30, 220, 'Steuerung ist auch über den '+
- 'Zahlenblock möglich, wobei mit '+
- 'Home/End');
- OutTextXY(30, 240, 'und PgUp/PgDn diagonal'+
- ' gelenkt werden kann.');
- OutTextXY(30, 260, 'Dafür muß aber NumLock aktiv sein.'+
- ' Anhalten: "5"');
- OutTextXY(30, 280, 'Mit Esc wird das Spiel abgebro'+
- 'chen und die Punktzahl angezeigt.');
- OutTextXY(30, 320, 'Beginnen mit Enter');
- ReadLn;
- END;
-
-
- CONSTRUCTOR OneShot.Init;
- BEGIN
- DifY := 4; xl := 3; yl := 4; visible := FALSE;
- Bottom := GetMaxY - BSpace - yl;
- Left := 0 + LSpace + xl;
- Right := GetMaxX - RSpace - xl;
- Top := 0 + TSpace + yl;
- SetActivePage(1);
- PutPixel(10, 8, 14); PutPixel(10, 10, 14);
- PutPixel(10, 11, 14); PutPixel(11, 10, 14);
- PutPixel( 9, 10, 14); PutPixel(10, 9, 14);
- PutPixel(10, 12, 14); PutPixel(12, 9, 14);
- PutPixel( 8, 9, 14);
- CatchImage(8, 8, 12, 12, Im);
- SetActivePage(0);
- END;
-
- PROCEDURE OneShot.SetStartPos(nx, ny : INTEGER);
- BEGIN
- x := nx; y := ny; visible := TRUE;
- PutImage(x, y, Im.Img^, XorPut);
- END;
-
- PROCEDURE OneShot.Move;
- BEGIN
- Inc(y, DifY);
- IF y > Bottom THEN
- visible := FALSE
- ELSE
- PutImage(x, y, Im.Img^, XorPut);
- PutImage(x, y-DifY, Im.Img^, XorPut);
-
- { Prüfen, ob Spieler getroffen: }
- IF (x > px1) AND (x < px2) AND
- (y > py1) AND (y < py2) THEN BEGIN
- visible := FALSE;
- Dec(Lifes);
- IF Lifes = 0 THEN Quit := TRUE;
- Status;
- PutImage(x, y, Im.Img^, XorPut);
- END;
- END;
-
- CONSTRUCTOR OnePlShot.Init;
- BEGIN
- DifY := 7; xl := 3; yl := 4; Top := 0 + TSpace+yl;
- Visible := FALSE;
- SetActivePage(1);
- PutPixel(7,10,13);
- PutPixel(108,110,13); PutPixel(110,109,13);
- PutPixel(110,110,13); PutPixel(109,111,13);
- PutPixel(111,111,13); PutPixel(110,113,13);
- PutPixel(109,110,13); PutPixel(111,110,13);
- PutPixel(108,112,13); PutPixel(112,112,13);
- CatchImage(108, 107, 112, 113, Im);
- SetActivePage(0);
- END;
-
- PROCEDURE OnePlShot.Move;
- BEGIN
- Dec(y, DifY);
- IF y < Top THEN
- Visible := FALSE
- ELSE
- PutImage(x, y, Im.Img^, XorPut);
- PutImage(x, y+DifY, Im.Img^, XorPut);
- END;
-
- CONSTRUCTOR OneRocket.Init;
- VAR
- i : INTEGER;
- BEGIN
- HowOften := HOCR; xl := 22; yl := 12;
- ChangeDir := CDMin + Random(CDCons);
- Bottom := GetMaxY - BSpace - yl;
- Left := 0 + LSpace;
- Right := GetMaxX - RSpace - xl;
- Top := 0 + TSpace + yl;
- DifY := 3; DifX := 6;
- NewShot := NSMin + Random(NSCons);
- FOR i := 1 TO MaxShots DO
- New(Shots[i], Init);
- RocketImage(im);
- END;
-
- PROCEDURE OneRocket.Move;
- VAR
- j, i, OldX, OldY : INTEGER;
- Killed : BOOLEAN;
- BEGIN
- Killed := FALSE;
- IF HowOften = 0 THEN BEGIN
- OldY := y; Inc(y, DifY);
- OldX := x; Inc(x, DifX);
- { Irgendeine Grenze verletzt ? }
- IF y > Bottom THEN y := Top;
- IF x > Right THEN x := Left;
- IF x < Left THEN x := Right;
-
- IF ChangeDir = 0 THEN BEGIN
- ChangeDir := CDMin + Random(CDCons);
- DifX := -DifX
- END ELSE
- Dec(ChangeDir);
- PutImage(x, y, Im.Img^, XorPut);
- PutImage(Oldx, OldY, Im.Img^, XorPut);
- { In den Spieler geflogen ? }
- IF (x > px1) AND (x < px2) AND (y > py1) AND
- (y < py2) OR (x + xl > px1) AND (x + xl < px2) AND
- (y + yl > py1) AND (y + yl < py2) THEN BEGIN
- Killed := TRUE;
- Dec(lifes);
- Status;
- END;
- { Vom Spieler abgeschossen ? }
- FOR i := 1 TO PlsMax DO
- IF PlShots[i]^.Visible THEN
- IF (PlShots[i]^.x > x) AND
- (PlShots[i]^.x < x+xl) AND
- (PlShots[i]^.y > y) AND
- (PlShots[i]^.y < y+yl) THEN BEGIN
- Killed := TRUE;
- Inc(Points, 500);
- END;
- HowOften := HOCR;
-
- IF (NewShot = 0) THEN BEGIN
- i := 0;
- { Welcher Schuß ist noch nicht unterwegs? }
- REPEAT
- Inc(i);
- UNTIL (i = MaxShots) OR (NOT Shots[i]^.visible);
- IF i <> MaxShots THEN
- Shots[i]^.SetStartPos(x+8, y+15);
- NewShot := NSCons + Random(NSMin);
- END;
- Dec(NewShot)
- END ELSE
- Dec(HowOften);
- { Schüsse bewegen: }
- FOR i := 1 TO MaxShots DO
- IF Shots[i]^.visible THEN Shots[i]^.Move;
- { Getroffen ? }
- IF Killed THEN BEGIN
- Visible := FALSE; PutImage(x, y, Im.Img^, XorPut);
- IF Lifes = 0 THEN Quit := TRUE;
- FOR i := 1 TO MaxShots DO
- IF Shots[i]^.Visible THEN
- WITH Shots[i]^ DO BEGIN
- PutImage(x, y, Im.Img^, Xorput);
- visible := FALSE;
- END;
- END;
- END;
-
- DESTRUCTOR OneRocket.Done;
- VAR
- i : INTEGER;
- BEGIN
- FOR i := 1 TO MaxShots DO Dispose(Shots[i]);
- END;
-
- CONSTRUCTOR PlayerObj.Init;
- CONST
- b1 = 10; b2 = 8; b3 = 6; b4 = 2;
- l1 = 4; l2 = 2; l3 = 10; l4 = 1;
- px = 300; py = 100;
- VAR
- i : INTEGER;
- BEGIN
- FOR i := 1 TO PlSMax DO
- New(PlShots[i], Init);
- DifY := 2; Difx := 4;
- DifxCons := DifX; DifyCons := Dify;
- xl := 20; yl := 19;
- visible := FALSE;
- Bottom := GetMaxY - PBSpace;
- Left := 0 + PLSpace;
- Right := GetMaxX - PRSpace;
- Top := 0 + PTSpace;
- x := (Right - Left) DIV 2 + Left;
- y := Bottom - yl * 2;
- px1 := x; py1 := y;
- px2 := x + xl; py2 := y + yl;
- SetActivePage(1);
- SetWriteMode(CopyPut);
- MoveTo(px - b1, py); LineTo(px - b2, py - l1);
- LineTo(px - b3, py - l2); LineTo(px - b4, py - l3);
- LineRel(0, -4); LineRel(0, 4);
- LineTo(px, py-l1); LineTo(px + b4, py - l3);
- LineRel(0, -4); LineRel(0, 4);
- LineTo(px + b3, py - l2); LineTo(px + b2, py - l1);
- LineTo(px + b1, py); LineTo(px, py + l4);
- LineTo(px - b1, py); LineTo(px, py - l1 + 1);
- LineTo(px + b1, py);
- CatchImage(px - b1, py - l3 - 8, px + b1, py + l4, Im);
- SetActivePage(0);
- PutImage(x, y, Im.Img^, XorPut);
- END;
-
- PROCEDURE PlayerObj.ReadKeybord;
- VAR
- i : INTEGER;
- BEGIN
- ch := ReadKey;
- IF ch = #0 THEN BEGIN
- ch := ReadKey;
- { Cursortasten: }
- CASE ch OF
- #75 : BEGIN DifX := -DifxCons; DifY := 0 END;
- #77 : BEGIN DifX := DifxCons; DifY := 0 END;
- #72 : BEGIN DifY := -DifyCons; DifX := 0 END;
- #80 : BEGIN DifY := DifyCons; DifX := 0 END;
- END
- END ELSE
- CASE ch OF
- { Space: schießen }
- #32 : BEGIN
- i := 0;
- REPEAT
- Inc(i);
- UNTIL (NOT PlShots[i]^.Visible) OR
- (i = PlSMax);
- IF i <> PlsMax THEN BEGIN
- Plshots[i]^.SetStartPos(x+8, y);
- { Geschw. erniedrigen }
- IF i MOD 4 = 0 THEN BEGIN
- Inc(DifYCons); Inc(DifXCons);
- IF NOT DifX = 0 THEN DifX := DifXCons;
- IF NOT DifY = 0 THEN DifY := DifYCons;
- END;
- END;
- END; { Schießen }
- #27 : Quit := TRUE;
- { Zahlenblock (NUM aktiv) }
- #53 : BEGIN DifX := 0; DifY := 0 END;
- #52 : BEGIN DifX := -DifXCons; DifY := 0 END;
- #54 : BEGIN DifX := DifXCons; DifY := 0 END;
- #56 : BEGIN DifY := -DifYCons; DifX := 0 END;
- #50 : BEGIN DifY := DifYCons; DifX := 0 END;
- #55 : BEGIN
- DifX := -DifXCons; DifY := -DifYCons;
- END;
- #49 : BEGIN
- DifX := -DifXCons; DifY := DifYCons;
- END;
- #57 : BEGIN
- DifX := DifXCons; DifY := -DifYCons;
- END;
- #51 : BEGIN
- DifX := DifXCons; DifY := DifYCons;
- END;
- END;
- Move;
- END;
-
- PROCEDURE PlayerObj.Move;
- VAR
- i : INTEGER;
- BEGIN
- FOR i := 1 TO PlsMax DO { Schüsse bewegen }
- IF PlShots[i]^.Visible THEN BEGIN
- PlShots[i]^.Move;
- { Wenn abgeschossen, dann Geschw. erhöhen }
- IF (NOT PlShots[i]^.Visible) AND
- (i MOD 4 = 0) THEN BEGIN
- Dec(DifYCons); Dec(DifXCons);
- IF NOT Difx = 0 THEN DifX := DifXCons;
- IF NOT DifY = 0 THEN DifY := DifYCons;
- END;
- END;
- IF x > Right - xl THEN DifX := -DifXCons;
- IF x < Left THEN DifX := DifXCons;
- IF y > Bottom - yl THEN DifY := -DifYCons;
- IF y < Top THEN DifY := DifYCons;
- PutImage(x + DifX, y + DifY, Im.Img^, XorPut);
- PutImage(x, y, Im.Img^, XorPut);
- Inc(x, DifX);
- Inc(y, DifY);
- px1 := x; py1 := y; px2 := x + xl; py2 := y + yl;
- END;
-
- DESTRUCTOR PlayerObj.Done;
- BEGIN
- FOR i := 1 TO PlSMax DO DisPose(PlShots[i]);
- END;
-
- BEGIN
- FirstInit;
- REPEAT
- Again := TRUE;
- InitGame;
- REPEAT
- FOR i := 1 TO NrRockets DO
- IF AllRockets[i]^.visible THEN
- AllRockets[i]^.Move
- ELSE
- AllRockets[i]^.SetStartPos
- ((GetMaxX-RSpace-LSpace) DIV
- NrRockets*(i-1)+Lspace,
- Random(PTSpace)+TSpace);
- IF KeyPressed THEN Player.ReadKeybord
- ELSE Player.Move;
- UNTIL Quit;
- QuitGame;
- UNTIL NOT Again;
- FOR i := 1 TO NrRockets DO Dispose(AllRockets[i], Done);
- CloseGraph;
- ClrScr;
- END.
- (* ------------------------------------------------------ *)
- (* Ende von SPACEWAR.PAS *)