Sprites (ASM)

weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

CBM prg StudioDie wichtigsten Grundlagen zu den Sprites

Unter BASIC habt ihr evtl. schon mal die Sprites benutzt. Hier wird nochmal alles zusammengetragen und von der Assemblerseite betrachtet.

Das Sprites freibewegliche und vom aktuellen Grafikmodus unabhängige Objekte sind, wisst ihr bestimmt schon. Der C64 kann davon 8 Stück gleichzeitig darstellen. Durch entsprechende Techniken (Rasterinterrupt), lassen sich auch mehr anzeigen. Sprites können einfarbig und hochauflösend (Hi-Res) oder mehrfarbig (Multicolor) und „gröber“ sein. Ihre Größe lässt sich in der Breite und/oder Höhe einfach verdoppeln. Außerdem könnt ihr festlegen, ob die Sprites vor oder hinter der Hintergrundgrafik erscheinen sollen. Darüberhinaus gibt es eine Kollisionserkennung, man kann also feststellen, ob sich zwei Sprites berühren oder ob ein Sprite mit dem Hintergrund Kontakt hat.

Für die Sprites ist natürlich wieder der Grafikchip (VIC-II) des C64 zuständig. Wie wichtig die Sprites sind, kann man evtl. daran erkennen, dass von den 47 Registern (beim C128 gibt es noch zwei weitere) alleine 34 für die Sprites zusändig sind. Wie ihr in „Kleine Hardwarkunde“ gesehen habt, beginnen die Register des VIC-II ab $D000, schauen wir uns also die Register für die Sprites einmal an:

Adresse
Nr.
Beschreibung
$D000
00
Sprite 0: X-Position (s. auch $D010)
$D001
01
Sprite 0: Y-Position
$D002
02
Sprite 1: X-Position (s. auch $D010)
$D003
03
Sprite 1: Y-Position
$D004
04
Sprite 2: X-Position (s. auch $D010)
$D005
05
Sprite 2: Y-Position
$D006
06
Sprite 3: X-Position (s. auch $D010)
$D007
07
Sprite 3: Y-Position
$D008
08
Sprite 4: X-Position (s. auch $D010)
$D009
09
Sprite 4: Y-Position
$D00A
10
Sprite 5: X-Position (s. auch $D010)
$D00B
11
Sprite 5: Y-Position
$D00C
12
Sprite 6: X-Position (s. auch $D010)
$D00D
13
Sprite 6: Y-Position
$D00E
14
Sprite 7: X-Position (s. auch $D010)
$D00F
15
Sprite 7: Y-Position
$D010
16
Für ALLE Sprites: Das höchste Bit der X-Position
Da der Bildschirm breiter als 256 (mehr passt ja nicht in ein Byte) Pixel ist benötigt man noch ein weiteres Bit um ein Sprite z. B. nach X = 300 zu bringen. Die C64-Entwickler haben sich entschieden diese Info in diesem einzelnen Byte für alle Sprites zu speichern.

Sprite-Nr. = Bit-Nr. (denkt dran: Bit-7 ist ganz links, Bit-0 ist ganz rechts)
$D015
21
Legt fest, ob das jeweilige Sprite aktiv (sichtbar) ist (=1)
Sprite-Nr. = Bit-Nr.
$D017
23
Bestimmt, ob das jeweilige Sprite in seiner Höhe verdoppelt (=1) werden soll oder nicht (=0)
Sprite-Nr. = Bit-Nr.
$D01B
27
Soll das jeweilige Sprite vor (=0) oder hinter der Hintergrundgrafik (=1) erscheinen.
Sprite-Nr. = Bit-Nr.
$D01C
28
Legt fest, ob das jeweilige Sprite Hi-Res (=0) oder Multicolor (=1) ist.
Sprite-Nr. = Bit-Nr.
$D01D
29
Legt fest, ob das jeweilige Sprite normal (=0) oder in seiner Breite verdoppelt (=1) dargestellt werden soll.
Sprite-Nr. = Bit-Nr.
$D01E
30
Zeigt eine Kollision (=1) zwischen Sprites an.
Sprite-Nr. = Bit-Nr.

Der Registerinhalt wird beim lesen gelöscht!
$D01F
31
Zeigt eine Kollision (=1) zwischen einem Sprite und dem Hintergrund an.
Sprite-Nr. = Bit-Nr.

Der Registerinhalt wird beim lesen gelöscht!
$D025
37
Erste Spritefarbe (Multicolor_0) für den Sprite-Multicolormodus (s. $D01C)
Achtung: Diese ist für alle Sprites gleich!
$D026
38
Zweite Spritefarbe (Multicolor_1) für den Sprite-Multicolormodus (s. $D01C)
Achtung: Diese ist für alle Sprites gleich!
$D027
39
Sprite-0: Farbe - Hauptfarbe des Sprites
$D028
40
Sprite-1: Farbe - Hauptfarbe des Sprites
$D029
41
Sprite-2: Farbe - Hauptfarbe des Sprites
$D02A
42
Sprite-3: Farbe - Hauptfarbe des Sprites
$D02B
43
Sprite-4: Farbe - Hauptfarbe des Sprites
$D02C
44
Sprite-5: Farbe - Hauptfarbe des Sprites
$D02D
45
Sprite-6: Farbe - Hauptfarbe des Sprites
$D02E
46
Sprite-7: Farbe - Hauptfarbe des Sprites

Wie ihr seht werden in  $D000 –  $D00F die jeweiligen X- und Y-Postionen der acht Sprites gespeichert. Die X-Position könnte damit max. 255 betragen, da ja nur ein Byte vorgesehen ist. Deshalb gibt es noch das Register $D010! Dort steht für jedes Sprite ein weiteres Bit zur Verfügung. Somit haben wir neun Bits und können Zahlen von 0 bis 511 darstellen.
Wichtig: Die Bit-Nr. entspricht dabei der Sprite-Nr. (das kommt hier häufiger vor!)

Im obigen Beispiel ist die X-Position von Sprite 0, 1 und 5 also größer als 255, da im Register  $D010 das jeweilige Bit gesetzt ist.

Was sind nun Hi-Res- und Multicolor-Sprites (siehe Register $D01C$D025 und $D026)?
Die Hi-Res-Sprites sind einfarbig und haben eine Größe von 24 Pixeln (Punkten) mal 21 Zeilen. Ein einzelnes Bit bestimmt jeweils, ob der Pixel sichtbar oder durchsichtig ist. Die Farbe der sichtbaren Pixel kann für jedes einzelne Sprite frei gewählt werden, dies geschieht über die Register von  $D027$D02E.

Bei Multicolor-Sprites reduziert sich die Auflösung für den Entwurf auf 12 * 21 Pixel, da nun immer zwei Bits benötigt werden um festzulegen ob ein Pixel sichtbar ist. Auf dem Bildschirm werden aber für einen „Entwurf-Punkt“ zwei Pixel benötigt, das Sprite wirkt dadurch um einiges „gröber“.

Das Besondere ist nun, dass alle Sprites die selben beiden Multicolor-Werte benutzen müssen, Multicolor_0 und Multicolor_1 ( $D025 & $D026) kann man also nur einmal festlegen. Wie beim Hi-Res-Sprite besitzt aber jedes Sprite weiterhin seine individuelle Farbe in  $D027$D02E.

Die Erklärungen in der Tabelle zu den restlichen Register sollen erstmal reichen, wir werden aber gleich im Beispiel alle einmal verwenden, damit ihre Funktion klar wird.

 

OK, was müssen wir nun tun, um Sprites anzuzeigen?

  • die Sprites enwerfen und als BYTES im Speicher ablegen
  • dem VIC II mitteilen, wo die Spritedaten liegen
  • Einstellungen wie doppelte Breite / Höhe; Hi-Res oder Multicolor vornehmen
  • die Farben festlegen
  • die aktuellen X- und Y-Positionen eintragen
  • die Sprites sichtbar schalten

 

Die Sprites entwerfen:
Im BASIC-Teil habe ich noch einen Excel-Sprite-Editor vorgestellt, aber nun wollen wir das CBM prg Studio verwenden.

Der Sprite-Editor
Der Sprite Editor

Wer eine kurze (verdammt, sind doch über 16 Minuten geworden 😉 ) Einführung möchte, der kann sich ja mal dieses Video ansehen.

Wir sollten hier aber erstmal die von mir vorgegebenen Sprites verwenden, damit das Ergebnis vergleichbar bleibt. Aber sobald ihr den Umgang mit den Sprite verinnerlicht habt, solltet ihr eure eigenen Versuche durchführen.

 

Dem VIC-II mitteilen, wo die Spritedaten liegen:
Zunächst müssen wir mal klären, wo die Speicherstellen überhaupt liegen, an denen der VIC II die Adressen der Spritedaten erwartet. Erwähnt habe ich das in anderen Beiträgen schon häufiger: Die Adressen befinden sich hinter dem Bildschirmspeicher, um genau zu sein, in den letzten 8 Bytes des Kilobytes, dass ab der Startadresse des Bildschirmspeichers zufinden ist. Diese Adressen werden Sprite-Pointer genannt.

Screen-RAM nach dem Einschalten
Das Screen-RAM nach dem Einschalten

Nach dem Einschalten findet ihr die Sprite-Pointer also an den Stellen $07F8 bis $07FF.

Mini Exkurs: VIC II
Ganz so eindeutig ist das nun aber doch wieder nicht. Die genaue Position ist noch von weiteren Faktoren abhängig.
Der VIC II kann immer nur 16KB „sehen“. Ihr habt daher die Möglichkeit dem VIC mitzuteilen, auf welche 16KB (Bank-0 bis 3) er zugreifen darf. Innerhalb der jeweiligen Bank könnt ihr dann noch den Beginn des BS-Speichers in 1KB Schritten auf die von euch gewünschte Position verschieben.
Genaueres dazu gibt es im Beitrag VIC-II: Speicherbereiche festlegen.

Aber wie sollen wir unsere Adressen für die Spritedaten nun in nur einem BYTE ablegen? Hier kommt eine ähnliche Logik wie eben beim Exkurs zum Tragen. Da ein Sprite max. 24 Pixel * 21 Zeilen oder auch 3 Bytes * 21 Zeilen, also 63 Byte groß sein kann, werden die Daten auf 64Byte aufgefüllt und an einer durch 64 teilbaren Adresse erwartet. Teilt man die 16KB, die der VIC „sieht“, durch die 256 möglichen Plätze (wir haben ja nur ein BYTE für die Adresse der aktuellen Spritedaten) dann kommen wir wieder auf 64 BYTES. Wir müssen also die Nr. des 64-BYTE-Blocks innerhalb der für den VIC-II sichtbaren 16KB-Bank angeben.
Normalerweise würdet ihr euch direkt eine passende Adresse aussuchen und diese dann verwenden. Wir halten das aber in unserem Beispiel zu Übungszwecken einfach mal dynamisch und berechnen uns die entsprechende Position.

Beginnen wir mit dem Programm. Nicht erschrecken, dass es so lang ist, ich starte erstmal mit einer Reihe von Variablen/Konstanten, die ich zukünftig ausbaue und häufiger verwende.

 

Das Programm macht noch nicht wirklich viel. Nach  main:  wird zunächst nur der erste 64-Byte-Block der Spritedaten berechnet. Dazu kopieren wir das LSB & MSB unserer Startadresse der Spritedaten von spritesdata:  in ein Hilfsregister calc16Bit:. Beachtet bitte, dass wir den Assembler mittels  align 64 dazu gebracht haben, den Beginn von  spritesdata:  an eine durch 64 teilbare Adresse zu verschieben.
Um die Nr. des 64-Byte-Blocks zu erhalten, müssen wir nun (das klappt so nur, weil wir alles auf Standard gelassen haben!) unsere Adresse durch 64 teilen. Dazu verschieben wir diese einfach 6 mal bitweise nach rechts (2*2*2*2*2*2 = 64). Also in einer kleinen Schleife mit  lsr  das MSB nach rechts verschieben und danach mit  ror, damit das Carry-Flag beachtet wird, das LSB nach rechts verschieben. Zum Schluß haben wir im LSB des Hilfsregisters unsere gesuchte Nr. des 64-BYTE-Blocks. Diesen Wert holen wir ins X-Register und speichern ihn unter SPRITE0DATA. Dann erhöhen wir X um 1 (das zweite Sprite folgt ja direkt hinter dem ersten) und speichern X an SPRITE1DATA. Somit weiß der VIC II jetzt, wo er die Daten für Sprite-0 und 1 finden kann. Hier endet das Programm erstmal.
Wer kommt über einen Richtungswechsel für diesen Sonderfall auf eine schnellere Lösung für die Berechnung des 64-BYTE-Blocks?

 

Gebt die weiteren Sourcezeilen bitte einfach vor dem  rts  ein.

 

Einstellungen wie doppelte Breite / Höhe, Hi-Res oder Multicolor vornehmen
Unsere beiden Sprites sollen zunächst ohne jegliche Vergrößerung angezeigt werden. Daher löschen wir die Register  $D017 und $D018

 

Unser Sprite-0 ist Hi-Res, das Sprite-1 aber Multicolor. Daher Bit-1 in  $D01C setzen. Wir wollen zur Sicherheit, alle anderen Sprites auf Hi-Res setzen, daher schreiben wir einfach %00000010  ins Register.

 

Außerdem sorgen wir dafür, dass unsere Sprites erstmal vor dem Hintergrund zu sehen sind, indem wir  $D01B auf null setzten.

 

Die Farben festlegen:

Die Hauptfarben für Sprite-0 und 1 schreiben wir in die Register  $D027 und $D028.

 

Da das zweite ein Multicolor-Sprite ist, sollten wir auch noch die dazugehörigen Farben setzen.

Denkt daran, dass diese beiden Farben für alle Multicolor-Sprites gleich sind!

 

Die aktuellen X- und Y-Positionen eintragen:
Bei der Positionierung der Sprites müssen wir einiges beachten. Zunächst mal findet die Positionierung in Pixeln und nicht in Zeichen und Reihen, wie bei unseren Textausgaben, statt.
Der C64 hat zwar eine Auflösung von 320 * 200 Pixel, dies gilt aber nur für den sichtbaren Bereich. Bei der Positionierung unserer Sprites müssen wir beachten, dass der Ursprung die Koordinaten X=0 und Y=0 hat und sich links oben in der Ecke befindet. Die X-Werte nehmen nach rechts und die Y-Werte nach unten zu. Da wir noch den Rahmen beachten müssen, wird unser Sprite erst ab X=24 und Y=50 komplett sichtbar. Werft einen Blick auf die nachfolgende Grafik, um euch ein besseres Bild davon zu machen. Damit es nicht zu einfach wird, verschieben sich die im Bild angegebenen Werte, wenn ihr den 38 * 24 Zeichenmodu aktiviert.

ASM_ScreenCoords

Da der Rahmen eine höhere Priorität als die Sprites hat, verschwinden diese standardmäßig dahinter! Auch hier gibt es wieder Tricks um Sprites im Rahmen anzuzeigen. Wo wir gerade bei der Priorität sind, untereinander hat Sprite-0 die höchste und Sprite-7 die niedrigste Priorität, d. h. Sprite-0 wird bei Überschneidungen über alle anderen Sprites gezeichnet. Diese Sprite/Sprite-Priorität läßt sich, im Gegensatz zu der mit dem Hintergrund, nicht ändern.

Die Priorität der Sprites: 0 überdeckt alle anderen, 1 über deckt Sprite 2-7, usw.
Die Priorität der Sprites: 0 überdeckt alle anderen, 1 überdeckt Sprite 2-7, 2 überdeckt 3-7 usw.  Die Sprites stammen aus ‚The Way of the Exploding Fist‚

Außerdem haben wir weiter oben ja schon erfahren, dass die X-Position über zwei Register gesteuert wird, da der BS ja 320 Pixel breit ist.

Setzen wir unsere Sprites einfach erstmal so, dass wir sie sehen. Sprite-0 soll an X=$20 und Y=$80 erscheinen, das zweite rechts daneben an ($40, $80). Die Register für Sprite-0 sind  $D000 & $D001, die für Sprite-1  $D002 und $D003. Auch hier löschen wir zur Sicherheit wieder ein Register, diesmal  $D010 in dem ja das höchste Bit für die X-Position gespeichert wird.

 

Die Sprites sichtbar schalten:
Ein letzter, kleiner Schritt noch, dann sehen wir unsere Sprites endlich. Wir müssen nur noch in  $D015 die sichtbaren Sprites eintragen. Um Grafikmüll zu vermeiden aktivieren wir hier nur unsere beiden Sprites, alle anderen schalten wir ab.

Fügt also abschließend noch diese beiden Zeilen hinzu:

Unsere bedeiden Sprites
Unsere beiden Sprites

 

Aktiviert jetzt mal für Sprite-0 die Verdopplung.
Ändert dazu die Zeile:

in

Da wir den Akku danach in die Register  $D017 und  $D01D schreiben, wird unser Sprite-0 sofort in Breite und Höhe verdoppelt. Selbstverständlich könnt ihr das Sprite auch nur horizontal oder vertikal vergrößern.

ASM-SpriteTest002

Bei dieser Vergrößerung könnt ihr gleich zwei Sachen genauer erkennen:

  1. Unser Sprite-0 wird wie gewünscht vor dem Hintergrund dargestellt
  2. Sprite-0 überlagert Sprite-1, da die Priorität von Sprite-0 höher ist.

 

 

Jetzt soll Sprite-0 hinter dem Hintergrund erscheinen, ändert dazu

in

ASM-SpriteTest003

Damit es etwas deutlicher wird, habe ich den Cursor um eine Stelle nach rechts bewegt. Man kann aber durchaus erkennen, dass der Text jetzt über Sprite-0 liegt.

Verschiebt ihr jetzt den Cursor auf einen Bereich, an dem sich Sprite-0 und 1 überschneiden, dann seht ihr, dass, obwohl Sprite-1 vor dem Hintergrund erscheinen soll, der Hintergrund an den Stellen sichtbar wird, an denen Sprite-0 das nächste Sprite überdeckt.

ASM-SpriteTest004

Das liegt daran, dass zuerst die Farbe von Sprite-0 bestimmt wird (Sprite- oder Hintergrundfarbe) dann wird Sprite-0 auf Grund der höheren Priorität über Sprite-1 gezeichnet und somit bleibt die Hintergrundfarbe an den Schnittpunkten erhalten.

 

I like to move it, move it
Bringen wir mal etwas Bewegung in die ganze Sache. Sprite-1 (Mulitcolor) soll sich einfach mal auf und ab bewegen. Dabei soll es erst umkehren, wenn es jeweils komplett unter dem oberen bzw. unterem Rand verschwunden ist. Fügt dazu einfach hinter unsere Aktivierung sta SPRITEACTIV und vor dem rts die folgenden Zeilen ein.

Wie ihr seht erhöhen wir bei  move: zunächst direkt das Register SPRITE1Y. Damit bewegt sich das Sprite-1 nach unten. Dann holen wir das Register  SPRITE1Y  in den Akku, um zu prüfen, ob es vollständig unter dem unteren Rand verschwunden ist. Dies ist der Fall, sobald das Sprite-1 die Position 250 ( $FA) erreicht hat. Ist die Postion noch nicht erreicht, dann springen wir zu move_0:, um den oberen Rand zu testen. Ist das Sprite aber in der 250. Zeile angekommen, dann laden wir den OpCode für den absolut adressierten DEC-Befehl in den Akku und überschreiben den bisherigen INC-Befehl bei move:. Durch die Veränderung unseres Programmes zur Laufzeit, haben wir hier also eine Umkehr der Bewegungsrichtung erzielt. Das Programm läuft anschließend bei move_0: weiter. Hier wird nun geprüft, ob das Sprite-1 unter dem oberen Rand verschunden ist, falls ja tauschen wir bei move: den DEC-Befehl wieder gegen INC aus, anderenfalls geht es bei move_1: weiter. Das abschließende move_1: benötigen wir erst gleich, für die Bewegung von Sprite-0.

Wenn ihr das Programm nun startet, seht ihr das Sprite-1 wahrscheinlich mehrfach. Das liegt daran, dass die Bewegung so schnell vonstatten geht, dass unser Auge nicht mehr mitkommt. Normalerweise würde man das Programm über einen Interrupt im Takt halten, aber wir benutzen für unseren Test hier einfach eine Warteschleife.

Fügt zwischen  move_1: und dem  jmp move:  die folgenden Zeilen ein:

Die verschaltelte Schleife sollte für euch kein Problem sein, durch anpassen von X und Y könnt ihr die Wartezeit beeinflussen.

Jetzt solltet ihr die Bewegung des Sprites, bei einem erneuten Start, in Ruhe verfolgen können.

Soweit, so gut, nun wollen wir Sprite-0 von links nach rechts und umgekehrt bewegen. Dabei soll jetzt aber das Sprite-0 vom Rahmen abprallen, also nicht dahinter verschwinden. Gebt die folgenden Zeilen ab dem bereits vorhandenen Label move_1: ein.

Prinzipiell machen wir das Gleiche wie eben. Hinter  move_1: werden  INC und  DEC wieder gegeneinander ausgetauscht, um die Bewegungsrichtung zu ändern. Aber die Bewegung in X-Richtung erfordert etwas mehr Aufwand, wir müssen ja auch das höchste Bit im Register  $D010 setzen, sobald die X-Position größer als 255 ist. Wir werden mit einer kleinen Unzulänglichlkeit dieses Problem lösen. Da wir unser Sprite-0 immer um einen Pixel bewegen und der linke Rand 24 Pixel breit ist, können wir nach  INC bzw. DEC an einer 0 erkennen, ob die 255. X-Position betroffen ist. Das funktioniert beim Überlauf von $FF => $100 auch wie geplant, wir landen wieder bei 0 und können das höchste Bit setzen. Genaugenommen schalten wir es mit dem EOR #%00000001 einfach um. Wir prüfen dann mit dem AND #%00000001, ob das höchste Bit für Sprite-0 gesetzt ist, wenn ja geht es bei move_2: weiter. Anderenfalls verringern wir die X-Position aber nochmal. Daher bewegt sich unser Sprite-0, wenn es von rechts nach links läuft von der Position 257 auf 255. Wer den Grund für diese unschöne Lösung (OK ich war nur zu faul es korrekt zu machen 😉 ) sehen möchte, der kann die Zeile ja mal auskommentieren und genau darauf achten, was dann passiert. Da es auf unser Beispiel keine weiteren Auswirkungen hat, belasse ich es aber dabei. Ihr könnt das ja mal korrigieren. Bei move_2: schauen wir dann, ob das höchste Bit gesetzt ist, um zu entscheiden, ob wir den linken oder rechten Rand prüfen müssen. Hier geschieht wieder das Gleiche, wie beim Sprite-1. Wird der Rand erreicht, dann schalten wir den Befehl hinter move_1: um, damit das Sprite-0 in die andere Richtung läuft. Diese Art der Bewegung taugt wirklich nur für unser Beispiel. Für eure Programme solltet ihr die anders realisieren.
Zum Schluß gibt es wieder ein Label coll_1:, dass uns erst gleich beim letzten Abschnitt interessiert.

Das Programm läßt sich nun starten und die beiden Sprites bewegen sich über den Bildschirm. Beim Sprite-0 (links/rechts) könnt ihr evtl. das Tearing erkennen, fällt bei Vollbild bzw. auf einem großen Bildschirm besonders auf.

Sprites: Tearing
Tearing

Tearing tritt auf, wenn man mit dem Zeichnen des nächsten Bildes bzw. Änderungen daran, nicht wartet, bis der Rasterstrahl eine definierte Position (am besten außerhalb des sichtbaren Bereichs) erreicht hat. Oben im Bild wurde das Sprite von rechts nach links bewegt und während der Rasterstrahl das aktuelle Bild gezeichnet hat, haben wir das Sprite um einen Pixel nach links verschoben, so das der Rest nun versetzt angezeigt wird.

Es sollte klar sein, dass durch gleichzeitige Veränderung der X- und Y-Position eines Sprites, sich dieses in jedem erdenklichen Bewegungsmuster (z. B. linear oder sinusförmig) an jede gewünschte Bildschirmposition bringen lässt.

 

Achtung: Kollision!
Abschließend wollen wir noch einen Blick auf die Kollisionserkennung werfen. Diese kann man auch über einen Interrupt durchführen, aber wir beschränken uns hier aufs manuelle Prüfen.
Wenn die beiden Sprites (0 & 1) sich berühren, dann wollen wir die Rahmenfarbe ändern. Trifft Sprite-1 auf den Hintergrund, dann soll die Hintergrundfarbe geändert werden.

 

Fügt also hinter dem vorhandenen coll_1:, diese Zeilen ein:

Da wir nur zwei Sprites haben, machen wir es uns für die Sprite/Sprite-Kollision sehr einfach und kontrollieren nur, ob das Register  $D01E  SPRITESPRITECOLL noch null ist. Ist dies der Fall, dann haben wir keine Kollision und springen zu coll_2:, sobald es ungleich null ist, berühren sich zwei Sprites und wir ändern die Rahmenfarbe.

Bei coll_2:  holen wir zunächst das Register  $D01F für die Sprite/Hintergrund-Kollision SPRITEBACKGROUNDCOLL in den Akku. Dann prüfen wir ob Bit-1 (fürs 1. Sprite) gesetzt ist, falls nicht gehts zur Warteschleife bei sleep:, wenn ja ändern wir die Hintergrundfarbe.

Beachtet, dass die Register  $D01E und  $D01F durchs Lesen gelöscht werden. Solltet ihr die Werte noch benötigen, dann müsst ihr diese irgendwo speichern. Überprüfen könnt ihr dies, indem ihr einfach mal die entsprechenden lda-Befehle verdoppelt. Dann sollten Änderung an der Rahmen- bzw. Hintergrundfarbe kaum noch auftreten. Es kann immer noch passieren, dass beim zweiten lda wieder eine neue Kollision erkannt wurde und das Register wieder gefüllt ist, aber das passiert nur noch sehr selten.


 

Das Programm ist nun fertig und ihr könnt das Ergebnis nach einem Start bewundern.

 

Ihr solltet nun viel damit experimentieren und euren Umgang mit Sprites vertiefen. Im Rahmen des L.O.V.E.-Projektes werden später natürlich weiterführende Themen behandelt (z. B. Animation, mehr als 8 Sprites usw.)


Start im Java Emulator


 

 


Schrott!!Naja...Geht so...Ganz gut...SUPER! (12 Bewertungen | Ø 4,92 von 5 | 98,33%)

Loading...


 

<<< zurück |

 

 

weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

6 Gedanken zu „Sprites (ASM)“

  1. Hallo Jörn,
    es hat sich leider ein kleiner Fehler in der Beschreibung der Farbzuweisungen für die MC-Sprites eingeschlichen:
    %00 = Pixel nicht gesetzt (durchsichtig)
    %01 = Multicolor_0 ($D025)
    %10 = Multicolor_1 ($D026)
    %11 = Spritefarbe ($D027 – $D02E, wie bei Hi-Res)

    Korrekt wäre:
    %00 = Pixel nicht gesetzt (durchsichtig)
    %01 = Multicolor_0 ($D025)
    %10 = Spritefarbe ($D027 – $D02E, wie bei Hi-Res)
    %11 = Multicolor_1 ($D026)

    Gruß
    Frank


    09.05.2017 – Edit: Kommentar nach „Sprites (ASM)“ vorschoben, ich denke da passt er besser hin.

  2. Hallo Jörn,

    kleine Korrektur im Kommentar der Zeile
    „lda #$CE ;sonst, OpCode für INC in den Akku“

    Hier lädst du den OpCode für DEC in den Akku, nicht für INC.

    Ist ein wirklich ein super Tutorial, großes Lob!!!

    Schöne Grüße
    Alex

  3. Hallo Jörn,

    das hier ist das beste, WIRKLICH DAS BESTE, was ich jemals an deutschsprachigen Tutorials über den C64 gesehen habe. Ich wünschte, ich hätte Deine umfängliche Wissensbasis schon 1986 gehabt. Leider bin ich nie weit über den „Lothar Englisch“-Level hinausgekommen.

    Danke für die Mühe.
    Das hier ist Internet-Gold!!!

    Gruß,

    Tina

    1. Hallo Tina,
      danke fürs Lob.
      Es macht mir einfach Spaß, mich in die Themen einzuarbeiten und für andere Interessierte niederzuschreiben. Außerdem zwingt es mich dazu, mich sehr intensiv mit dem jeweiligen Themenblock zu beschäftigen.

      Gruß,
      Jörn

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Protected by WP Anti Spam