Die ersten Sprites
Es wird Zeit, wie versprochen, endlich die ersten Sprites in unser Programm einzubauen. Beachtet bitte, dass der Beitrag relativ kurz wirkt, wie angedroht habe ich die allgemeinen Grundlagen ausgelagert.
Bevor ihr hier fortfahrt, schaut euch zunächst die Sprite-Grundlagen an.
Die Sprites zeichnen
Fügt dem Projekt jetzt ein Sprite Set hinzu und nennt es „Tiles.spriteproject“.
Stellt am besten alles, so wie auf dem folgenden Bild ein. Sehr wichtig ist der Multi-Color-Modus! Denkt auch daran, dass wir für die Sprites 40 * 40 Punkte (durch Verdopplung in X- und Y-Richtung) vorgesehen haben. Daher dürft ihr die beiden letzten Spalten rechts und die letzte Zeile unten nicht benutzen! Auch hier sollte ein Blick auf das Bild für Klarheit sorgen.
Entwerft dann, wie oben auf dem Bild, sieben Sprites, die euere Puzzleteile darstellen. Damit sich alles gut zusammenfügt, achtet auf die Übergänge. Außerdem solltet ihr auf die Reihenfolge der Sprites achten. Legt sie so an, dass sie in das folgende Raster passen und so das fertige Puzzle ergeben.
0 1 2 3 4 5 6 7
Im Editor findet ihr rechts noch den Reiter » Preview «. Damit könnt ihr eure Sprites frei positionieren und kontrollieren, ob die Übergänge der Sprites passen.
So sehen die von mir vorbereiteten Sprites aus.
Diese sollen Drähte darstellen, die vom Spieler später verbunden werden müssen. Gleich im Programm erkennt ihr noch besser, wie sich alles zusammenfügt 😉 .
Sprites in den Source aufnehmen
Bevor es wirklich losgeht, fügt erstmal zu „Puzzle.asm“ eine Reihe von Konstanten hinzu, die gleich benötigt werden. Diese sollten aus dem bereits eingangs erwähntem Beitrag Sprites (ASM) bekannt sein.
SPRITE0X = $d000 ;(00) X-Position von Sprite 0 SPRITE0Y = $d001 ;(01) Y-Position von Sprite 0 SPRITE1X = $d002 ;(02) X-Position von Sprite 1 SPRITE1Y = $d003 ;(03) Y-Position von Sprite 1 SPRITE2X = $d004 ;(04) X-Position von Sprite 2 SPRITE2Y = $d005 ;(05) Y-Position von Sprite 2 SPRITE3X = $d006 ;(06) X-Position von Sprite 3 SPRITE3Y = $d007 ;(07) Y-Position von Sprite 3 SPRITE4X = $d008 ;(08) X-Position von Sprite 4 SPRITE4Y = $d009 ;(09) Y-Position von Sprite 4 SPRITE5X = $d00a ;(10) X-Position von Sprite 5 SPRITE5Y = $d00b ;(11) Y-Position von Sprite 5 SPRITE6X = $d00c ;(12) X-Position von Sprite 6 SPRITE6Y = $d00d ;(13) Y-Position von Sprite 6 SPRITE7X = $d00e ;(14) X-Position von Sprite 7 SPRITE7Y = $d00f ;(15) Y-Position von Sprite 7 SPRITESMAXX = $d010 ;(16) Höhstes BIT der jeweiligen X-Position ; da der BS 320 Punkte breit ist reicht ; ein BYTE für die X-Position nicht aus! ; Daher wird hier das 9. Bit der X-Pos ; gespeichert. BIT-Nr. (0-7) = Sprite-Nr. SPRITEACTIVE = $d015 ;(21) Bestimmt welche Sprites sichtbar sind ; Bit-Nr. = Sprite-Nr. SPRITEDOUBLEHEIGHT = $d017 ;(23) Doppelte Höhe der Sprites ; Bit-Nr. = Sprite-Nr. SPRITEDEEP = $d01B ;(27) Legt fest ob ein Sprite vor oder hinter ; dem Hintergrund erscheinen soll. ; Bit = 1: Hintergrund vor dem Sprite ; Bit-Nr. = Sprite-Nr. SPRITEMULTICOLOR = $d01c ;(28) Bit = 1: MultiColor Sprite ; Bit-Nr. = Sprite-Nr. SPRITEDOUBLEWIDTH = $d01d ;(29) Bit = 1: Doppelte Breite des Sprites ; Bit-Nr. = Sprite-Nr. SPRITEMULTICOLOR0 = $d025 ;(37) Spritefarbe 0 im Multicolormodus SPRITEMULTICOLOR1 = $d026 ;(38) Spritefarbe 1 im Multicolormodus SPRITE0COLOR = $d027 ;(39) Farbe von Sprite 0 SPRITE1COLOR = $d028 ;(40) Farbe von Sprite 1 SPRITE2COLOR = $d029 ;(41) Farbe von Sprite 2 SPRITE3COLOR = $d02a ;(42) Farbe von Sprite 3 SPRITE4COLOR = $d02b ;(43) Farbe von Sprite 4 SPRITE5COLOR = $d02c ;(44) Farbe von Sprite 5 SPRITE6COLOR = $d02d ;(45) Farbe von Sprite 6 SPRITE7COLOR = $d02e ;(46) Farbe von Sprite 7 SPRITE0DATA = $07f8 ;Sprite-Pointer für die Sprite-0-Daten
Wie bei den Bildschirmen, können wir die Sprites über !media einbinden. Als Dateinamen geben wir unseren oben festgelegten Namen Tiles.spriteproject an. Dann folgt der Typ, hier sprite. Ohne weitere Angaben, würden jetzt 256*64 Bytes belegt werden. Da wir nur acht Sprites entworfen haben, sorgen wir mit dem abschließenden ,0,8 dafür, dass ab dem ersten Sprite (die Zählung beginnt bei 0!) acht Sprites geladen werden. So werden nur 512 Bytes, statt 16KB (16384 Bytes) Speicher belegt.
;*** unsere Puzzleteile !align 63,0 spriteTiles !media "Tiles.spriteproject",sprite,0,8
Fügt diesen Block auf jeden Fall VOR screenTitle und screenPuzzle ein, sonst seht ihr am Ende nur „Grütze“.
Die Erklärung, weshalb dies passiert, gibt es später, wenn wir uns mit der Speicherorganisation des C64 beschäftigen.
Wie bei Sprites (ASM) erwähnt, sorgt !align 63,0 dafür, dass die kommenden Bytes (oder auch Anweisungen) an einer Adresse beginnen, die bei einer UND-Verknüpfung mit der ersten Zahl 0 ergibt. Für die Sprites benötigen wir eine durch 64 teilbare Adresse. Anschließend folgt unser Label spriteTiles und dann unsere Daten.
In puzzleMain benötigen wir einen Aufruf für unsere Laderoutine. Fügt vor puzzleMainLoop einfach jsr loadSprites ein.
jsr loadSprites ;Sprites kopieren ;******************************************************************************* ;*** Eingabeschleife für das Puzzle ;******************************************************************************* puzzleMainLoop ;Start der Endlosschleife jmp puzzleMainLoop ;Endlosschleife
Die Laderoutine
Zu Beginn berechnen wir den ersten 64-Byte-Block. An dieser Stelle liegt unser erstes Sprite. Für die Berechnung verwende ich die zweite Methode, die am Ende von Sprites (ASM) erklärt wurde.
;******************************************************************************* ;*** Sprites initialisieren ;******************************************************************************* ;*** Übergabe: - ;******************************************************************************* ;*** Rückgabe: - ;******************************************************************************* ;*** ändert : A, X, Y, SR ;******************************************************************************* !zone loadSprites loadSprites ;*** 64-Byte-Block berechnen lda #<spriteTiles ;LSB der Spritedaten holen sta calc16Bit ;im 'Hilfsregister' speichern lda #>spriteTiles ;MSB auch sta calc16Bit+1 ;ins 'Hilfregister' ldx #$02 ;Schleifenzähler .loop asl calc16Bit ;LSB nach links 'shiften' rol calc16Bit+1 ;MSB nach links 'rotieren', wg. Carry-Flag! dex ;Schleifenzähler verringern bne .loop ;wenn nicht 0, nochmal ldy #$00 lda calc16Bit+1 ;Im MSB des 'Hilfsregisters' steht der 64-Byte-Block
Jetzt wird noch die Variable calc16Bit benötigt, fügen wir diese einfach hinter inputState ein.
;*** Hilfsregsiter für 16-Bit-Operationen calc16Bit !word $0000
Im Akku haben wir nun den ersten 64-BYTE-Block, diesen verwenden wir jetzt, um die Startadresse der Daten für alle Sprites zu setzen. Da unsere Sprites direkt hintereinander liegen müssen wir den Akku nur für jedes Sprite um eins erhöhen.
;*** Start Block für alle Sprites setzen .next sta SPRITE0DATA,Y ;In der zuständigen Speicherstelle ablegen clc adc #$01 ;Das nächste Sprite folgt direkt dahinter, also +1 iny cpy #$08 bne .next
Anschließend positionieren wir unsere Sprites erstmal so auf dem Spielfeld, wie sie nach der Lösung des Puzzles stehen müssten. Die Positionen könnt ihr durch abzählen der Zeichenabstände und unter Zuhilfenahme der Grafik vom Beitrag Sprites berechnen. Wie im vorherigen Beitrag erwähnt, sind die Sprites 20*20 Pixel groß und werden im Programm in beide Richtungen vergrößert, um auf die gewünschte Endgröße von 40*40 Pixel zu kommen. Somit nehmen die Sprites exakt den Platz von 5*5 Zeichen auf dem Bildschirm ein.
;*** Sprites positionieren ldx #$40 ldy #$5a stx SPRITE0X sty SPRITE0Y ldx #$40+40 stx SPRITE1X sty SPRITE1Y ldx #$40+80 stx SPRITE2X sty SPRITE2Y ldx #$40 ldy #$5A+40 stx SPRITE3X sty SPRITE3Y ldx #$40+40 stx SPRITE4X sty SPRITE4Y ldx #$40+80 stx SPRITE5X sty SPRITE5Y ldx #$40 ldy #$5A+80 stx SPRITE6X sty SPRITE6Y ldx #$40+40 stx SPRITE7X sty SPRITE7Y
Die Farben müssen wir natürlich auch setzen. Alle Sprites haben als Hauptfarbe blau, für den Rahmen, sowie rot und grün für die Drähte.
;*** Hauptfarbe für alle Sprites auf blau setzen lda #COLOR_BLUE sta SPRITE0COLOR sta SPRITE1COLOR sta SPRITE2COLOR sta SPRITE3COLOR sta SPRITE4COLOR sta SPRITE5COLOR sta SPRITE6COLOR sta SPRITE7COLOR ;*** Multicolor-Farben setzen lda #COLOR_GREEN sta SPRITEMULTICOLOR1 lda #COLOR_RED sta SPRITEMULTICOLOR0
Zum Schluß sorgen wir noch dafür, dass alle Sprites vor dem Hintergrund auftauchen, in ihrer Breite und Höhe verdoppelt werden, Multicolor sind und schließlich aktiviert werden. Dann endet die Laderoutine und springt zurück.
;*** Die Sprites sollen VOR dem Hintergrund erscheinen lda #%00000000 sta SPRITEDEEP ;*** ALLE Sprites in Breite & Höhe verdoppeln, ;*** auf Multicolor setzen und aktivieren. lda #%11111111 sta SPRITEDOUBLEWIDTH sta SPRITEDOUBLEHEIGHT sta SPRITEMULTICOLOR sta SPRITEACTIVE rts ;Zurück
Nach einem Programmstart solltet ihr die Sprites auf dem Spielfeld sehen. Wie angekündigt, wurden die Sprites so entworfen, dass sie sich mit dem Hintergrund ergänzen.
Das war auch schon wieder alles, für dieses Mal. Wie gewohnt, folgt hier noch der Download.
Schritt 3 - Puzzle 003