C 64
Grafik

Und sie drehen sich doch

Leicht und komfortabel lassen sich beliebige Sprites um die X- und Y-Achse drehen. Auch das Verkleinern und Vergrößern dieser kleinen Kunstwerke ist kein Problem. Das spart Arbeit und Zeit.

Mit »Shrinksprite« (Listing 1), wie sich dieses Programm nennt, lassen sich Sprites horizontal und vertikal verkleinern oder aber an der X- und Y-Achse drehen. Da die veränderten Sprites in einem neuen Sprite-Block zwischengespeichert werden, bleibt das ursprüngliche Sprite in seiner vollen Pracht erhalten. Auf Wunsch läßt sich der entsprechende Sprite-Zeiger auf den neuen Block umschalten. Dadurch wird eine kontinuierliche, flimmerfreie Verformung ermöglicht.

Shrinksprite ist mit einem einfachen SYS-Aufruf mit Parameterübergabe zu starten:

SYS 49152, Ursprungsblock, Zielblock, vertikale Stauchung, horizontale Stauchung, Spritenummer

Ursprungsblock

Nach dem SYS-Aufruf und einem Komma folgt der zu behandelnde Sprite-Block (0 bis 255). Dadurch ist das Errechnen der Adresse ab der das Sprite gespeichert ist überflüssig.

Zielblock

Hier ist die Nummer des Blocks anzugeben, in den das geänderte Sprite gespeichert werden soll. Dieser Block darf mit dem Ursprungsblock identisch sein. Allerdings ist dann das ursprüngliche Sprite unwiderruflich verloren. Daher ist es ratsam, sich zu jedem behandelten Sprite einen anderen Zielblock zu suchen.

Vertikale und horizontale Stauchung

Um die horizontale und vertikale Stauchung zu verstehen, läßt sich die Stauchung des Sprites als Drehung um die eigene Achse interpretieren. Bei vertikaler Stauchung liegt die Drehachse auf der elften Bytereihe und bei der horizontalen Stauchung zwischen dem zwölften und dreizehnten Bit. Die Drehachsen teilen das Sprite in jeweils zwei gleiche Hälften (Bild 1). Sind die beiden angegebenen Drehfaktoren für die horizontale und vertikale Stauchung auf Null gesetzt, dann sieht das erzeugte Sprite genauso aus wie das ursprüngliche Sprite. Es hat sich also nichts geändert. Was aber passiert wenn der Drehfaktor größer wird? Bei vertikaler Drehung wird das Sprite mit zunehmendem Drehfaktor immer schmaler (Bild 2). Ist der Drehfaktor auf 10 gesetzt, sieht man nur noch einen vertikalen Strich. Das Sprite wurde um 90 Grad gedreht. Wird der Drehfaktor weiter bis maximal 20 erhöht, so wird das Sprite nicht nur breiter, sondern gleichzeitig an der Drehachse gespiegelt. Durch diesen Effekt läßt sich das Sprite tatsächlich von Null bis 180 Grad drehen.

Gerastertes Koordinatengitter mit nummerierten Achsen und den Markierungen X und Y
Bild 1. Um diese Achsen können Sie Ihre Sprites drehen
Vier Reihen gestauchter Gesichts-Sprites, beschriftet mit Vertikal und Horizontal
Bild 2. Durch die Kombination beider Stauchungen lassen sich effektvolle Bewegungen realisieren

Spritenummer

Die Spritenummer läßt das automatische Umschalten der Sprite-Zeiger auf bestimmte Sprites zu. So kann man eine kontinuierliche Bewegung erzeugen. Wird eine Sprite-Nummer zwischen Null und Sieben gewählt, schaltet der entsprechende Sprite-Zeiger um (bei Null wäre dies die Speicherzelle 2040, bei Eins 2041 und so weiter).

Die Wirkungs- und Funktionsweise von »Shrinksprite« ist in dem Demo (Listing 2) beschrieben. Laden Sie zuerst das Programm mit dem Namen »Loader« (Listing 3) und starten es mit RUN. Der Rest wird vom Programm erledigt.

Tips für Maschinenprogrammierer

Das Programm (Listing 1) belegt den Speicherbereich von $C000 bis $C33D plus 126 Byte für zwei Sprite-Puffer. Soll die Routine in ein Maschinenprogramm integriert werden, müssen die Speicherzellen $FB, $FC, $FD, $FE und $02 folgende Werte enthalten:

$FB -> Ursprungsblock
$FC -> Zielblock
$FD -> vertikale Stauchung
$FE -> horizontale Stauchung
$02 -> Sprite-Nummer

Anschließend muß »Shrinksprite« mit »JMP $C019« oder »JSR $C019« aufgerufen werden.

Wie funktioniert's

Nach der Parameterübergabe und deren Prüfung auf Richtigkeit wird zuerst das zu verändernde Sprite horizontal gestaucht und im ersten Sprite-Puffer gespeichert. Anschließend wird der Inhalt des Puffers vertikal gestaucht und im zweiten Sprite-Puffer gespeichert. Das Programm kopiert dann den Inhalt des zweiten Sprite-Puffers in den Zielblock und setzt den Sprite-Zeiger auf den Zielblock.

(B. Reike/ah)
PROGRAMM : SHRINKSPRITE   C000 C33E
-----------------------------------
C000 : 20 9B B7 86 FB 20 9B B7   4B
C008 : 86 FC 20 9B B7 86 FD 20   70
C010 : 9B B7 86 FE 20 9B B7 86   D3
C018 : 02 A9 17 C5 FE 90 06 A9   4D
C020 : 14 C5 FD B0 01 60 A9 00   66
C028 : 85 25 A5 FC 85 24 A0 06   51
C030 : 06 24 26 25 88 D0 F9 20   AE
C038 : 01 C1 A9 00 85 5A A5 FD   42
C040 : C9 0B 90 24 38 A9 14 E5   24
C048 : FD AA A9 00 CA 30 06 18   7B
C050 : 69 0B 4C 4C C0 18 65 5A   F3
C058 : AA BD 0F C1 85 59 A9 3C   1F
C060 : 38 E5 59 85 59 4C 7E C0   05
C068 : A6 FD A9 00 CA 30 06 18   EE
C070 : 69 0B 4C 6C C0 18 65 5A   17
C078 : AA BD 0F C1 85 59 A2 03   B1
C080 : A9 00 18 65 5A CA D0 FA   11
C088 : 85 5B A9 3D 85 5C A9 C3   36
C090 : 85 5D 18 A5 5C 65 59 85   E0
C098 : 5C 90 02 E6 5D A9 00 85   C8
C0A0 : 5F A5 FB 85 5E A0 06 06   90
C0A8 : 5E 26 5F 88 D0 F9 18 A5   8B
C0B0 : 5E 65 5B 85 5E 90 02 E6   89
C0B8 : 5F 20 F5 C0 06 59 A5 5C   37
C0C0 : 38 E5 59 B0 02 C6 5D 18   53
C0C8 : 69 3C 90 02 E6 5D 85 5C   DC
C0D0 : 06 5B A5 5E 38 E5 5B B0   3A
C0D8 : 02 C6 5F 18 69 3C 90 02   D7
C0E0 : E6 5F 85 5E 20 F5 C0 E6   25
C0E8 : 5A A9 0B C5 5A F0 03 4C   64
C0F0 : 3E C0 4C 88 C1 A0 02 B1   3F
C0F8 : 5E 11 5C 91 5C 88 10 F7   62
C100 : 60 A0 3E A9 00 99 3D C3   BE
C108 : 99 7C C3 88 10 F7 60 00   23
C110 : 03 06 09 0C 0F 12 15 18   E0
C118 : 1B 1E 03 06 09 0C 0F 12   15
C120 : 12 15 18 1B 1E 06 09 0C   75
C128 : 0C 0F 12 15 18 18 1B 1E   CE
C130 : 09 0C 0C 0F 12 15 15 18   73
C138 : 1B 1B 1E 0C 0F 0F 12 12   C0
C140 : 15 18 18 1B 1B 1E 0F 12   CE
C148 : 12 15 15 18 18 1B 1B 1E   30
C150 : 1E 12 12 15 15 18 18 18   41
C158 : 1B 1B 1E 1E 15 15 18 18   D7
C160 : 18 1B 1B 1B 1B 1E 1E 18   7B
C168 : 18 18 1B 1B 1B 1B 1B 1E   EA
C170 : 1E 1E 1B 1B 1B 1B 1B 1E   FB
C178 : 1E 1E 1E 1E 1E 1E 1E 1E   78
C180 : 1E 1E 1E 1E 1E 1E 1E 1E   80
C188 : A9 00 8D A8 C2 8D A9 C2   6E
C190 : EE A9 C2 A9 0B C5 FE B0   75
C198 : 0C A9 17 38 E5 FE 85 FE   B0
C1A0 : A9 01 8D A8 C2 A9 00 85   C7
C1A8 : 57 A9 07 C5 57 B0 1A A9   05
C1B0 : 01 85 59 38 A5 57 E9 08   9E
C1B8 : AA BD C1 C1 85 5A 4C D4   EF
C1C0 : C1 01 02 04 08 10 20 40   05
C1C8 : 80 A9 02 85 59 A6 57 BD   F2
C1D0 : C1 C1 85 5A AD A8 C2 F0   2B
C1D8 : 0E A5 5A 20 99 C2 85 5A   CE
C1E0 : A6 59 BD AA C2 85 59 A6   02
C1E8 : FE A9 00 CA 30 06 18 69   7B
C1F0 : 0C 4C EB C1 18 65 57 AA   B5
C1F8 : BD AD C2 85 5B A9 02 85   03
C200 : 5C A5 5B 29 10 F0 02 C6   49
C208 : 5C A5 5B 29 0F AA BD C1   F4
C210 : C1 85 5D A9 00 85 5E 18   F6
C218 : A5 5E 65 59 A8 B9 3D C3   46
C220 : 25 5A C9 00 F0 0E 18 A5   10
C228 : 5E 65 5C A8 B9 7C C3 05   FE
C230 : 5D 99 7C C3 18 A5 5E 69   EC
C238 : 03 85 5E A9 3C C5 5E 90   57
C240 : 03 4C 17 C2 AD A9 C2 F0   9D
C248 : 0B A9 00 8D A9 C2 20 7C   04
C250 : C2 4C 13 C2 A9 01 8D A9   82
C258 : C2 E6 57 A9 0B C5 57 90   F6
C260 : 03 4C A9 C1 A0 3E B9 7C   08
C268 : C3 91 24 88 10 F8 A9 07   8B
C270 : C5 02 90 07 A6 02 A5 FC   46
C278 : 9D F8 07 60 A5 5A 20 99   40
C280 : C2 85 5A A5 5D 20 99 C2   13
C288 : 85 5D A6 59 BD AA C2 85   D8
C290 : 59 A6 5C BD AA C2 85 5C   9B
C298 : 60 A2 00 C9 80 F0 05 0A   3A
C2A0 : E8 4C 9B C2 BD C1 C1 60   9F
C2A8 : 00 00 02 01 00 00 01 02   51
C2B0 : 03 04 05 06 07 10 11 12   11
C2B8 : 13 01 02 03 04 05 06 06   B9
C2C0 : 07 10 11 12 13 02 03 04   AB
C2C8 : 04 05 06 07 10 11 12 12   A7
C2D0 : 13 03 04 04 05 06 07 07   91
C2D8 : 10 11 12 12 13 04 05 05   A7
C2E0 : 06 07 07 10 11 11 12 13   36
C2E8 : 13 05 06 06 07 07 10 10   C9
C2F0 : 11 12 12 13 13 06 06 07   79
C2F8 : 07 10 10 11 11 12 12 13   3E
C300 : 13 07 07 10 10 11 11 11   4B
C308 : 12 12 13 13 13 10 10 11   5F
C310 : 11 11 12 12 12 12 13 13   95
C318 : 13 11 11 11 12 12 12 12   38
C320 : 13 13 13 13 13 12 12 12   12
C328 : 12 13 13 13 13 13 13 13   27
C330 : 13 13 13 13 13 13 13 13   30
C338 : 13 13 13 13 13 00         4C
Listing 1. Hauptprogramm »Shrinksprite«
10 rem *******************
20 rem * shrinksprite 64 *
30 rem *      demo       *
40 rem *   written by    *
50 rem * burkhard reike  *
60 rem *  in march '86   *
70 rem *******************
80 poke53280,0:poke53281,0
90 print"{clr}{grn}            bitte warten !":poke55,0:poke56,60
100 forx=0to318:reada:poke16064+x,a:next
110 clr:v=53248:ad=49152:forx=0to9:pokev+x,0:next:pokev+23,0:pokev+29,0
120 forx=0to4:s(x)=251+x:s1(x)=246+x:pokev+39+x,x+1:nextx
130 print"{clr}":forx=0to3:pokev+2*x,45*x+100:nextx
140 forx=0to3:sysad,s(x),s1(x),10,10,x:pokev+21,peek(v+21)or2^x
150 fory=1to100:pokev+2*x+1,y:nexty
160 fory=9to0step-1:sysad,s(x),s1(x),y,y,x:nexty:nextx
170 print"{home}{down}{down}{down}{down}{down}{down}{down}{down}{down}{down}         fuer 'shrinksprite 64'"
180 print"{down}{down}{down}{down}{down}{down}{down}             {rvon}taste druecken{rvof}"
190 fors=0to3:forx=1to23:sysad,s(s),s1(s),0,x,s:geta$:ifa$<>""then220
200 nextx:forx=23to0step-1:sysad,s(s),s1(s),0,x,s:geta$:ifa$<>""then220
210 nextx,s:goto190
220 forx=0to7:pokev+x,0:nextx:print"{clr}"
230 printspc(12)"shrinksprite 64"
240 printspc(12)"***************"
250 print"shrinksprite 64 hat die faehigkeit,durcheinen sys-aufruf und para";
260 print"meteruebergabe einen sprite horizontal und vertikal zu stauchen";
270 print",wobei der urspruengliche spriteerhalten bleibt,da der gestauchte";
280 print" spritein einem neuen spriteblock abgelegt     wird.das programm ";
290 print"kann auf wunsch den   spritezeiger auf den neuen block setzen.":print
300 gosub1060:print"{clr}":printspc(13)"{rvon}die parameter{rvof}"
310 print"der aufruf der routine sieht folgendermassen aus:"
320 a$(1)="{del}routine":a$(2)="sprite1":a$(3)="sprite2":a$(4)="vertikal"
330 a$(5)="horizontal":a$(6)="nummer"
340 print:print:q=7:gosub1070:gosub1060:print"{clr}"
350 q=1:gosub1070
360 print"die adresse nach dem sysaufruf ist stetsder anfang der routine ";
370 print"'shrinksprite 64'":print:gosub1060:print"{clr}":q=2:gosub1070
380 print"nach dem ersten komma kommt die nummer  des spriteblocks,der ";
390 print"veraendert werden  soll (0-255).":print:gosub1060:print"{clr}":q=3
400 gosub1070:print"hiernach folgt die nummer des sprite-   blocks";
410 print",in dem der veraenderte sprite ab-gelegt werden soll.dieser block";
420 print" darf mitdem ersten block identisch sein.":print:gosub1060
430 print"{clr}":q=4:gosub1070:print"es folgen nun zwei parameter,die";
440 print" fuer   das ausmass der stauchung verantwortlichsind.zuerst kommt ";
450 print"grad der vertikalen   stauchung (0-20).":print:gosub1060:q=5:print"{clr}"
460 gosub1070:print"dann der grad der horizontalen stauchung(0-23).zu den ";
470 print"parametern der stauchungengibt es spaeter noch weitere ausfuehrungen."
480 gosub1060:print"{clr}":q=6:gosub1070
490 print"die spritenummer (0-7) bewirkt,dass der entsprechende zeiger auf ";
500 print"den spriteblockdes sprites,der veraendert werden soll, auf den neuen";
510 print" block geschaltet wird(bei 0 wuerde zum beispiel der zeiger 2040"
520 print"veraendert werden)."
530 print"ist die nummer groesser als 7,so wird {rght} diese umschaltung unterdrue";
540 print"ckt.":gosub1060
550 print"{clr}veraendern sie nun mit hilfe der        funktionstasten den sprite:"
560 print"{rvon}f1{rvof} - der grad der vertikalen stauchung       wird erhoeht (bis 20)"
570 print"{rvon}f3{rvof} - der grad der vertikalen stauchung       wird niedriger (bis 0)"
580 print"{rvon}f5{rvof} - der grad der horizontalen stauchung     wird erhoeht (bis 23)"
590 print"{rvon}f7{rvof} - der grad der horizontalen stauchung     wird niedriger (bis 0)"
600 print"{rvon}return{rvof} - verlassen dieses programmteils"
610 pokev+8,170:pokev+9,180:poke2044,s(4):pokev+21,16:pokev+43,4
620 print"{down}{down}{down}":a$="00":b$="00":a=0:b=0
630 print"{up}      vertikal:{rvon}"+a$+"{rvof}     horizontal:{rvon}"+b$+"{rvof}"
640 c$="":getc$:ifc$=""then640
650 ifasc(c$)=13then730
660 ifc$="{f1}"thenifa<20thena=a+1
670 ifc$="{f3}"thenifa>0thena=a-1
680 ifc$="{f5}"thenifb<23thenb=b+1
690 ifc$="{f7}"thenifb>0thenb=b-1
700 sysad,s(4),s1(4),a,b,4:a$=right$(str$(a),2):ifa<10thena$="0"+right$(a$,1)
710 b$=right$(str$(b),2):ifb<10thenb$="0"+right$(b$,1)
720 goto630
730 pokev+8,0:print"{clr}mit shrinksprite 64 kann man also ohne  grossen aufwand ";
740 print"einen sprite effektvoll veraendern:er veraendert seine groesse"
750 print"(seine entfernung),wird duenner oder    dreht sich sogar."
760 print"durch die einfache und schnelle para-   meteruebergabe kann jeder ";
770 print"anwender      shrinksprite 64 in seinen eigenen pro-  grammen verwe";
780 print"nden.":gosub1060:print"{clr}wussten sie schon,wie die welt aus der"
790 print"sicht von pacman aussieht ?"
800 forx=1to4000:nextx
810 print"{clr}{down}{down}{down}{down}{down}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}PM             NO{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}{CBM-Y}";
820 print"            {CBM-N} M           N {CBM-H}"
830 print"            {CBM-N}  M         N  {CBM-H}"
840 print"            {CBM-N}  {CBM-N}        N   {CBM-H}"
850 print"            {CBM-N}  {CBM-N}PM     N    {CBM-H}"
860 print"            {CBM-N}  {CBM-N}{CBM-N} M   N     {CBM-H}"
870 print"            {CBM-N}  {CBM-N}{CBM-N}  M N      {CBM-H}"
880 print"            {CBM-N}  {CBM-N}{CBM-N}  {CBM-N} {CBM-H}      {CBM-H}"
890 print"            {CBM-N}  {CBM-N}{CBM-N}  N M      {CBM-H}"
900 print"            {CBM-N}  {CBM-N}{CBM-N} N   M     {CBM-H}"
910 print"            {CBM-N}  {CBM-N}{SHIFT-@}N     M    {CBM-H}"
920 print"            {CBM-N}  {CBM-N}        M   {CBM-H}"
930 print"            {CBM-N}  N         M  {CBM-H}"
940 print"            {CBM-N} N           M {CBM-H}"
950 print"{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{SHIFT-@}N             ML{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}{CBM-P}":forx=1to800:nextx
960 sysad,s(4),s1(0),4,5,0:sysad,s(4),s1(4),10,10,4:pokev+8,175:pokev+9,140:a=0
970 forx=9to0step-1
980 a=a+1.3:sysad,s(4),s1(4),x,x,4:pokev+9,140+a:nextx:poke198,0
990 pokev+23,1:pokev+29,1:pokev,164:pokev+1,147
1000 pokev+39,4:pokev+21,1:poke198,0
1010 a=0:forx=3to0step-1:a=a+3:sysad,s(4),s1(0),x,x+1,0:poke198,0
1020 pokev+1,147+a:nextx:sysad,s(4),s1(0),0,0,0:x=0
1030 forq=1to25:sysad,s(4),s1(0),0,x,0:x=23-x:fory=1to50:nexty:nextq:print"{clr}"
1040 goto110
1050 end
1060 printspc(17)"{rvon}taste{rvof}":poke198,0:wait198,255:return
1070 forx=1to6:en$(x)="":an$(x)="":next:an$(q)="{rvon}":en$(q)="{rvof}"
1080 print"sys ";:forx=1to6:print",";an$(x)a$(x)en$(x);:next:print:print:return
1090 data0,0,0,127,254,0,127,255,128,127,255,192,63,255,224,63,255,240,63,7
1100 data240,62,1,248,62,1,248,62,0,248,62,0,248,62,0,248,62,1,248,62,3,248
1110 data63,7,240,63,255,240,127,255,224,127,255,192,127,255,128,127,254,0,0
1120 data0,0,0,0,0,0,63,255,240,127,255,248,127,255,248,63,255,240,62,0,0,62
1130 data0,0,62,0,0,63,255,192,63,255,224,63,255,224,63,255,192,62,0,0,62,0
1140 data0,62,0,0,62,0,0,63,255,240,127,255,248,127,255,248,63,255,240,0,0,0
1150 data0,0,0,0,60,0,60,127,0,254,127,195,254,127,255,254,127,255,254,125,255
1160 data190,124,126,62,124,126,62,124,60,62,124,24,62,124,0,62,124,0,62,124
1170 data0,62,124,0,62,124,0,62,124,0,62,124,0,62,124,0,62,124,0,62,56,0,28
1180 data0,0,0,0,0,254,0,3,255,128,7,255,192,15,255,224,31,255,240,31,199,240
1190 data63,129,248,63,1,248,62,0,248,62,0,248,62,0,248,63,1,248,63,3,248,31
1200 data199,240,31,255,240,15,255,224,7,255,192,3,255,128,0,254,0,0,0,0,0,1
1210 data255,128,15,255,240,31,255,248,63,255,252,60,126,60,121,188,30,115
1220 data216,14,241,153,143,240,27,207,248,61,159,252,126,63,255,255,255,254
1230 data237,207,252,76,143,248,0,15,250,49,47,255,51,191,255,255,255
1240 data247,60,239,226,24,71,66,24,66
Listing 2. Demoprogramm zu »Shrinksprite«.
10 a$=chr$(34):print"{clr}{down}{down}{down}lO"a$"shrinksprite"a$",8,1":print:print:print:print
20 print"new":print:print:print"lO"a$"demo"a$",8":print:print:print
30 print:print"run":print"{home}":poke198,4:forx=0to3:poke631+x,13:nextx
Listing 3. »Lader« für das Demoprogramm
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →