C 64
Listing des Monats

Trickfilm mit dem C 64

In die vierte Dimension, die bewegte dreidimensionale Grafik, dringen Sie mit diesem Programm vor.
Sie können so mit einfachsten Mitteln Trickfilme mit verblüffenden Eigenschaften erstellen.

Das Bild kann »gekippt« werden
Auch dreidimensionale Körper können dargestellt werden
Vier Phasen der Bewegung

Die Idee zu diesem Programm kam uns, als wir zum zweiten Mal die Sendung »Das Bild, das aus dem Rechner kam« sahen.

Die erste noch in Comal geschriebene Version berechnete jeweils ein Bild und zeichnete es sofort. Das Ergebnis: nur alle 7 Sekunden ein Bild! Auch als erst alle Linien berechnet und dann gezeichnet wurden, konnte von einem flüssigen Bewegungsablauf keine Rede sein. Bei der jetztigen Version wird der Teil des Zeichnens von einer Maschinencode-Routine übernommen, die eine Geschwindigkeit von 3 bis 10 Bilder/s erlaubt. Die Unterschiede gegenüber anderen Trickfilmgeneratoren:

(Dirk und Armin Biernaczyk/rg)

In die vierte Dimension, die bewegte dreidimensionale Grafik, dringen Sie mit unserem Listing des Monats vor.

Der »3D-Movie Maker« muß in zwei Teilen eingegeben werden: zuerst das Maschinenprogramm, dann der Basic-Teil. Wenn das Maschinenprogramm eingegeben und gestartet wurde, so speichert es sich, falls kein Prüfsummenfehler auftrat, selbst als »TRICK.OBJ« ab. Man braucht sich nun nicht mehr darum zu kümmern. Bei dem Basic-Teil, der nun eingegeben werden kann, dürfen alle REM-Zeilen ersatzlos wegfallen. Beim Start des Basic-Teils wird automatisch der Maschinenteil, der sich auf Diskette befinden sollte, nachgeladen.

Bedienung - Eingabe des Körpers

Vor der Benutzung des Programmes, müssen die Punkte Verbindungs- und Bewegungsvorschrift des Körpers in den DATA-Zeilen ab 8000 festgelegt werden. Dies ist notwendig, damit bei Änderungen oder einem erneuten Start nicht alles wieder neu eingegeben werden muß. Die DATA-Zeilen, die das Listing momentan enthält, erzeugen den auf dem Bildschirm herumfliegenden Schriftzug »64’er«. Die Punkte werden mit X, Y und Z-Koordinaten eingegeben. Als Endmarke dient hier dreimal die 1000. Bei der Verbindungsvorschrift wird jeweils der Anfangs- und Endpunkt angegeben zum Beispiel: Von Punkt 1 nach Punkt2 = DATA 1,2. Hier dient zweimal die 1000 als Endmarkierung.

Beispiel: Man will ein Kreuz erzeugen.

Punkte:DATA0,10,0,10,0,0,-10,0
DATA —10, 0,0, 1000,1000,1000
Verbindungsvorschrift:DATA 1,3,2,4,1000,1000

Bei der Bewegungsvorschrift ist es allerdings etwas komplizierter. Hier müssen zweimal drei Verschiebungsarten, drei Drehungsarten und die Dauer des Vorgangs angegeben werden. Zuerst kommt die erste Verschiebung in X-, Y- und Z-Richtung, dann die Drehung um die drei Achsen, nun die zweite Verschiebung und zum Schluß die Dauer des Ganzen. Diese Reihenfolge hat folgenden Sinn:

Wird zuerstverschoben und dann gedreht, dreht sich die Figur um den Bildschirmmittelpunkt. Bei umgekehrter Reihenfolge dreht sich die Figur an beliebiger Stelle um ihren eigenen Mittelpunkt. Hier ein Beispiel einer DATA-Zeile: DATA 0,0,0,5,0,0, 0,5,0, 10

Die Figur bewegt sich 10 Bilder lang um jeweils 5 Stellen nach oben und dreht sich dabei um jeweils fünf Grad um die X-Achse. Einen Zoomeffekt erreicht man durch Verschieben in der Z-Achse, so kann man zum Beispiel mit DATA 0,0,0,0,0,0,0,0,1,50 eine Figur langsam vergrößern. Hier bildet einmal die 1000 die Schlußmarkierung. Um die vielen verschiedenen Möglichkeiten der Bewegung zu entdecken, lohnt es sich, die verschiedenen Kombinationen auszuprobieren (und dabei mit einfachen Bewegungen anzufangen).

Bedienung — Ablauf des Programms

Der »3D-Movie-Maker« stellt vier Menüpunkte zur Wahl:

Der Algorithmus

Das eigentliche Kernstück des Programms ist ein Algorithmus, der die Punkte um einen Winkel dreht, die X-, Y- und Z-Koordinaten in Bildschirmkoordinaten umrechnet und dann die außerhalb liegenden Teile der Linien wegstreicht. Beim Drehen (hier um die Z-Achse) werden erst X- und Y-Koordinaten in Radius und Winkel (im Bogenmaß) umgerechnet; bezogen auf den Koordinatenursprung (siehe Bild 1). Nun wird der Winkel, um den gedreht werden soll, addiert und die neuen Koordinaten werden aus dem neuen Winkel und dem Radius errechnet (siehe Bild 2).

Bild 1. Angabe der Winkel in Bogenmaß
Bild 2. Berechnung der neuen Koordinaten

Beim Umrechnen in Bildschirmkoordinaten wird einfach die Z-Koordinate auf die X und Y-Koordinate so aufgerechnet, daß Punkte, die weiter vorne liegen, vom Mittelpunkt wegrücken. Außerdem wird der Koordinatenursprung in die Bildschirmmitte verlegt. Durch dieses Verfahren wird die Figur mit einem Fluchtpunkt in der Mitte des Bildschirms dargestellt Das nun folgende Wegstreichen der außerhalb liegenden Linien und Linienstücke geschieht mit Hilfe einer Gradengleichung. Falls nur Teile der Geraden außerhalb des Bildschirms liegen, wird der äußerste Wert für X beziehungsweise Y angenommen und die fehlende Koordinate errechnet (siehe Bild 3).

Beschreibung der Maschinenroutine

Die Zeichenroutine des »3D-Movie-Makers« übernimmt die Verwaltung der Grafik und ist, zum Erreichen eines Trickfilmeffekts, ganz auf Geschwindigkeit ausgelegt Aus diesem Grund erhielt sie die folgenden Merkmale:

Das wichtigste Mittel zur Erzeugung eines flüssigen Bilderablaufs und die Grundidee der Routine ist jedoch das »verdeckte Zeichnen«. Dafür werden zwei Bitmaps benötigt (bei unserem Programm ab $A000 und $E000). Während nun eine der beiden zu sehen ist, wird auf der anderen gezeichnet. Nun wird das neue Bild sichtbar gemacht und das alte, welches nicht mehr zu sehen ist, wird gelöscht. Dieser Vorgang wiederholt sich, bis alle Bilder abgearbeitet sind. Hier noch eine Anmerkung: die Lineroutine haben wir mit einigen Änderungen dem Artikel »Ein schneller Drawline-Algorithmus« aus dem 64’er, 4/84 entnommen. Die Funktion läßt sich am besten dort nachvollziehen.

(Armin und Dirk Biernaczyk/rg)

Felder:

X(I), Y(I), Z(I) Originalkoordinaten der Figur aus den DATA-Zeilen
X1(I), Y1(I), Z(I) Koordinaten beim Rechnen und für das POKEN
P1(I), P2(I) Verbindungsvorschriften aus den DATA-Zeilen

Normale Variablen:

PO Speicherpointer für fertige Daten
Q-1 Zähler für fertige Bilder
A2 Anzahl der Linien pro Bild
A1 Anzahl der Punkte pro Bild
AN Anzahl der Bilder
P1, P2, P3, P4, PB, PA Variablen zur Berechnung des zu löschenden Bildschirmbereichs
WX, WY, WZ, XA, YA, ZA, XB, YB, ZB Variablen für die Drehbewegungen und Verschieben (werden bei jedem Bild auf W1, ... aufaddiert)
W1, W2, W3, X1, Y1, Z1, X2, Y2, Z2 Momentane Lage des Körpers
Variablenliste
Listing »TRICK.OBJ«. Verwenden Sie bitte zur Eingabe den MSE
100 rem -----------------------------
105 rem -- 3d-movie-maker          --
110 rem -- ein programm von:       --
115 rem -- dirk & armin biernaczyk --
120 rem -- an der papenburg 41     --
125 rem -- 4630 bochum 6           --
130 rem -- tel.: //////            --
135 rem -----------------------------
140 rem (c) 1985 by armin & dirk
145 rem             biernaczyk
150 :
160 rem ------------------
170 rem --- hauptmenue ---
180 rem ------------------
190 :
191 ifa=0thena=1:load"trick.obj",8,1
192 :
195 poke56,50:clr:rem speicher herab.
200 printchr$(147)
210 printspc(10)"** 3d-movie-maker **"
220 print:print:print:print
230 printspc(9)"1 - grafik erstellen"
235 print
240 printspc(9)"2 - grafik abspielen"
245 print
250 printspc(9)"3 - grafik laden"
255 print
260 printspc(9)"4 - grafik abspeichern"
262 print
264 printspc(9)"5 - ende"
265 :
270 getw$:ifw$<"1"orw$>"5"then270
280 w=val(w$)
285 ifw=5thenend
290 onwgosub1040,5040,6040,7040
300 goto200
310 :
315 :
320 :
1000 rem -----------------
1010 rem --- erstellen ---
1020 rem -----------------
1030 :
1040 gosub4540   :rem variablen
1050 gosub4040   :rem einlesen
1060 printchr$(147)"fertige bilder: "
1061 ifan*(a2*6+2)<23000then1080
1062 print"zu wenig speicherplatz"
1063 poke198,0:wait198,1:return
1070 :
1080 forq=1toan  :rem anzahl der bilder
1085 gosub3040   :rem bewegen
1090 gosub2040   :rem berechnen
1095 getta$:ifta$=" "thenifq>1thensys49152,q-1,a2,1
1100 next
1110 q=q-1
1120 return
1130 :
1135 :
2000 rem -----------------
2010 rem --- berechnen ---
2020 rem -----------------
2030 :
2040 rem --- verschieben1 ---
2050 :
2060 fori=1toa1
2070 x1(i)=x(i)+x1:y1(i)=y(i)+y1
2080 z1(i)=z(i)+z1
2090 next
2100 :
2110 rem --- drehen ---
2120 :
2130 ifw1=0then2250
2140 fori=1toa1
2150 xd=x1(i):yd=y1(i)
2160 ifxd=0thenxd=1e-20
2165 ifyd=0thenyd=1e-20
2170 r=sqr(xd*xd+yd*yd)
2180 w=atn(yd/xd)
2190 ifxd>0andyd<0thenw=w+~*2:goto2210
2200 ifxd<0thenw=w+~
2210 w=w+w1
2220 y1(i)=sin(w)*r:x1(i)=cos(w)*r
2230 next
2240 :
2250 ifw2=0then2370
2260 fori=1toa1
2270 zd=z1(i):yd=y1(i)
2280 ifzd=0thenzd=1e-20
2285 ifyd=0thenyd=1e-20
2290 r=sqr(zd*zd+yd*yd)
2300 w=atn(yd/zd)
2310 ifzd>0andyd<0thenw=w+~*2:goto2330
2320 ifzd<0thenw=w+~
2330 w=w+w2
2340 y1(i)=sin(w)*r:z1(i)=cos(w)*r
2350 next
2360 :
2370 ifw3=0then2510
2380 fori=1toa1
2390 zd=z1(i):xd=x1(i)
2400 ifzd=0thenzd=1e-20
2405 ifxd=0thenxd=1e-20
2410 r=sqr(zd*zd+xd*xd)
2420 w=atn(xd/zd)
2430 ifzd>0andxd<0thenw=w+~*2:goto2450
2440 ifzd<0thenw=w+~
2450 w=w+w3
2460 x1(i)=sin(w)*r:z1(i)=cos(w)*r
2470 next
2480 :
2490 rem --- umrechnen ---
2500 :
2510 fori=1toa1
2530 x1(i)=(x1(i)+x2)*1.01^(z1(i)+z2)
2540 y1(i)=(y1(i)+y2)*1.01^(z1(i)+z2)
2560 next
2565 rem 1.01 kann leicht geaendert
2567 rem werden
2580 :
2590 pa=0:pb=199
2600 po=po-2
2601 rem -----------------------------
2602 rem --- ubergetretene linien  ---
2603 rem --- berechnen und poken   ---
2604 rem -----------------------------
2610 fori=1toa2
2620 x0%=x1(p1(i)):y1%=y1(p1(i))
2630 x2%=x1(p2(i)):y2%=y1(p2(i))
2640 x1%=0:x3%=0:me=0
2641 ifx0%> 159andx2%> 159then2760
2642 ifx0%<-159andx2%<-159then2760
2643 ify1%<- 99andy2%<- 99then2760
2644 ify1%>  99andy2%>  99then2760
2650 ify1%=y2%then2711
2655 ifx2%=x0%then2690
2660 m=(y2%-y1%)/(x2%-x0%)
2670 b=-m*x0%+y1%
2680 goto2720
2690 ify1%>99ory1%<-99theny1%=99*sgn(y1%)
2700 ify2%>99ory2%<-99theny2%=99*sgn(y2%)
2710 goto 2760
2711 ifx0%>159orx0%<-159thenx0%=159*sgn(x0%)
2712 ifx2%>159orx2%<-159thenx2%=159*sgn(x2%)
2713 goto 2760
2720 ifx0%>159orx0%<-159thenx0%=159*sgn(x0%):y1%=m*x0%+b
2730 ifx2%>159orx2%<-159thenx2%=159*sgn(x2%):y2%=m*x2%+b
2740 ify1%>99ory1%<-99theny1%=99*sgn(y1%):x0%=(y1%-b)/m
2750 ify2%>99ory2%<-99theny2%=99*sgn(y2%):x2%=(y2%-b)/m
2760 ify1%>99ory1%<-99thenx1%=255:x0%=0:y1%=0:y2%=0:x2%=0:goto2810
2770 ifx0%>159orx0%<-159thenx1%=255:x0%=0:y1%=0:y2%=0:x2%=0:goto2810
2780 :
2790 x0%=x0%+160:x2%=x2%+160
2791 y1%=y1%+100:y2%=y2%+100
2793 ify1%>pathenpa=y1%
2794 ify2%>pathenpa=y2%
2795 ify1%<pbthenpb=y1%
2796 ify2%<pbthenpb=y2%
2799 ifx0%>255thenx0%=x0%-256:x1%=1
2800 ifx2%>255thenx2%=x2%-256:x3%=1
2805 :
2810 pokepo,x0%:pokepo-1,x1%
2820 pokepo-2,y1%:pokepo-3,x2%
2830 pokepo-4,x3%:pokepo-5,y2%
2840 po=po-6
2850 next
2860 :
2862 ifpa<pbthenpa=199:pb=0
2863 pa=40*((paor7)+1)/256+1
2864 pb=40*(pband248)/256
2866 poke po+6*a2+2,int(p1)-int(p3)
2868 poke po+6*a2+1,p3
2870 p1=p2:p2=pa:p3=p4:p4=pb
2872 printchr$(19)spc(16)q
2880 return
2890 :
2900 :
3000 rem ---------------
3010 rem --- bewegen ---
3020 rem ---------------
3030 :
3040 ife=0then3100
3050 w1=w1+wz:w2=w2+wx:w3=w3+wy
3060 x1=x1+xa:y1=y1+ya:z1=z1+za
3070 x2=x2+xb:y2=y2+yb:z2=z2+zb
3080 e=e-1:return
3090 :
3100 read xa,ya,za,wx,wy,wz,xb,yb,zb,e
3110 wx=wx*~/180:wy=wy*~/180
3120 wz=wz*~/180:ya=-ya:yb=-yb
3130 goto3050
3140 :
3150 :
4000 rem ----------------
4010 rem --- einlesen ---
4020 rem ----------------
4030 :
4040 i=0
4050 i=i+1
4060 read x(i),y(i),z(i)
4070 y(i)=-y(i)
4080 ifx(i)<1000then4050
4090 a1=i-1
4100 i=0
4110 i=i+1
4120 read p1(i),p2(i)
4130 ifp1(i)<1000then4110
4140 a2=i-1
4150 :
4155 an=0
4157 reada:ifa=1000then4180
4160 fori=1to9:reada:next
4170 an=an+a:goto4157
4180 restore
4190 reada,a,a
4200 ifa<1000then4190
4210 reada,a
4220 ifa<1000then4210
4230 :
4240 printchr$(147)"bilderzahl  "an
4250 printchr$(19)spc(11);:input i
4260 ifi>255ori>anthen4240
4270 an=i
4280 return
4290 :
4300 :
4500 rem -----------------
4510 rem --- variablen ---
4520 rem -----------------
4530 :
4533 rem nach bedarf dimensionieren
4536 :
4540 dim x(50),y(50),z(50)
4560 dim x1(50),y1(50),z1(50)
4570 dim p1(50),p2(50)
4580 po=35839:p1=32:p2=32:p3=0:p4=0
4590 return
4600 :
4605 :
5000 rem -----------------
5010 rem --- abspielen ---
5020 rem -----------------
5030 :
5040 ifq>0anda2>0then5090
5050 printchr$(147):print:print:print
5060 printspc(5)"es gibt keine grafik"
5070 poke198,0:wait198,1:poke198,0
5080 return
5090 input"{clr}wievile durchlauefe";du
5091 ifdu>255ordu<1then5090
5092 print"{home}{down}{down}wieviele bilder     "q
5093 print"{up}"spc(19);:inputi
5094 ifi>qori<1then5092
5100 :
5105 sys49152,i,a2,du:return
5110 :
6000 rem -------------
6010 rem --- laden ---
6020 rem -------------
6030 :
6040 printchr$(147):print:print:print:print
6050 input"   filename: ";na$
6055 ifna$="m"thenreturn
6060 open2,8,2,na$+".gra,s,r"
6070 open1,8,15:input#1,fe$
6080 iffe$="00"then6090
6082 close1:close2:goto6040
6090 get#2,q$,a2$
6100 q=asc(q$):a2=asc(a2$)
6110 ad=35839-q*(a2*6+2)
6140 close2:close1
6150 ah=int(ad/256):al=ad-ah*256
6160 a$=na$+".gra,s"
6170 fori=51000to51000+len(a$)-1
6180 pokei,asc(mid$(a$,i-50999,1))
6190 next
6200 poke183,len(a$)
6210 poke187,56:poke188,199
6220 poke185,0:poke186,8:poke147,0
6570 poke195,al:poke196,ah
6580 sys62648
6590 return
6600 :
6610 :
6620 :
7000 rem -------------------
7010 rem --- abspeichern ---
7020 rem -------------------
7030 :
7040 ifq>0anda2>0then7090
7050 printchr$(147):print:print:print
7060 printspc(5)"es gibt keine grafik"
7070 poke198,0:wait198,1:poke198,0
7080 return
7090 printchr$(147):print:print:print
7100 input"    filename: ";na$
7105 ifna$="m"thenreturn
7110 open2,8,2,na$+".gra,s,w"
7120 open1,8,15:input#1,fe$
7130 iffe$="00"then7140
7135 close1:close2:goto7090
7140 print#2,chr$(q);chr$(a2);
7150 fori=35839-q*(a2*6+2)to35839
7160 print#2,chr$(peek(i));:next
7170 close2:close1:return
7175 :
7180 :
7185 :
8000 rem -------------------------
8010 rem --- datas fuer punkte ---
8020 rem -------------------------
8030 :
8040 data -20, 10,0
8050 data -30, 10,0
8060 data -30,-10,0
8070 data -20,-10,0
8080 data -20,  0,0
8090 data -30,  0,0
8100 data -15, 10,0
8110 data -15,  0,0
8120 data - 5, 10,0
8130 data - 5,  0,0
8140 data - 5,-10,0
8150 data  10, 10,0
8160 data   5,  5,0
8170 data  15,-10,0
8180 data   5,-10,0
8190 data   5,  0,0
8200 data  15,  0,0
8210 data  15, -5,0
8220 data   5, -5,0
8230 data  20,-10,0
8240 data  20,  0,0
8250 data  20, -5,0
8260 data  30,  0,0
8900 data 1000,1000,1000
8910 :
9000 rem ----------------------------
9010 rem --- verbindungsvoschrift ---
9020 rem ----------------------------
9030 :
9040 data  1, 2,  2, 3,  3, 4,  4, 5
9050 data  5, 6,  7, 8,  8,10,  9,11
9060 data 12,13, 14,15, 15,16, 16,17
9070 data 17,18, 18,19, 20,21, 22,23
9450 data 1000,1000
9460 :
9500 rem --------------------------
9510 rem --- bewegungsvoschrift ---
9520 rem --------------------------
9530 :
9531 rem xa,ya,za,wx,wy,wz,xb,yb,zb,e
9550 data 0,0,  1 ,0,0,0 ,0,0,  0 ,30
9560 data 0,0,  0 ,0,5,0 ,0,0,  0 ,108
9570 data 0,0,-30 ,0,0,0 ,0,0,-30 ,1
9580 data 0,0,  0 ,5,0,5 ,0,0,.81 ,36
9620 data 1000
Listing »3D-Movie-Maker«. Beachten Sie bitte bei der Eingabe den Checksummer 64.
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →