Das Raumschiff „zusammenbauen“
Diesmal geht es darum, unser Raumschiff auf den Bildschirm zubringen. Aber leider werden wir dann gleich wieder ausgebremst! Sollten Probleme auftreten, benutzt einfach den letzten Beitrag Landung 002 als Ausgangspunkt.
Das Raumschiff anzeigen
Wie bereits bei Landung 001 erklärt, besteht das Raumschiff aus zwei übereinanderliegenden Hi-Res-Sprites und drei MultiColor-Sprites. Zur Erinnerung, im Editor sollten die Sprites ungefähr so aussehen:
Wer mit den Sprites noch auf Kriegsfuß steht, sollte evtl. nochmal bei Sprites (ASM) nachschlagen.
Fügt jetzt vor dem Label screenCanyon, die Sprites ein (s. gelb hervorgehobene Zeilen).
;*** Die Sprites !align 63,0 spriteSpaceship !media "Ship.spriteproject",sprite,0,5 ;*** Der Canyon screenCanyon !media "Canyon.charscreen",charcolor
Wir richteten die Sprites natürlich wieder, an einer durch 64 teilbaren Adresse aus. Legen ein Label (hier spriteSpaceship) fest und binden die dazugehörige Datei (bei mir „Ship.spriteproject“) ein.
Dann gibt es wieder zwei Konstanten, die am Programmbeginn benötigt werden.
SPACESHIP_STARTX = $a5 ;X-Position und SPACESHIP_STARTY = $32 ;Y-Position, an der das Schiff startet
In der Funktion initLander fügen wir vor das jsr drawCanyon die folgenden, gelb markierten, Zeilen ein.
initLander lda #SPACESHIP_STARTX ;Startpositione setzen sta SpaceshipPos ;X lda #SPACESHIP_STARTY ;und sta SpaceshipPos+1 ;Y jsr initSprites ;Sprites initialisieren jsr drawCanyon rts
Hier wird einfach die X- & Y-Startposition in die Variable SpaceshipPos geschrieben, die z. B. hinter LaserFlash eingefügt werden kann.
SpaceshipPos !byte SPACESHIP_STARTX ;X- und !byte SPACESHIP_STARTY ;Y-Position des Landungsschiffs
Da zur Initialisierung der Sprites, nach initSprites gesprungen wird, brauchen wir natürlich noch die entsprechende Funktion. Legt diese hinter der Routine initLander ab.
!zone initSprites ;******************************************************************************* ;*** Sprites initialisieren ;******************************************************************************* ;*** Übergabe: - ;******************************************************************************* ;*** Rückgabe: - ;******************************************************************************* ;*** ändert : A, X, SR ;******************************************************************************* initSprites ldx #spriteSpaceship/64 ;Nr. des ersten 64-Byte-Sprite-Blocks stx SPRITEPOINTER0+4 ;Spritedaten zuweisen inx stx SPRITEPOINTER0+0 inx stx SPRITEPOINTER0+2 inx stx SPRITEPOINTER0+3 inx stx SPRITEPOINTER0+1 jsr updateSprites ;Sprite-Positionen setzen lda #COLOR_BLACK ;Farben der Sprites setzen sta VIC_SPRITE0COLOR lda #COLOR_LIGHTGREY sta VIC_SPRITE4COLOR lda #COLOR_RED sta VIC_SPRITEMULTICOLOR0 lda #COLOR_YELLOW sta VIC_SPRITEMULTICOLOR1 lda #%00001110 ;nur die "Feuer"-Sprites sind MultiColor sta VIC_SPRITEMULTICOLOR lda #%00000000 sta VIC_SPRITEDEEP sta VIC_SPRITEDOUBLEWIDTH sta VIC_SPRITEDOUBLEHEIGHT lda #%00010001 ;erstmal nur das 'Schiff' anzeigen sta VIC_SPRITEACTIVE rts ;zurück
Zu Beginn wird wieder die Spriteposition berechnet (zur Abwechslung mal direkt vom Assembler). Anschließend werden die Spritedaten auf die Sprite-Nr. verteilt. Hier ist es wichtig auf die korrekte Reihenfolge zu achten. Die Details (schwarzes Sprite) sollten die Nr. 0 begkommen, um alles Andere zu überdecken. Dann folgen „Feuer unten“ (Nr. 1), „Feuer links“ (Nr. 2), „Feuer rechts“ (Nr. 3) und der Schiffsrumpf (großes graue Sprite) wird (Nr. 4). Die Feuerdüsen müssen in dieser Reihenfolgen abgelegt werden, damit das Einblenden nachher korrekt klappt. Der Rest sollte kein Problem sein. Über updateSprites werden einmal die Sprite-Positionen gesetzt, dann Farben, MultiColor, Doppeltebreite usw. festgelegt und schließlich Sprite 0 und 4 sichtbar geschaltet.
Bevor wir das Programm wieder starten können, wird noch eine weitere Funktion benötigt, die ihr am besten direkt, hinter initSprites einfügt.
!zone updateSprites ;******************************************************************************* ;*** Sprites positionieren ;******************************************************************************* ;*** Übergabe: - ;******************************************************************************* ;*** Rückgabe: - ;******************************************************************************* ;*** ändert : X, SR ;******************************************************************************* updateSprites ldx SpaceshipPos ;X-Position holen stx VIC_SPRITE0X ;für Sprite-0 stx VIC_SPRITE1X ;1 und stx VIC_SPRITE4X ;4 übernehmen inx ;rechtes 'Feuer' inx ;um drei Pixel nach rechts inx ;verschieben stx VIC_SPRITE3X ldx SpaceshipPos ;nochmal die X-Position holen dex ;und linkes 'Feuer' dex ;um drei Pixel nach links dex ;verschieben stx VIC_SPRITE2X ldx SpaceshipPos+1 ;Y-Position stx VIC_SPRITE0Y ;für stx VIC_SPRITE1Y ;alle stx VIC_SPRITE2Y ;Sprites stx VIC_SPRITE3Y ;identisch stx VIC_SPRITE4Y rts ;zurück
Diese Funktion positioniert alle Sprites so, dass diese jederzeit an der richtigen Stelle stehen. Zu Beginn wird die X-Position aus SpaceshipPos geholt. Für die Details, den Rumpf und „Feuer unten“ passt dieser Wert. Die Feuerdüsen für links und rechts müssen aber etwas verschoben werden, bis sie an der richtigen Stelle erscheinen. Zum Schluß müssen noch alle Sprites auf die korrekte Y-Position gesetzt werden und schon kann die Funktion verlassen werden.
Endlich können wir uns das Ergebnis mal ansehen.
Wie man direkt sieht, haben wir ein kleines Problem. Habt ihr das Programm bis hierher unverändert übernommen und auf einem PAL-System gestartet, dann sollte euch ein Flackern des Himmels auffallen. Aktiviert ihr auch nur ein Sprite mehr ist der Himmel fast dauerhaft braun statt blau, aktiviert ihr aber nur ein einziges Sprite sieht wieder alles gut aus.
Daher unterbrechen wir hier erstmal wieder, um im nächsten Beitrag zu klären, was da gerade schiefgeht.
Dies ist übrigens ein schönes Beispiel dafür, dass man sich bei der Entwicklung unter Windows nie zu sicher sein sollte. Je nach Emulator kann es z. B. sein, dass sich der Fehler nicht oder anders zeigt. Auch wenn VICE und CCS64 echt super sind, ein Programm sollte zusätzlich immer auf einem echten C64 getestet werden. Um so trickreicher eure Effekte sind, um so wichtiger wird dies natürlich. Die Grenzbereiche der Hardware sind eher ein Problem für Emulatoren, als die Hausmannskost.
Schritt 13 - Landung 003
Hi,
Darf man hinter einem incbin keinen ;rem machen? Habe jetzt fast eine Stunde lang nach dem Bug gesucht. Ich hatte ganz unten
incbin "lander.spt",1,5,true ;rem Kommentar
, dann passen die Sprites nicht mehr. Komisch.Schönen Urlaub noch.
Hallo,
ja du hast recht (wieder mal 😉 ).
Ein Kommentar hinter dem TRUE führt dazu, dass dieses nicht mehr korrekt ausgewertet wird. Die Sprites werden dann nicht auf 64-BYTEs aufgefüllt!
Da dies auch bei meiner BETA 3.1 noch der Fall ist, habe ich Arthur das Problem mitgeteilt.