Erstellt: 1. Dezember 2013 (zuletzt geändert: 1. November 2021)

Landung 009

Sound abspielen und dann nichts wie raus

C64 Studio

So, nun sind wir fast am Ende des zweiten Levels angelangt. Im abschließenden Beitrag wollen wir jetzt noch das Programm etwas aufpolieren. Um es wirklich hübsch zu machen, fehlt uns zwar noch einiges an Wissen, aber mit zwei kleinen Änderungen möchte ich mal zeigen, wo der Weg hinführen kann. Wie in L.O.V.E. – Die Planung unter Punkt 7 erwähnt, sollten / müssen wir ganz zum Schluß das komplette Projekt nochmal überarbeiten, um ein professionelles Ergebnis zu erhalten.

Sound für die Schubdüsen

Auch wenn ich immer noch nicht auf die Soundprogrammierung eingegangen bin, laßt uns, wie beim Puzzle, zumindest für ein Geräusch sorgen. Es wäre doch schön, wenn die Düsen auch hörbar sind. Da Rauschen dafür nahezu perfekt geeignet ist, baut doch diese neue Funktion ins Programm ein, z. B. vor initFuel.

!zone soundThrust
;*******************************************************************************
;*** Ton für die Steuerdüsen
;*******************************************************************************
;*** Übergabe: -
;*******************************************************************************
;*** Rückgabe: -
;*******************************************************************************
;*** ändert  : A, SR
;*******************************************************************************
soundThrust
 lda #SID_WAVE_WHITENOISE          ;Rauschen
 sta SID_VOICE1_WAVEFORM           ;für die 1. Stimme
 lda #$05                          ;niedrige Frequenz                          
 sta SID_VOICE1_FREQ_MSB           ;für die erste Stimme
 lda #$FF
 sta SID_SUSTAIN_RELEASE           ;Anschlag & Abschwellen
 sta SID_VOLUME                    ;Lautstärke 
 rts                               ;zurück

Diese Routine entspricht eigentlich der, aus dem Puzzle. Wir setzen diesmal nur Sustain und Release, sowie die Lautstärke aufs Maximum. Der Rest bleibt unverändert. Jetzt müssen wir unseren Soundeffekt natürlich noch starten und beenden. Dies machen wir zunächst einfach in der Funktion checkInput.

Ändert das Programm dort ab .exit wie folgt:

.exit                               ;im X-Register stehen die sichtbaren 
 stx VIC_SPRITEACTIVE               ;Sprites, die wir jetzt wieder setzen
 txa                                ;aktive Sprites in den Akku
 and #%00001110                     ;prüfen ob eine der Düsen aktiv ist
 beq .skip                          ;falls nicht Sound aus bei .skip
 jsr soundThrust                    ;sonst Sound aktivieren
 rts                                ;zurück
.skip
 lda #$00
 sta SID_VOLUME                     ;Lautstärke auf 0 setzen (Sound aus)
 rts                                ;zurück

Wir holen uns hier die aktiven Sprites in den Akku und prüfen, ob eine der Düsen „unter Feuer steht“. Ist das der Fall, dann springen wir nach soundThrust um den Soundeffekt zu starten. Falls keine Düse aktiv ist, setzen wir bei .skip die Lautstärke einfach auf 0. Da es sonst keine Effekte oder Musik gibt, können wir das einfach so machen.

Startet ihr das Spiel nun, dann vernehmt ihr hoffentlich ein wohliges Rauschen, sobald die Düsen sichtbar sind. Ein Problem fällt euch wahrscheinlich spätestens beim Ableben oder einer Landung auf. Der Sound bleibt bestehen! Daher sollten wir den, bei der Landung und beim „Gameover“ noch abschalten.

Fügt dazu direkt hinter ;sonst -> gelandet die Zeilen

 lda #$00
 sta SID_VOLUME                 ;Lautstärke auf 0 setzen

ein, um den Ton abzuschalten (wir setzen hier einfach wieder die Lautstärke auf 0).

Bei gameover werden bereits die Sprites abgeschaltet, fügt hinter sta VIC_SPRITEACTIVE ;Sprites abschalten noch die Zeile sta SID_VOLUME ;Lautstärke auf 0 setzen ein.

Jetzt endet unser Düsensound auch bei einer Landung oder falls wir scheitern.

Den Canyon verlassen

Da der Spieler in unserem nächsten Level – „Die Fahrt zur Basis“, eben genau dies machen muss, eben zur Basis zu fahren, schaffen wir noch eine passende Überleitung, indem wir nach der erfolgreichen Landung zeigen, wie das Fahrzeug den Canyon verläßt.

Also habe ich noch ein weiteres Spriteprojekt „Finished.spriteproject“ angelegt und eine Mini-Version des Space-Rovers als MultiColor-Sprite entworfen. Damit es nicht so aussieht, als sei der Space-Rover aus dem Landungsschiff gezaubert worden, habe ich noch ein Singlecolor-Sprite vorbereitet, dass die geöffnete Luke des Schiffes darstellen soll.

Rover und Luke.
Rover und Luke

Um diese Sprites nun ins Programm einzubauen, müssen wir natürlich als erstes wieder den Assembler anweisen die neuen Sprites zu laden. Fügt dazu, ziemlich am Ende des Sourcecodes, hinter den bisherigen Sprite, die neuen Sprites ein.

;*** Die Sprites
!align 63,0
spriteSpaceship
 !media "Ship.spriteproject",sprite,0,5
spriteFuel
 !media "Fuel.spriteproject",sprite,0,3
spriteFinished
 !media "Finished.spriteproject",sprite,0,2

Wir machen es uns nun auch wieder ganz einfach. Begebt euch zum gameloop und führt die folgenden Änderungen, direkt vor der Zeile lda #COLOR_LIGHTGREEN ;mit grün anzeigen, dass alles gut ist, durch.

 lda #COLOR_BLACK                   ;da wir die Sprites überschreiben
 sta VIC_SPRITE1COLOR               ;die neuen Farbe setzen
 lda #COLOR_GREY
 sta VIC_SPRITE0COLOR
 lda #COLOR_BLACK
 sta VIC_SPRITEMULTICOLOR0
 lda #COLOR_WHITE
 sta VIC_SPRITEMULTICOLOR1

Außer dem Landungsschiff, sind alle Sprites deaktiviert. Für unsere Schlußsequenz benötigten wir noch neue Spritefarben. Daher setzen wir die Farben für den Space-Rover (dieser wird gleich Sprite-0) und für die offene Luke (wird Sprite-1). Solltet ihr euch jetzt fragen, warum wir die offene Luke nicht, wie die bisher geschlossene, als Sprite-0 und den Rover als 1 anlegen, dann schaut euch nochmal an wie die Sprites gezeichnet werden. Wir wollen es ja hübsch machen 😉 .

Jetzt müssen wir wieder die entsprechende Nummer des 64-Byte-Blocks für den VIC berechnen. Fügt also die folgenden Zeilen, hinter denen von eben ein.

 ldx #spriteFinished/64             ;Adresse für den Rover
 stx SPRITEPOINTER0
 inx                                ;die Luke befindet sich direkt dahinter
 stx SPRITEPOINTER0+1

Nun haben wir dem VIC gezeigt, wo die Spritedaten liegen, jetzt müssen wir die Sprites noch positionieren und einige Register setzen.

 lda VIC_SPRITE4X                   ;den Rover positionieren
 clc
 adc #$0B
 sta VIC_SPRITE0X
 tax                                ;Position für Bewegung ins X-Reg
 lda #%00010011
 sta VIC_SPRITEACTIVE               ;Sprites aktivieren
 lda #%00000001
 sta VIC_SPRITEMULTICOLOR           ;der Rover ist Multicolor!

Da die Landeposition variieren kann, müssen wir hier die X-Position für den Rover zur Laufzeit berechnen. Der Rest ist soweit bekannt.

Nun lassen wir den Rover nach rechts aus dem Canyon fahren.

@loop:
 ldy #$30                       ;etwas Zeit für die
 sty calc16bit:                 ;Bewegung des Rovers verschwenden
 dec calc16bit:
 bne *-3
 dey
 bne *-9
 inx                            ;X-Position erhöhen
 stx VICSPRITE0X                ;und ins VIC-Register schreiben
 bne @loop:                     ;solange nicht 0 -> @loop:
 lda VICSPRITESMAXX             ;sonst prüfen, ob für die X-Posi
 and #%00000001                 ;bereits das höchste BIT gesetzt ist
 bne @skip1:                    ;falls ja sind wir fertig -> @skip:
 inc VICSPRITESMAXX             ;sonst höchstes BIT setzen
 jmp @loop:                     ;und zum Beginn der Schleife springen
@skip1:
 lda VICSPRITEACTIVE            ;zur Sicherheit noch den Rover 'abschalten'
 and #%11111110
 sta VICSPRITEACTIVE

Damit der Rover nicht zu schnell bewegt wird, bauen wir bei .loop eine Verzögerung ein (bei Verwendung einer Super-CPU werden solche Warteschleifen natürlich viel schneller durchlaufen). Wenn diese zwei verschachtelten Schleifen abgearbeitet sind, erhöhen wir das X-Register (dort steht immer noch die X-Position drin) und beachten dabei, dass wir auch das Bit für die maximale X-Position in $d010 setzen müssen. Dies machen wir, wenn das Bit noch nicht gesetzt wurde und die X-Position 0 ist. Wird die X-Position 0 und das höchste Bit ist bereits gesetzt, dann verlassen wir die Schleife durch einen Sprung nach .skip1. Dort schalten wir noch den Rover ab und das Programm läuft dann wie bisher (BS grün, auf Feuer warten) weiter.

Hinter FuelClear brauchen wir jetzt noch die Hilfsvariable für die obige Berechnung:

Calc16Bit
 !word 0

Führt ihr jetzt eine erfolgreiche Landung aus, dann könnt ihr beobachten, wie der Space-Rover den Canyon verläßt. Nachdem er den sichtbaren Bereich bereits verlassen hat, dauert es etwas, bis der Bildschirm endlich grün wird. Dass könnt ihr ja noch anpassen.

Ein letztes Problem wollen wir aber noch gemeinsam lösen. Da wir unseren IRQ gestoppt haben, verschwindet auch des Lasernetz. Dadurch sieht es während der Rover-Fahrt so aus, als sei der Canyon eine Höhle, weil der Himmel verschwindet.

Der Rover fährt, aber ohne den Himmel sieht es blöd aus!
Der Rover fährt, aber ohne den Himmel sieht es blöd aus!

Wir sollten nun also unseren Raster-IRQ bei einer Landung aktviert lassen, aber natürlich gleichzeitig dafür sorgen, dass man nicht wieder losfliegen kann.

Löscht erstmal bei gameloop die markierte Zeile mit dem sei-Befehl.

 bmi gameloop                       ;falls ja, Hauptschleife
 sei                                ;IRQs sperren
 beq gameover                       ;falls 0 -> crash
                                    ;sonst -> gelandet

Damit bleibt der Interrupt weiterhin aktiv, egal ob das Schiff zerstört oder gelandet wurde.

Um nun zu verhindern, dass das Schiff weiterhin sinkt bzw. steuerbar ist, fügen wir noch zwei kleine Prüfungen in unseren Interrupt ein.
Bei landerIRQ begeben wir uns vor die Zeile jsr updateSprites ;Sprites positionieren und fügen die Prüfung ein.

 lda Alive                          ;prüfen, ob das Schiff noch aktiv ist
 bpl *+5                            ;falls nicht -> updatesprites: überspringen

Hier kontrollieren wir, ob Alive positiv ist. Denkt daran, wie wir die Variable verwenden: ;-1 = OK, 0 = zerstört, 1 = gelandet. Wir rufen updateSprites also nur auf, solange Alive den Wert -1 hat (nicht vergessen, 0 gilt auch als positiv!), anderenfalls wird der Funktionsaufruf übersprungen.

Der freie Fall ist somit gestoppt, nun müssen wir noch die Eingabe unterbinden. Sucht die Anweisung jsr checkInput ;Joystick verarbeiten und fügt davor nochmal die Prüfung für Alive von eben ein.

 lda Alive                          ;prüfen, ob das Schiff noch aktiv ist
 bpl *+5                            ;falls nicht -> updatesprites: überspringen

Um ein unschönes Flackern zu verhindern, löscht abschließend noch hinter waitForFire das setzen der Rahmenfarbe. Wir färben nun nur noch den Canyon-Hintergrund rot und grün ein.

Jetzt sieht es schon besser aus…

Keep watching the sky - again.
Keep watching the sky – again.

Falls ihr bis hierhin alles 1:1 übernommen habt, kommt es zu einem weiteren Problem:

Beachtet die Treibstoffanzeige.
Beachtet die Treibstoffanzeige.

Die Treibstoffanzeige sieht komisch aus.

Wir haben uns bisher überhaupt keine Gedanken darum gemacht, wo wir welche Daten im Speicher ablegen. Dies ist die Ursache für unser neues Problem und wird eins der ersten Themen beim nächsten Level. Verschiebt für den Moment, einfach die Daten (s. u.) ganz ans Programmende.

!zone Data
;*******************************************************************************
;*** Daten
;*******************************************************************************
LaserFlash
 !byte $00                          ;Rahmenfarbe fürs Laser-Raster

Spaceship_PosX
 !byte $00
 !byte SPACESHIP_STARTX             ;X- und  
Spaceship_PosY
 !byte $00
 !byte SPACESHIP_STARTY             ;Y-Position des Landungsschiffs
 
Spaceship_SpeedX
 !word $00
Spaceship_SpeedY
 !word $00

InputState
 !byte $00                          ;letzte Joystickeingabe

Alive                               ;Zustand des Landungsschiffes
 !byte $00                          ;-1 = OK, 0 = zerstört, 1 = gelandet

FuelCounter
 !byte $00                          ;Zähler für Treibstoffverbrauch

FuelClear
 !byte $00                          ;nächstes Byte, das gelöscht werden soll

Calc16Bit
 !word 0

Wie ihr seht, kann das Feintuning einiges an Zeit kosten und dies war nur ein kleiner Vorgeschmack, was man zur Verbesserung machen kann. Natürlich gibt es noch viel mehr: hübschere Grafiken (besonders der Canyon), beim Ableben eine Explosion anzeigen und einen passenden Sound-Effekt abspielen, evtl. etwas Musik, eine Punkteanzeige, usw.


Wir schließen die Landung nun aber ab und wenden uns dem 3. Level „Die Fahrt zur Basis“ zu. Dort wollen wir endlich etwas entwickeln, dass man auch mal vorzeigen kann.

Bis dahin, gutes Gelingen,
Jörn


Schrott!!Naja...Geht so...Ganz gut...SUPER! (4 Bewertungen | Ø 5,00 von 5 | 100,00%)

Loading...


ZurückWeiter

Schreibe einen Kommentar

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

Protected by WP Anti Spam