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 (englisch, bedeutet "Kobold" oder "Geist") ist ein auf dem Bildschirm frei bewegbares Grafikelement. Beim C64 hat ein Sprite eine maximale Punktgröße von 24 × 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 Grafikchip VIC-II im C64. Dieser unterstützt die Darstellung von maximal acht Sprites, entweder in einem hochauflösenden einfarbigen Modus (Hires; 24×21 Pixel; eine aus 16 möglichen Farben pro Sprite) oder einem Mehrfarben-Modus (Multicolor; 12×21 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, sogenannte "Sprite-Multiplexing". Sprites haben eine Aktionsfläche von 512×256 Pixels, wobei das Standard-Bildschirmfenster nur einen Teilbereich dieser Aktionsfläche darstellt.

[Bearbeiten] Sprite-Daten

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

Ein Sprite-Block 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 Sprite-Erstellungsprogramme (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 des BASIC 7.0 am C128 (oder beim Super Expander 64) einen Sprite-Editor auf.

Programmierung in BASIC

Die Sprite-Daten 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 Sprite-Block 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] Sprite-Datenzeiger

Speicheradresse
dez. / hex.
Funktion
2040 / $07F8 Sprite-Datenzeiger für Sprite 0
2041 / $07F9 Sprite-Datenzeiger für Sprite 1
2042 / $07FA Sprite-Datenzeiger für Sprite 2
2043 / $07FB Sprite-Datenzeiger für Sprite 3
2044 / $07FC Sprite-Datenzeiger für Sprite 4
2045 / $07FD Sprite-Datenzeiger für Sprite 5
2046 / $07FE Sprite-Datenzeiger für Sprite 6
2047 / $07FF Sprite-Datenzeiger für Sprite 7
  • Jedes der acht Sprites hat ein Byte, das Sprite-Datenzeiger (Sprite-Pointer) genannt wird.
  • Dieser Zeiger hat einen Wertebereich von 0 bis 255 und gibt an, wo sich die Sprite-Daten 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 des 1 KByte (1024 Byte) großen Bildschirmspeichers. Im Normalfall (Standardkonfiguration nach dem Einschalten) liegen die Adresswerte bei 2040-2047 ($07F8-$07FF).

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


Sprite-Blöcke
In Assembler ist man grundsätzlich relativ frei bei der Wahl der Sprite-Blöcke. In BASIC darf Sprite-Block 11 bedenkenlos verwendet werden. Die Sprite-Blö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 Sprite-Daten überschreiben können.


Beispiel
Ein Sprite-Block liegt im RAM-Speicher ab Adresse 892 und soll für Sprite 0 verwendet werden.
→ Der Sprite-Datenzeiger 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 24×21-Punktebereichs, 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 Sprite-Größe
Y-Wertebereich
doppelte Sprite-Größ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 Sprite-Größe
X-Wertebereich
doppelte Sprite-Größ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-Nummer Registernummer / dez. / hex. Funktion
0-7 29 / 53277 / $D01D Sprite-Größe horizontal (X) verdoppeln
0-7 23 / 53271 / $D017 Sprite-Größe vertikal (Y) verdoppeln
(thumbnail)
Normalgröße, 2*Y, 2*X und doppelte Größe

Der VIC-II-Chip hat die Fähigkeit, die Sprite-Größe in vertikaler und/oder horizontaler Richtung zu verdoppeln. Die Auflösung nimmt dabei nicht zu, lediglich das Sprite wird zweimal so hoch und 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-Nummer Register / dez. / hex. Funktion
0-7 28 / 53276 / $D01C Farbmodus
(0=einfarbig, 1=mehrfabig)
0-7 37 / 53285 / $D025 Mehrfarbenregister Farbe 0
(Bit-Paar = %01)
0-7 38 / 53286 / $D026 Mehrfarbenregister Farbe 1
(Bit-Paar = %11)
0 39 / 53287 / $D027 Sprite-Farbe 0
1 40 / 53288 / $D028 Sprite-Farbe 1
2 41 / 53289 / $D029 Sprite-Farbe 2
3 42 / 53290 / $D02A Sprite-Farbe 3
4 43 / 53291 / $D02B Sprite-Farbe 4
5 44 / 53292 / $D02C Sprite-Farbe 5
6 45 / 53293 / $D02D Sprite-Farbe 6
7 46 / 53294 / $D02E Sprite-Farbe 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 Sprite-Definition 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 normalem Sprite)
            |---|---|---|---|---|---|---|---| 
Bit         | 7 + 6 | 5 + 4 | 3 + 2 | 1 + 0 | (bei Multicolor-Sprite)
            |---|---|---|---|---|---|---|---|
Bit-Wert    |128|064|032|016|008|004|002|001|
            |---|---|---|---|---|---|---|---|
1. Beispiel |   |   |   |   |   |   |   |   | (Hintergrundfarbe), Wert 0
            |---|---|---|---|---|---|---|---|
2. Beispiel |   | X |   | X |   | X |   | X | (Multicolor-Farbe 0), Wert 85
            |---|---|---|---|---|---|---|---|
3. Beispiel | X |   | X |   | X |   | X |   | (Sprite-Farbe), Wert 170
            |---|---|---|---|---|---|---|---|
4. Beispiel | X | X | X | X | X | X | X | X | (Multicolor-Farbe 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-Nummer 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 Beispielanimation 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 die Bits "01" zugeordnet sind und sonst 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 bis 6 sollen unverändert bleiben.

BASIC:

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

Assembler:

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

[Bearbeiten] Sprites animieren

Sprite Animation.png Sprite Animation.gif
Acht Einzelbilder und das animierte Ergebnis.
  • Um eine Sprite-Animation zu erstellen sind mindestens zwei aufeinander abgestimmte Bilder erforderlich.
  • Die Sprite-Blöcke werden in der Abspielreihenfolge nacheinander im Speicher abgelegt.

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


[Bearbeiten] Register zur Sprite-Kontrolle

  • 53269 / $D015 Sprite ein- oder ausschalten
    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 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)
  • 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

Stellt das Sprites 0 mit zufälliger Form in weißer Farbe dar.

PRINT PEEK (53278): PRINT PEEK (53279)

Liest die Sprite-Kollisions-Bits aus.

[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 PRINT CHR$(147): V=53248: POKE V+33,0: REM Bildschirmbereinigung
 2 FOR X=12800 TO 12927: POKE X,0: NEXT X: REM Speicherbereinigung für Sprite-Bereich

10 FOR X=12800 TO 12881: READ Y: POKE X,Y: NEXT X: REM Sprite-Generierung
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 Sprite-Farbe Sprite 0&1&2
15 POKE V+23,7: POKE V+29,7: POKE V+16,1: REM Sprite-Eigenschaften 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] Weblinks

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