^1 غكككككككككككككككككككككككككككككككككككككغ ^1 غ S P R I T E S I N Q B A S I C غ ^1 غـــــــــــــــــــــــــــــــــــــغ ^3 Zwei Beispielprogramme von ^4 LeidPen! ^2______________________________________________________________________________ >> The Real Adok: In der letzten Ausgabe des Hugendubelexpress hat TOXO uns gezeigt, wie man Sprites in QBasic bewegen kann. Nun hat LeidPen zwei Beispielprogramme gecodet, die noch einmal sch”n demonstrieren, wie Sprites verwendet werden! Das erste Programm stellt ein Raumschiff dar, das sich um einen Planeten herum bewegt. Dabei sieht man sehr deutlich, welche m„chtigen Befehle QBasic einem bietet, um Objekte rotieren zu lassen! Nebenbei l„لt sich dieses Programm auch als Geschwindigkeitstest der CPU und der Grafikkarte verwenden, weil zum Schluل die Anzahl der Bewegungen pro Sekunde angezeigt wird! Also, hier ist das Programm! ^2______________________________________________________________________________ ^0' ^0'============================================================================ ^0'Programm: "SCHLEIFE", demonstriert ein Sprite mit der DRAW-Anweisung ^0'Sprache: QBasic ^0'Autor(c): Roland Heer ^0'Stand: 28.2.95 ^0'============================================================================ ^0' ^0DEFINT A-Z ^0DECLARE SUB Fliegen (Obj$, Vol) ^0DECLARE SUB Form (Obj$, Vol) ^0DECLARE SUB Himmel () ^0DIM SHARED m, v ^0 CLS ^0 LOCATE 8, 30: PRINT "Abbrechen mit <ESC>" ^0 LOCATE 10, 20: INPUT "Sprite-Gr”لe (4 ... 8) oder Leereingabe : ", m ^0 LOCATE 11, 20: INPUT "Geschwindigkeit (1 oder 2) oder Leereingabe : ", v ^0 IF m < 4 THEN m = 4 ^0 IF m > 8 THEN m = 8 ^0 IF v < 1 THEN v = 1 ^0 IF v > 2 THEN v = 2 ^0 SCREEN 9 ^0 CALL Himmel ^0 CALL Form(Obj$, Vol) ^0 CALL Fliegen(Obj$, Vol) ^0 SLEEP ^0 SCREEN 0, , 0, 0 ^0SYSTEM ^0'____________________________________________________________________________ ^0' ^0SUB Fliegen (Obj$, Vol) ^0'** S=Gr”لe, TA=Winkel fپr DRAW-Funktion ^0 DIM pict(1561, 1), altX(1), altY(1) ^0 PCOPY 0, 1 'Himmel kopieren ^0 wi = 0: wiPTR$ = VARPTR$(wi) ^0 gr = m: grPTR$ = VARPTR$(gr) ^0 dx = CINT(gr * Vol / 8) ^0 dy = CINT(.7 * dx) ^0 ddx = 2 * dx ^0 ddy = 2 * dy ^0 vis = 0 'sichtbare Bildschirmseite ^0 hid = 1 'unsichtbare " " ^0 X = 350: Y = 310 ^0 altX(vis) = X: altX(hid) = X 'alte Koordinaten ^0 altY(vis) = Y: altY(hid) = Y 'fپr 2 BS-Seiten ^0 GET (X - dx, Y - dy)-STEP(ddx, ddy), pict(0, 0) 'alter Untergrund ^0 GET (X - dx, Y - dy)-STEP(ddx, ddy), pict(0, 1) 'alter Untergrund ^0 SCREEN , , hid, vis ^0 PSET (X, Y), 0 'Anfangszentrum ^0 DRAW "S=" + grPTR$ + "TA=" + wiPTR$ + Obj$ 'Bild zeichnen ^0 PCOPY 1, 0 'und in BS 0 kopieren ^0 t! = TIMER ^0 FOR i = 0 TO 220 STEP v '1. Bogen ^0 X = CINT(350 * COS(i / 220)) ^0 Y = CINT(310 * (1 - SIN(i / 220))) ^0 IF (i MOD 4) = 0 THEN ^0 wi = wi + 1 ^0 END IF ^0 GOSUB fliege ^0 NEXT i ^0 x0 = 151 ^0 y0 = 39 ^0 FOR i = 124 TO 550 STEP 2 * v '2. Bogen ^0 X = x0 + CINT(70 * COS(i / 120)) ^0 Y = y0 + CINT(62 * (1 - SIN(i / 120))) ^0 wi = wi + v ^0 GOSUB fliege ^0 NEXT i ^0 x0 = X ^0 y0 = Y - 310 ^0 FOR i = 2 TO 200 STEP v '3. Bogen ^0 X = x0 + CINT(350 * SIN(i / 220)) ^0 Y = y0 + CINT(310 * COS(i / 220)) ^0 IF (i MOD 4) = 0 THEN ^0 wi = wi + 1 ^0 END IF ^0 GOSUB fliege ^0 NEXT i ^0 SCREEN , , vis, vis ^0 PUT (altX(hid) - dx, altY(hid) - dy), pict(0, hid), PSET ^0 'alter Untergrund ^0 PRINT "Bewegungen/sec:"; n / (TIMER - t!); ^0EXIT SUB ^0fliege: ^0 DO: LOOP UNTIL INP(&H3DA) AND 8 'Bildwechsel abwarten ^0 DO: LOOP WHILE INP(&H3DA) AND 8 ^0 PUT (altX(hid) - dx, altY(hid) - dy), pict(0, hid), PSET ^0 'alter Untergrund ^0 GET (X - dx, Y - dy)-STEP(ddx, ddy), pict(0, hid) 'neuer Untergrund ^0 PSET (X, Y), 0 'neues Zentrum setzen ^0 DRAW "TA=" + wiPTR$ + Obj$ 'neues Bild zeichnen ^0 altX(hid) = X ^0 altY(hid) = Y ^0 hid = 1 - hid: vis = 1 - vis 'Screen wechseln ^0 SCREEN , , hid, vis ^0 n = n + 1 ^0 IF LEN(INKEY$) THEN EXIT SUB ^0RETURN ^0END SUB ^0'____________________________________________________________________________ ^0' ^0SUB Form (Obj$, Vol) ^0'** Makro fپr DRAW-Funktion definieren ^0 Vol = 37 'ohne Kondensstreifen ^0 'Vol = 30 'mit Kondensstreifen ^0 Obj$ = "C15 BU12 D2 L1 R2 F2 D1 G1 D1 R2 F3 D1 F3 R1 F1" ^0 Obj$ = Obj$ + "R3 U2 E1 F1 D3 G1 L2 D1 L2 G2 L5 H2 L6" ^0 Obj$ = Obj$ + "G2 L5 H2 L2 U1 L2 H1 U3 E1 F1 D2 R3 E1" ^0 Obj$ = Obj$ + "R1 E3 U1 E3 R2 U1 H1 U1 E2 R2 BD10 P8,15" ^0END SUB ^0'____________________________________________________________________________ ^0' ^0SUB Himmel ^0 RANDOMIZE TIMER ^0 Stern$ = "C14 BL4 R8 BG4 BU1 U6 BU1 BF2 G4 BR4 H4 BF1 R2 D2 L2 U2" ^0 FOR i = 8 TO 344 STEP 8 'kleine Sterne ^0 FOR j = 8 TO 632 STEP 8 ^0 IF RND < .015 THEN ^0 LINE (j, i)-STEP(4, 0), 14 ^0 LINE (j + 2, i + 2)-STEP(0, -4), 14 ^0 'Farbe 15 wird nicht verdeckt! ^0 END IF ^0 NEXT j ^0 NEXT i ^0 FOR i = 14 TO 336 STEP 14 'mittlere Sterne ^0 FOR j = 14 TO 630 STEP 14 ^0 IF RND < .015 THEN ^0 PSET (j, i), 0 ^0 DRAW (Stern$) ^0 END IF ^0 NEXT j ^0 NEXT i ^0 FOR i = 14 TO 336 STEP 14 'groلe Sterne ^0 FOR j = 14 TO 630 STEP 14 ^0 IF RND < .01 THEN ^0 PSET (j, i), 0 ^0 DRAW ("S6 " + Stern$) ^0 END IF ^0 NEXT j ^0 NEXT i ^0 c! = ATN(1) / 45 'Mond ^0 phi = -30 ^0 X = 300: Y = 146 ^0 a = 28: b = 15 ^0 CIRCLE (X, Y), 37, 1 'blauer Kreis ^0 PAINT (X, Y), 8, 1 'Sterne l”schen ^0 PAINT (X, Y), 0, 1 'im Mondbereich ^0 CIRCLE (X, Y), 37, 14, (95 + phi) * c!, (285 + phi) * c! ^0 'gelber Halbkreis ^0 ds! = SIN(phi * c!) ^0 dc! = COS(phi * c!) ^0 PSET (X + ds! * a, Y + dc! * a), 0 ^0 FOR i! = 0 TO 180 * c! STEP 2 * c! 'gelbe Halbellipse ^0 xi! = a * COS(i!) 'geneigt ^0 yi! = b * SIN(i!) ^0 LINE -(X - dc! * yi! + ds! * xi!, Y + dc! * xi! + ds! * yi!), 14 ^0 NEXT i! ^0 PAINT (X - 25, Y), 14 'gelb fپllen ^0END SUB ^2______________________________________________________________________________ >> The Real Adok: Und nun zum zweiten Programm! Hierbei handelt es sich um ein kleines Spiel, bei dem man mit einem Meteor das Raumschiff rammen muل. Die Sprites werden mit PUT-Anweisungen angezeigt, das heiلt, sie mپssen vorher in einem Array gespeichert werden. Es werden mehrere Arrays ben”tigt, weil es auch mehrere Sprites gibt. Das eigentliche Spiel wird mit den Cursor- tasten gesteuert. Hat man das Raumschiff mit dem Meteor gerammt, gibt es eine sch”ne Explosion - auch das l„لt sich sehr leicht mit den Grafik- befehlen von QBasic programmieren! ^2______________________________________________________________________________ ^0' ^0'============================================================================ ^0'Programm: "JAGD", demonstriert Sprites mit PUT-Anweisungen ^0'Sprache: QBasic ^0'Autor(c): Roland Heer ^0'Stand: 28.2.95 ^0'============================================================================ ^0' ^0DEFINT A-Z ^0DECLARE SUB DoExplosion (Ex, Ey, vis) ^0DECLARE SUB MaleFlieger () ^0DECLARE SUB MaleHimmel () ^0DECLARE SUB MaleMeteor () ^0DECLARE SUB Move () ^0DIM SHARED FX, FY, MX, MY, k, MCode(1 TO 9) ^0DIM SHARED dx1, dy1, dx2, dy2 ^0DIM SHARED Mond(1141), MondX, MondY ^0DIM SHARED U1(201, 1), Objekt1(201), Schatten1(201) ^0DIM SHARED U2(1123, 1), Objekt2(1123), Schatten2(1123) ^0CONST ScrXmax = 639 'x-Bildschirmbereich ^0CONST ScrYmax = 349 'y-Bildschirmbereich ^0 CLS ^0 LOCATE 8, 30: PRINT "Abbrechen mit <ESC>" ^0 LOCATE 10, 20: INPUT "Sprite-Gr”لe (4 ... 8) oder Leereingabe: ", k ^0 IF k < 4 THEN k = 4 ^0 IF k > 8 THEN k = 8 ^0 RESTORE CodeData 'Make-Codes speichern ^0 FOR i = 1 TO 9 ^0 READ MCode(i) ^0 NEXT i ^0 SCREEN 9 ^0 CLS ^0 CALL MaleHimmel ^0 CALL MaleMeteor ^0 CALL MaleFlieger ^0 CALL Move ^0 SCREEN , , 0, 0 ^0 LOCATE 25, 1: PRINT STRING$(80, " "); ^0 SLEEP ^0 SCREEN 0 ^0SYSTEM ^0CodeData: ^0 DATA 79,80,81: '1 2 3 ^0 DATA 75,76,77: '4 5 6 ^0 DATA 71,72,73: '7 8 9 auf dem num. Tastenblock ^0'____________________________________________________________________________ ^0' ^0SUB DoExplosion (Ex, Ey, vis) ^0 PLAY "MBO0L32EFGEFDC" 'Krach ^0 PLAY "MBO0L16EFGEFDC" ^0 SCREEN , , vis, vis ^0 Radius = 10 * k ^0 FOR c = 1 TO Radius 'Feuerball ^0 CIRCLE (Ex, Ey), c, 15 'zunehmend ^0 NEXT c ^0 FOR c = Radius TO 0 STEP -1 'Feuerball ^0 CIRCLE (Ex, Ey), c, 0 'abnehmend ^0 t! = TIMER ^0 DO: LOOP UNTIL TIMER - t! > .05 ^0 NEXT c ^0 PUT (MondX, MondY), Mond, PSET 'Mond reparieren 'falls besch„digt ^0 LOCATE 25, 1: PRINT STRING$(80, " "); ^0 SLEEP ^0 SCREEN 0, , 0, 0 ^0SYSTEM ^0END SUB ^0'____________________________________________________________________________ ^0' ^0SUB MaleFlieger ^0'** S=Gr”لe, TA=Winkel fپr DRAW-Funktion ^0 Vol = 34 ^0 Obj$ = "C15 BU13 D2 L1 R2 F2 D1 G1 D1 R2 F3 D1 F3 R1 F1" ^0 Obj$ = Obj$ + "R3 U2 E1 F1 D3 G1 L2 D1 L2 G2 L5 H2 L6" ^0 Obj$ = Obj$ + "G2 L5 H2 L2 U1 L2 H1 U3 E1 F1 D2 R3 E1" ^0 Obj$ = Obj$ + "R1 E3 U1 E3 R2 U1 H1 U1 E2 R2 BD10" ^0 Neg$ = Obj$ + "P15,15" 'Schatten invertiert ^0 Obj$ = Obj$ + "P8,15" 'Flugzeug ^0 wi = 35: wiPTR$ = VARPTR$(wi) 'Achse 35 Grad ^0 gr = k: grPTR$ = VARPTR$(gr) 'Gr”لe k ^0 dx2 = CINT(gr * Vol / 8) ^0 dy2 = CINT(.6 * dx2) ^0 ddx = 2 * dx2 'Breite und H”he des ^0 ddy = 2 * dy2 'umschlieلd. Rechtecks ^0 CLS ^0 x = 350 'Anfangsposition ^0 y = 280 ^0 FX = x - dx2 ^0 FY = y - dy2 ^0 PSET (x, y), 0 ^0 DRAW "S=" + grPTR$ + "TA=" + wiPTR$ + Obj$ 'Flugzeug zeichnen ^0 GET (FX, FY)-STEP(ddx, ddy), Objekt2 'speichern ^0 PSET (x, y), 0 ^0 DRAW "S=" + grPTR$ + "TA=" + wiPTR$ + Neg$ 'Schattenbild zeichnen ^0 GET (FX, FY)-STEP(ddx, ddy), Schatten2 'speichern ^0 PUT (FX, FY), Schatten2, PRESET 'Schattenbild invert. ^0 GET (FX, FY)-STEP(ddx, ddy), Schatten2 'speichern ^0END SUB ^0'____________________________________________________________________________ ^0' ^0SUB MaleHimmel ^0 RANDOMIZE TIMER ^0 COLOR 14 ^0 Stern$ = "C14 BL4 R8 BG4 BU1 U6 BU1 BF2 G4 BR4 H4 BF1 R2 D2 L2 U2" ^0 FOR i = 8 TO 344 STEP 8 'kleine Sterne ^0 FOR j = 8 TO 632 STEP 8 ^0 IF RND < .015 THEN ^0 LINE (j, i)-STEP(4, 0) ^0 LINE (j + 2, i + 2)-STEP(0, -4) ^0 END IF ^0 NEXT j ^0 NEXT i ^0 FOR i = 14 TO 336 STEP 14 'mittlere Sterne ^0 FOR j = 14 TO 630 STEP 14 ^0 IF RND < .015 THEN ^0 PSET (j, i), 0 ^0 DRAW (Stern$) ^0 END IF ^0 NEXT j ^0 NEXT i ^0 FOR i = 14 TO 336 STEP 14 'groلe Sterne ^0 FOR j = 14 TO 630 STEP 14 ^0 IF RND < .01 THEN ^0 PSET (j, i), 0 ^0 DRAW ("S6 " + Stern$) ^0 END IF ^0 NEXT j ^0 NEXT i ^0 c! = ATN(1) / 45 'Mond ^0 phi = -30 ^0 x = 250: y = 146 ^0 a = 28: b = 15 ^0 CIRCLE (x, y), 37, 1 'blauer Kreis ^0 PAINT (x, y), 8, 1 'Sterne l”schen ^0 PAINT (x, y), 0, 1 'im Mondbereich ^0 CIRCLE (x, y), 37, , (95 + phi) * c!, (285 + phi) * c! 'gelber Halbkreis ^0 ds! = SIN(phi * c!) ^0 dc! = COS(phi * c!) ^0 PSET (x + ds! * a, y + dc! * a), 0 ^0 FOR i! = 0 TO 180 * c! STEP 2 * c! 'gelbe Halbellipse ^0 xi! = a * COS(i!) 'geneigt ^0 yi! = b * SIN(i!) ^0 LINE -(x - dc! * yi! + ds! * xi!, y + dc! * xi! + ds! * yi!) ^0 NEXT i! ^0 PAINT (x - 25, y) 'gelb fپllen ^0 GET (x - 37, y - 28)-STEP(74, 56), Mond ^0 MondX = x - 37: MondY = y - 28 ^0 LOCATE 25, 2 ^0 PRINT "Meteor mit den Pfeiltasten (auch diagonal: 1,3,7,9) bewegen"; ^0END SUB ^0'____________________________________________________________________________ ^0' ^0SUB MaleMeteor ^0 SCREEN , , 1, 0 'auf 1 schreiben ^0 CLS '0 anzeigen ^0 Radius = 6 ^0 dx1 = CINT(Radius * k / 4) ^0 dy1 = CINT(.78 * dx1) ^0 ddx = 2 * dx1: ddy = 2 * dy1 'Breite und H”he des 'umschlieلd. Rechtecks ^0 x = 320 ^0 y = 175 ^0 MX = x - dx1 ^0 MY = y - dy1 ^0 CIRCLE (x, y), Radius * k \ 4, 4 ^0 PAINT (x, y), 3, 4 ^0 GET (MX, MY)-STEP(ddx, ddy), Objekt1 'speichern ^0 CIRCLE (x, y), Radius * k \ 4, 15 ^0 PAINT (x, y), 15, 15 ^0 GET (MX, MY)-STEP(ddx, ddy), Schatten1 'speichern ^0 PUT (MX, MY), Schatten1, PRESET 'Schatten invert. ^0 GET (MX, MY)-STEP(ddx, ddy), Schatten1 'speichern ^0END SUB ^0'____________________________________________________________________________ ^0' ^0SUB Move ^0'** Sprites bewegen ^0 DIM MaX(1), MaY(1), FaX(1), FaY(1) 'alte Koordinaten 'fپr 2 BS-Seiten ^0 hid = 1 'versteckte BSeite ^0 vis = 0 'sichtbare BSeite ^0 PCOPY vis, hid 'Himmel kopieren ^0 vF = 1 'Geschwdkt. Flieger ^0 vM = vF + 1 'Geschwdkt. Meteor ^0 ddx1 = 2 * dx1: ddx2 = 2 * dx2 'Breite Objekt 1+2 ^0 ddy1 = 2 * dy1: ddy2 = 2 * dy2 'H”he Objekt 1+2 ^0 MaX(hid) = MX: FaX(hid) = FX 'alte Werte = ^0 MaY(hid) = MY: FaY(hid) = FY 'aktuelle Werte ^0 MaX(vis) = MX: FaX(vis) = FX ^0 MaY(vis) = MY: FaY(vis) = FY ^0 GET (MX, MY)-STEP(ddx1, ddy1), U1(0, 0) 'Untergrunde fپr ^0 GET (MX, MY)-STEP(ddx1, ddy1), U1(0, 1) 'Objekt1 retten ^0 GET (FX, FY)-STEP(ddx2, ddy2), U2(0, 0) 'Untergrunde fپr ^0 GET (FX, FY)-STEP(ddx2, ddy2), U2(0, 1) 'Objekt2 retten ^0 PUT (MX, MY), Schatten1, AND 'Objekt1 darstellen ^0 PUT (MX, MY), Objekt1, OR ^0 PUT (FX, FY), Schatten2, AND 'Objekt2 darstellen ^0 PUT (FX, FY), Objekt2, OR ^0 PCOPY hid, vis ^0 MBerX = ScrXmax - ddx1 'Bildrandgrenzen ^0 MBerY = ScrYmax - ddy1 'f. Meteorbewegung ^0 tF! = TIMER 'f. Flieger+Meteor ^0 DO ^0 Code = INP(&H60) 'Port 60h abfragen ^0 SELECT CASE Code 'Taste auswerten ^0 CASE MCode(1) 'links unten ^0 IF MX > vM THEN MX = MX - vM ^0 IF MY < MBerY - vM THEN MY = MY + vM ^0 CASE MCode(2) 'unten ^0 IF MY < MBerY - vM THEN MY = MY + vM ^0 CASE MCode(3) 'rechts unten ^0 IF MX < MBerX - vM THEN MX = MX + vM ^0 IF MY < MBerY - vM THEN MY = MY + vM ^0 CASE MCode(4) 'links ^0 IF MX > vM THEN MX = MX - vM ^0 CASE MCode(6) 'rechts ^0 IF MX < MBerX - vM THEN MX = MX + vM ^0 CASE MCode(7) 'links oben ^0 IF MX > vM THEN MX = MX - vM ^0 IF MY > vM THEN MY = MY - vM ^0 CASE MCode(8) 'oben ^0 IF MY > vM THEN MY = MY - vM ^0 CASE MCode(9) 'rechts oben ^0 IF MX < MBerX - vM THEN MX = MX + vM ^0 IF MY > vM THEN MY = MY - vM ^0 END SELECT ^0 IF MX < FX + ddx2 AND FX < MX + ddx1 THEN 'Kollision prپfen ^0 IF MY < FY + ddy2 AND FY < MY + ddy1 THEN ^0 CALL DoExplosion(FX + dx2, FY + dy2, vis) ^0 END IF ^0 END IF ^0 DO: LOOP UNTIL INP(&H3DA) AND 8 'Bildwechsel abwarten ^0 DO: LOOP WHILE INP(&H3DA) AND 8 ^0 PUT (MaX(hid), MaY(hid)), U1(0, hid), PSET 'alter Untergrund ^0 GET (MX, MY)-STEP(ddx1, ddy1), U1(0, hid) 'neuer Untergrd. ^0 PUT (MX, MY), Schatten1, AND 'Objekt1 darstellen ^0 PUT (MX, MY), Objekt1, OR ^0 MaX(hid) = MX ^0 MaY(hid) = MY ^0 IF FY <= 1 THEN 'Bildrand erreicht ^0 IF letzt < 2 THEN ^0 PUT (FaX(hid), FaY(hid)), U2(0, hid), PSET 'alter Untgr. ^0 IF letzt = 1 THEN ^0 LOCATE 1, 1 ^0 PRINT USING "Flugbewegungen/sec: ###.#"; n / (TIMER - tF!); ^0 PCOPY hid, vis ^0 tM! = TIMER 'fپr Meteor solo ^0 n = 0 ^0 FX = -ddx2: FY = -ddy2 'weitere Kollision ^0 END IF 'verhindern ^0 letzt = letzt + 1 ^0 END IF ^0 n = n + 1 ^0 IF n MOD 100 = 0 THEN ^0 LOCATE 2, 1 ^0 PRINT USING "Meteorbewegungen/sec: ###.#"; n / (TIMER - tM!); ^0 IF n MOD 10000 = 0 THEN 'ڑberlauf verhind. ^0 tM! = TIMER ^0 n = 0 ^0 END IF ^0 END IF ^0 GOTO ScreenWechsel ^0 END IF ^0 FX = FX - vF 'neue Position ^0 FY = FY - vF 'fپr Flieger ^0 PUT (FaX(hid), FaY(hid)), U2(0, hid), PSET 'alter Untergrund ^0 GET (FX, FY)-STEP(ddx2, ddy2), U2(0, hid) 'neuer Untergrund ^0 PUT (FX, FY), Schatten2, AND 'Objekt2 darstellen ^0 PUT (FX, FY), Objekt2, OR ^0 FaX(hid) = FX ^0 FaY(hid) = FY ^0 n = n + 1 ^0ScreenWechsel: ^0 hid = 1 - hid: vis = 1 - vis ^0 SCREEN , , hid, vis ^0 IF INKEY$ = CHR$(27) THEN EXIT SUB ^0 LOOP ^0END SUB ^2______________________________________________________________________________ ^1 Das war's!