Sprite

Aus C64-Wiki
Wechseln zu: Navigation, Suche
Begriffsklärung Der Titel dieses Artikels ist mehrdeutig. Weitere Bedeutungen finden sich unter Sprite (Begriffsklärung).

Ein Sprite (wörtlich etwa "Kobold") ist ein auf dem Bildschirm frei bewegbares Grafikelement. Beim C64 hat ein Sprite eine maximale Punktgröße von 24 x 21 Pixel (HiRes) und eine Speichergröße von 63 Bytes. Durch die hohe Flexibilität und Verarbeitungsgeschwindigkeit sind Sprites besonders in Spielen populär, z.B. für Spielfiguren oder Gegner. Auch genutzt werden Sprites zur Darstellung eines Mauszeigers oder Steuerpfeils als Pixelcursor (z.B. in Anwendungen mit GUI zur Bedienung von Fenstermenüs), als Ersatz für den Zeichen-basierten Textcursor oder für die Darstellung von Icons.

(thumbnail)
Sprite Entwurfsblatt

Inhaltsverzeichnis

[Bearbeiten] Einführung

Die Verwaltung der Sprites, die Festlegung der Sprite-Eigenschaften (z.B. Farbe, Größe, Kollisions- oder Prioritätsverhalten) und die Steuerung der Sprites erfolgt über den Grafikspeicherchip VIC(-II) im C64. Dieser unterstützt die Darstellung von max. acht Sprites, entweder in einem hochauflösenden einfarbigen Modus (Hires; 24x21 Pixel; eine aus 16 möglichen Farben pro Sprite) oder einem Mehrfarben-Modus (Multicolor; 12x21 Pixel; drei aus 16 möglichen Farben plus Hintergrundfarbe, wobei zwei Farben allen Sprites gemeinsam sind). Durch spezielle Programmiertechniken in Assembler, die den Raster-Interrupt beeinflussen, können mehr als acht Sprites gleichzeitig angezeigt werden, sog. "Sprite-Multiplexing". Sprites haben eine Aktionsfläche von 512x256 Pixels, wobei das Standard-Bildschirmfenster nur einen Teilbereich dieser Aktionsfläche darstellt.

[Bearbeiten] Spritedaten

(thumbnail)
Daten eines HiRes-Sprites: 0,126,0,3,255,192,7, ....

Ein Spriteblock besteht immer aus 63 Byte Daten und einem Platzhalter-Byte am Ende, also insgesamt 64 Byte. Jedes Byte besteht aus acht Bits, die eine Wertigkeit von 128, 64, 32, 16, 8, 4, 2, 1 aufweisen.

Die Spritedaten sind folgendermaßen aufgebaut:

Byte 1 Byte 2 Byte 3
Byte 4 Byte 5 Byte 6
... ... ...
... ... ...
Byte 61 Byte 62 Byte 63

Die Konstruktion von Sprites ist von Hand recht mühsam, so dass es hierzu bequeme Spriteerstellungsprogramme (Sprite-Editoren) gibt. In BASIC-Erweiterungen (wie z.B. Super Expander 64, Supergrafik, Simons' BASIC) oder in BASIC 7.0 gibt es oftmals eingebaute Sprite-Editoren oder anderweitige Hilfen für die Erstellung von Sprites. Beispielsweise ruft der BASIC-Befehl SPRDEF am C128 (oder beim Super Expander 64) einen Sprite-Editor auf.


Programmierung in Basic

Die Spritedaten werden sinnvollerweise in DATA-Zeilen abgelegt und mit Hilfe einer FOR-NEXT-Schleife, dem READ-Befehl und POKE-Befehl in den Speicher geschrieben:

10 SZ = 12288: REM Spriteblock 192
20 FOR X=0 TO 62: READ Y: POKE SZ+X,Y: NEXT X
30 DATA 255, 128, 16: REM 1. Datenreihe
...(Hier werden 19 weitere DATA-Zeilen eingefügt)
50 DATA 255, 128, 16: REM 21. Datenreihe

[Bearbeiten] Spritedatenzeiger

Speicheradresse dez. / hex. Funktion
2040 / $07F8 Spritedatenzeiger für Sprite 0
2041 / $07F9 Spritedatenzeiger für Sprite 1
2042 / $07FA Spritedatenzeiger für Sprite 2
2043 / $07FB Spritedatenzeiger für Sprite 3
2044 / $07FC Spritedatenzeiger für Sprite 4
2045 / $07FD Spritedatenzeiger für Sprite 5
2046 / $07FE Spritedatenzeiger für Sprite 6
2047 / $07FF Spritedatenzeiger für Sprite 7

Jedes der acht Sprites hat ein Byte, das Spritedatenzeiger (Spritepointer) genannt wird. Dieser Zeiger hat einen Wertebereich von 0 bis 255 und gibt an, wo sich die Spritedaten im Speicher befinden. Daraus ergibt sich ein 16 KByte (256*64 Byte) großer zugänglicher Speicherbereich.


Speicheradressen
Es sind immer die letzten acht Bytes vom 1 KByte (1024 Byte) großen Bildschirmspeichers. Im Normalfall liegen die Adresswerte bei 2040-2047 ($07F8-$07FF).

Anmerkung: Wird die Lage des Bildschirmspeichers verschoben, verändert sich auch die Lage der Spritepointer!


Spriteblöcke
In Assembler ist man grundsätzlich relativ frei bei der Wahl der Spriteblöcke. In Basic darf Spriteblock 11 bedenkenlos verwendet werden. Die Spriteblöcke 13 bis 15, die im Kassettenpuffer ($033C) liegen, können ebenfalls benutzt werden.

Bei "kleineren" Basic-Programmen können auch die obersten Blöcke (255, 254, ...) mit der Speicheradresse (16320, 16256, ...) abwärts verwendet werden. Hier ist aber Vorsicht geboten, da das Basic-Programm samt Variablen in Richtung aufsteigender Adressen und bei Verwendung von Strings der sich ausdehnende String-Heap früher oder später von höheren Adressen absteigend die Spritedaten überschreiben können.


Beispiel
Ein Spriteblock liegt im RAM-Speicher ab Adresse 892 und soll für Sprite 0 verwendet werden.
--> Der Spritedatenzeiger hat daher den Wert 13. (832/64)

POKE 2040,13

[Bearbeiten] Sprites positionieren

Sprite
nummer
Register
X-Position: 0-255
Register
Y-Position: 0-255
0 0 / 53248 / $D000 1 / 53249 / $D001
1 2 / 53250 / $D002 3 / 53251 / $D003
2 4 / 53252 / $D004 5 / 53253 / $D005
3 6 / 53254 / $D006 7 / 53255 / $D007
4 8 / 53256 / $D008 9 / 53257 / $D009
5 10 / 53258 / $D00A 11 / 53259 / $D00B
6 12 / 53260 / $D00C 13 / 53261 / $D00D
7 14 / 53262 / $D00E 15 / 53263 / $D00F
Sprite
nummer
Register X-Position (MSB-Bit mit Wertigkeit 256)
0-7 16 / 53264 / $D010

Jedes der acht Sprites kann punktgenau am Bildschirm positioniert werden. Hierzu stehen 512 mögliche X- und 256 mögliche Y-Positionen zur Verfügung. Der Bezugspunkt eines Sprites ist immer die obere linke Ecke des 24x21-Punktebereiches, ganz egal welche Pixel gesetzt sind.

[Bearbeiten] vertikale Positionierung

Das Y-Positionsregister der Sprites kann Zahlen von 0 bis 255 erfassen, von denen 200 im sichtbaren Bereich liegen.

Y-Wertebereich
normale Spritegröße
Y-Wertebereich
doppelte Spritegröße
Beschreibung
0-29 0-8 der obere Rahmen überdeckt komplett das Sprite.
30-49 9-49 der obere Rahmen überdeckt teilweise das Sprite.
50-229 50-208 das Sprite erscheint zur Gänze.
230-249 209-249 der untere Rahmen überdeckt teilweise das Sprite.
250-255 250-255 der untere Rahmen überdeckt komplett das Sprite.

Anmerkung: Diese Tabelle gilt für den 25-Zeilen-Modus. Im 24-Zeilen-Modus verkleinert sich der sichtbare Bereich oben und unten um jeweils vier Pixel.

[Bearbeiten] horizontale Positionierung

Durch Hinzunahme eines Extra-Bits mit der Wertigkeit 256 in Register (53264/$D010) hat ein Sprite nun 504 (PAL) bzw. 512 (NTSC) mögliche Positionen in der X-Richtung (links/rechts) von denen 320 im sichtbaren Bereich liegen.

X-Wertebereich
normale Spritegröße
X-Wertebereich
doppelte Spritegröße
Beschreibung
0 480 (PAL) / 488 (NTSC) der linke Rahmen überdeckt komplett das Sprite.
1-23 481-503 (PAL) / 489-511 (NTSC), 0-23 der linke Rahmen überdeckt teilweise das Sprite.
24-320 24-296 das Sprite erscheint zur Gänze.
321-343 297-343 der rechte Rahmen überdeckt teilweise das Sprite.
344 344 der rechte Rahmen überdeckt komplett das Sprite.

Anmerkung: Diese Tabelle gilt für den 40-Spalten-Modus. Im 38-Spalten-Modus verkleinert sich der sichtbare Bereich links um 7 und rechts um 9 Pixel.

[Bearbeiten] Beispiel

  • Sprite 5 soll auf X=300 (256+44) positioniert werden.
  • Die anderen Sprites sollen ihre momentane X-Position beibehalten.

Basic:

10 POKE 53258,44                :REM X-POSITION SPRITE 5 = 44
20 POKE 53264,PEEK(53264) OR 32 :REM EXTRA-BIT FÜR SPRITE 5 EIN

Assembler:

LDA #44
STA $D00A       ; X-Position Sprite 5 auf 44 setzen

LDA $D010       ; Lade X-MSB
ORA #%00100000  ; Extra-Bit für Sprite 5 einschalten
STA $D010       ; Schreibe X-MSB-Register

[Bearbeiten] Sprites vergrößern

Sprite # Registernummer / dez. / hex. Funktion
0-7 29 / 53277 / $D01D Spritegröße horizontal (X) verdoppeln
0-7 23 / 53271 / $D017 Spritegröße vertikal (Y) verdoppeln
(thumbnail)
Normalgröße, 2*Y, 2*X und doppelte Größe

Der VIC-II-Chip hat die Fähigkeit, die Spritegröße in vertikaler und/oder horizontaler Richtung zu verdoppeln. Die Auflösung nimmt dabei nicht zu, lediglich das Sprite wird zweimal so hoch/breit dargestellt. Bit=0 bedeutet Normalgröße. Bit=1 bedeutet Vergrößerung. Der Bezugspunkt des Sprites ist wie immer oben links.


Die einzelnen Bits dieser beiden Register haben folgende Gewichtung:

Sprite-Nummer 7 6 5 4 3 2 1 0
Wertigkeit 128 64 32 16 8 4 2 1


Beispiel

Sprite 0 bis 3 sollen in X-Richtung vergrößert werden, Sprite 4 bis 7 haben Normalgröße.

Basic:

10 POKE 53277,15  :REM SPRITE 0-3 IN X-RICHTUNG VERGRÖSSERN (1+2+4+8=15)

Assembler:

LDA #%00001111
STA $D01D       ; Sprite 0-3 in X-Richtung vergrößern / Sprite 4-7 normal

[Bearbeiten] Farbgebung der Sprites

Sprite# Register / dez. / hex. Frunktion
0-7 28 / 53276 / $D01C Farbmodus (0=einfarbig, 1=mehrfabig)
0-7 37 / 53285 / $D025 Mehrfarbenregister Farbe 0
(Bitpaar = %01)
0-7 38 / 53286 / $D026 Mehrfarbenregister Farbe 1
(Bitpaar = %11)
0 39 / 53287 / $D027 Spritefarbe 0
1 40 / 53288 / $D028 Spritefarbe 1
2 41 / 53289 / $D029 Spritefarbe 2
3 42 / 53290 / $D02A Spritefarbe 3
4 43 / 53291 / $D02B Spritefarbe 4
5 44 / 53292 / $D02C Spritefarbe 5
6 45 / 53293 / $D02D Spritefarbe 6
7 46 / 53294 / $D02E Spritefarbe 7
(thumbnail)
alle 16 möglichen Farben

Der Farbmodus wird in der Speicherstelle 53276 ($D01C) definiert. Für jedes Sprite ist ein Bit (0=Einfarbenmodus, 1=Mehrfarbenmodus) mit folgender Gewichtung vorgesehen:

Sprite-Nummer 7 6 5 4 3 2 1 0
Wertigkeit 128 64 32 16 8 4 2 1

[Bearbeiten] Einfarbenmodus

Im Einfarbenmodus (HiRes-Modus) wird jeder Punkt eines Sprites in der gleichen Farbe angezeigt. Diese Farbe wird im entsprechenden Farbregister abgelegt. Der Wertebereich liegt zwischen 0 und 15. Der Rest des Sprites ist transparent.

[Bearbeiten] Mehrfarbenmodus

Im Mehrfarbenmodus (Multicolor-Modus) bekommen alle Sprites zwei zusätzliche gemeinsame Farben. Die horizontale Auflösung wird von 24 auf 12 halbiert, da bei der Spritedefinition jeweils zwei Bits zusammengefasst werden. Jedes Pixel wird dadurch doppelt so breit. Es ergeben sich folgende vier Möglichkeiten:

Bit-Paar Farbe
 %00 transparent
 %10 Sprite-Farbenregister ($D027-$D02E)
 %01 Mehrfarbenregister #0 ($D025)
 %11 Mehrfarbenregister #1 ($D026)


[Bearbeiten] Beispiele

Bit        | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | (bei normales Sprite)
           |---|---|---|---|---|---|---|---| 
Bit        | 7 + 6 | 5 + 4 | 3 + 2 | 1 + 0 | (bei Multicolor Sprite)
           |---|---|---|---|---|---|---|---|
Bitwert    |128|064|032|016|008|004|002|001|
           |---|---|---|---|---|---|---|---|
1.Beispiel |   |   |   |   |   |   |   |   | (Hintergrundfarbe), Wert 0
           |---|---|---|---|---|---|---|---|
2.Beispiel |   | X |   | X |   | X |   | X | (Multicolorfarbe 0), Wert 85
           |---|---|---|---|---|---|---|---|
3.Beispiel | X |   | X |   | X |   | X |   | (Spritefarbe), Wert 170
           |---|---|---|---|---|---|---|---|
4.Beispiel | X | X | X | X | X | X | X | X | (Multicolorfarbe 1), Wert 255
           |---|---|---|---|---|---|---|---|
Diese Betrachtung gilt für einen Datenwert, der eine Linie darstellt.  

           |---|---|---|---|---|---|---|---|
5.Beispiel | X | X |   | X |   |   | X |   | Datenwert 146
           |---|---|---|---|---|---|---|---|
Einmal alles gemischt, d.h. dreifarbige Linie

[Bearbeiten] Sprite Anzeigeprioritäten

[Bearbeiten] Sprite/Sprite-Priorität

(thumbnail)
Sprite 0 (weiß) ist immer vor den anderen Sprites.

Die Priorität zwischen den einzelnen Sprites ist festgelegt und kann nicht verändert werden. Sprite 0 hat die höchste, Sprite 1 die nächste und Sprite 7 entsprechend die niedrigste Priorität. Das bedeutet: Überlappen sich z.B. Sprite 1 und Sprite 3, so erscheint Sprite 1 vor Sprite 3. Dadurch kann ein dreidimensionaler Effekt erzeugt werden.

Anmerkung: Ein "Fenstereffekt" ist möglich, wenn ein Sprite mit höherer Priorität transparente Bereiche hat (Pixel=0 oder bei Multicolor %00). So scheinen Sprites mit niedrigerer Priorität durch. (siehe Bild)

[Bearbeiten] Sprite/Hintergrund-Priorität

Sprite # Registernummer / dez. / hex. Funktion
0-7 27 / 53275 / $D01B Hintergrund-Sprite-Priorität
(thumbnail)
Bit=0, wenn Sprite nach rechts läuft.
Bit=1, wenn Sprite nach links läuft.

Das Prioritätsverhältnis zwischen Sprites und Bildschirmhintergrund wird durch das entsprechende Register in Adresse 53275 ($D01B) gesteuert. In diesem Register hat jedes Sprite ein Bit.

Ist das Bit 0, so hat das entsprechende Sprite eine höhere Priorität als der Bildschirmhintergrund. Das Sprite erscheint vor den Hintergrunddaten.

Ist das Bit 1, so hat der Hintergrund Priorität gegenüber dem Sprite. Das Sprite erscheint hinter den Hintergrunddaten. Genauer gesagt: Das Sprite erscheint hinter den Pixeln der Bits "1" für Hires bzw. "10" und "11" für Multicolor, aber vor denen der Bits "0" bzw. "00" und "01".
In der Beispiel-Animation sieht man, wie das Sprite sich von rechts nach links vor dem blauen Hintergrund, aber hinter dem grünen Busch bewegt. Dabei scheint es im Bereich des Stammes teilweise durch, weil hier der Farbe Orange, der die Bits "01" zugeordnet sind, vom Sprite überdeckt wird.

Die einzelnen Bits dieses Registers haben folgende Gewichtung:

Sprite-Nummer 7 6 5 4 3 2 1 0
Wertigkeit 128 64 32 16 8 4 2 1

Von diesem Register unabhängig hat der Bildschirmrahmen immer die höchste Priorität.

[Bearbeiten] Beispiel

Sprite 7 soll wieder vor den Hintergrunddaten erscheinen. Sprite 0-6 sollen unverändert bleiben.

Basic:

10 POKE 53275, PEEK(53275) AND 127 :REM BIT7 IM PRIORITÄTSREGISTER LÖSCHEN

Assembler:

LDA $D01B       ; Prioritäts-Register lesen 
AND #%01111111  ; Bit7 löschen, Bit 0-6 bleiben unverändert
STA $D01B       ; Prioritäts-Register schreiben

[Bearbeiten] Sprites animieren

Sprite Animation.png Sprite Animation.gif
acht Einzelbilder und das animierte Ergebnis

Um eine Spriteanimation zu erstellen sind mindestens zwei aufeinander abgestimmte Bilder erforderlich. Die Spriteblöcke werden in der Abspielreihenfolge nacheinander im Speicher abgelegt.

Der Spritedatenzeiger wird solange hochgezählt, bis das Ende erreicht ist und dann wieder auf den Ursprungswert zurückgesetzt.


[Bearbeiten] Register zur Spritekontrolle

  • 53269 / $D015 Sprite einschalten mit X=0 (alle aus) bis 255 (1, 2, 4, 8, 16, 32, 64, 128 für Sprite 0 bis 7; Kombinationen mit Addition der Werte für mehrere Sprites z.B. 3 für Sprite 0 und 1)
  • 53278 / $D01E Kollision zwischen Sprites; Auslesewerte X=0 (keine Kollison) bis 255 (1, 2, 4, 8, 16, 32, 64, 128 für Sprite 0 bis 7; Kombinationen mit Addition der Werte für mehrere Sprites z.B. 3 für Sprite 0 und 1)
  • 53279 / $D01F Kollision zwischen Sprites und Hintergrund (Zeichen); Auslesewerte X=0 (keine Kollision) bis 255 (1, 2, 4, 8, 16, 32, 64, 128 für Sprite 0 bis 7; Kombinationen mit Addition der Werte für mehrere Sprites z.B. 3 für Sprite 0 und 1)

[Bearbeiten] Speicheradressen

Folgende Speicheradressen sind für die Verwaltung, Steuerung und Eigenschaften der Sprites zuständig. Diese können entweder mit dem BASIC-Befehl POKE geändert werden oder mit dem BASIC-Befehl PEEK ausgelesen werden.

POKE 2040,13: POKE 53248,255 : POKE 53249, 100: POKE 53287,1

Darstellen des Sprites 0 mit zufälliger Form in weißer Farbe

PRINT PEEK (53278): PRINT PEEK (53279)

Auslesen der Spritekollisionen

[Bearbeiten] Beispiele

Hier eine kleine Demonstration was mit 3 Sprites (Multicolor und einfach) möglich ist. Die REM-Zeilen brauchen nicht eingegeben zu werden; sie dienen nur der Dokumentation des Programms. Außerdem passen diese leider nicht in der logischen Bildschirmzeile hinein! In der Variable V steckt der Anfangsspeicherbereich des VIC II.

 1 PRINTCHR$(147): V=53248: POKE V+33,0: REM Bildschirmbereinigung
 2 FOR X=12800 TO 12927: POKE X,0: NEXT X: REM Speicherbereinigung für Spritebereich

10 FOR X=12800 TO 12881: READ Y: POKE X,Y: NEXT X: REM Spritegenerierung
11 POKE 2040,200: POKE 2041,201: POKE 2042,201: POKE V+21,7
12 POKE V+28,6: POKE V+37,15: POKE V+38,2: REM Multicolor für Sprite 1&2
13 POKE V+39,7: POKE V+40,8: POKE V+41,6: REM Spritefarbe Sprite 0&1&2
15 POKE V+23,7: POKE V+29,7: POKE V+16,1: REM Spriteeigenschaften Höhe, Breite, X-Position
16 POKE V+1,133: POKE V+2,170: POKE V+5,115: REM X-/Y-Positionen

19 REM Bewegung und Farbänderungen
20 FOR X=200 TO 1 STEP-1: POKE V,X: Z=Z+0.61: POKE V+3,Z
21 POKE V+4,(201-X)/2: NEXT X
22 POKE V+16,0: POKE V,255: M=PEEK(V+4)
23 FOR X=255 TO 170 STEP-1: POKE V,X: Z=Z+0.66: POKE V+3,Z
24 POKE V+4,M+(256-X)/1.2: NEXT X
25 FOR X=0 TO 5: FOR Y=1 TO 255: POKE V+37+X,Y: NEXT Y,X
26 POKE V+38,2: POKE V+39,7: POKE V+41,6
27 FOR Y=1 TO 65: POKE V+40,Y: POKE V+37,Y+10
28 FOR Z=0 TO 15: POKE V+39,Y: NEXT Z, Y

29 REM Warten, löschen von Sprite 0 und Ausblendung 
30 FOR X=0 to 3000: NEXT X
31 FOR X=0 TO 32: POKE 12832+X,0: POKE 12832-X,0
32 FOR Y=0 TO 100: NEXT Y,X: POKE V+21,0

39 REM SPRITE C64-WIKI.DE (einfarbig; Sprite 0)
40 DATA 239,81,85,139,81,20,137,81,28,137,81,89,137,213,89,142,85,93,138   
41 DATA 95,85,138,91,85,238,91,85,0,0,0,0,0,0,0,0,0
42 DATA 0,199,0,0,231,0,0,164,0,0,180,0,0,151,0,0,180,0,0,164,0,0,231,0,0,199,0

44 REM Multicolor-Sprite Linie (Sprite 1&2)
45 DATA 0,255,255,255,170,85,170,170,85,170,85,170,85,85,170,85,255,255,255

[Bearbeiten] Links

WP-W11.png Wikipedia: Sprite (Computergrafik)
Mustread 32.gif Dieser Artikel wurde in die Liste der Lesenswerten Artikel aufgenommen.
In anderen Sprachen