Puzzle 004

Für diesen Beitrag wurde das CBM prg Studio verwendet.
weitersagen ...
Tweet about this on TwitterShare on FacebookShare on Google+Share on LinkedIn

CBM prg Studio
Lauter Tabellen

Es wird Zeit das Bewegen der Puzzleteile in Angriff zu nehmen. Wie wollen wir das jetzt umsetzt? Ich schlage vor, wir nummerieren die Felder zunächst von 1 bis 9 durch:

Love_1_4_1

 

Dann merken wir uns in einer Tabelle  tileorder: welches Puzzleteil sich auf welchem Feld befindet.
Tabellen werden von euch sehr häufig benötigt, z. B. für Colorcycling-Effekte oder wenn ihr etwas Sinusförmig bewegen möchtet. Daher verwenden wir zur Übung gleich mal drei davon, auch wenn wir einige Werte durchaus zur Laufzeit berechnen könnten.
Da wir den Ansatz Puzzleteil = Sprite-Nr. verfolgen, wissen wir so auch gleich welches Sprite auf welchem Feld zufinden ist. Wir speichern einfach die jeweilige Sprite-Nr. in der Tabelle, allerdings müssen wir noch das leere Feld beachten. Um dies zu erkennen speichern wir dafür $FF.
Fügt das Label  tileorder: und die BYTE-Anweisungen am Besten hinter dem Hilfsregister  calc16Bit: ein.

Die obige Tabelle enthält wieder die Positionen, so wie sie bei der Lösung des Puzzles vorliegen müssen. Wie ihr seht können wir jetzt auch sehr einfach erkennen, ob das Puzzle gelöst wurde. Im letzten Feld muss das leere stehen und davor müssen die Nr. aufsteigend sortiert sein. Das ich die Tabelle als 3*3 BYTES angelegt habe ist nur ein Zugeständnis an unser Vorstellungsvermögen. So fällt es uns leichter die jeweilige Position zu erkennen. Wir hätten die Werte auch alle direkt hintereinander in eine BYTE-Anweisung schreiben können, so wie sie später auch im Speicher zu finden sind. Die ‚optische‚ Aufbereitung im Source hat also keinen Einfluß darauf, wie die BYTES später im Speicher abgelegt sind. Wer möchte kann auch alle neun BYTES einzeln untereinander schreiben.

Um die Sprites zu positionieren, speichern wir uns als nächstes einfach die möglichen Startkoordinaten für jedes Feld in einer kleinen Tabelle ab. Da wir darauf geachtet haben, dass kein Sprite nach der X Position 255 gezeichnet werden muss, reichen uns zwei BYTES, je eins für die X- und Y-Position.

Fügt das Label spritepos: und die BYTE-Anweisungen direkt hinter der Tabelle von eben ein.

Hier findet ihr nun die Werte, wie wir sie im vorherigen Beitrag direkt beim Laden der Sprites verwendet haben. Einzige Ausnahme bilden die Koordinaten fürs 9. Feld. Da wir die Puzzleteile verschieben müssen, landen natürlich auch Sprites unten rechts. Wie ihr evtl. in der Tabelle besser seht, ließen sich die X und Y Position auch einfach berechnen.

Die letzte Tabelle könnten wir uns wirklich sparen, aber im Sinne der Übung, legen wir noch eine an. Möchten wir jetzt z. B. für das 3. Feld die Sprite-Position haben, dann müssen wir ja den Anfang ermitteln. Das kann man natürlich ganz einfach mit (Feld-1)*2 berechnen, aber wir benutzen, wie angedroht, noch eine Tabelle.
Fügt die Tabelle vor dem Label spritepos: ein.

Wie ihr seht steht hier für jedes Feld das Ergebnis der eben erwähnten Formel.

 

Routine zum Positionieren der Sprites
OK, wir haben jetzt lauter Tabellen, nun wollen wir die auch mal verwenden. Wir schreiben eine Routine, die alle Sprite anhand der Tabellen setzt.
Fügt die Funktion einfach hinter dem  rts  der loadsprites:-Routine ein.

Zu Beginn holen wir uns die Anzahl der Felder ins X-Register. Da wir von 8 bis 0 durch die Felder gehen, möchte ich nochmal auf den Unterschied zwischen unserer Zählung und der Position in der Liste eingehen. Da ich die Felder von 1-9 nummeriert habe, so wie es die meisten wohl intuitiv machen würden, müssen wir darauf achten, dass die Position im Speicher von 0 bis 8 geht.

Wir finden also den Inhalt von Feld 3 an der Adresse von  tileorder: plus 2 oder allgemein ausgedrückt an Adresse von tileorder: + (Feld-Nr. - 1).

Etwas ungewöhlich kommt euch evtl. das nächste Label  @loop: vor. Durch diese Schreibweise erkennt das CBM prg Studio, dass es sich um ein sog. ‚cheap label‚ handelt.

Exkurs ‚cheap label‚
Achtung: Das Verhalten der Cheap-Label wurde ab Version 2.8.0 geändert, beachtet bitte die rot hervorgehobenen Hinweise!
Beginnt ein Label mit einem @, dann behandelt es das CBM prg Studio als ‚cheap label‚. Durch ‚cheap label‚ ist es möglich ein Label mehrfach zu verwenden. Ein ‚cheap lable‚ ist nur innerhalb eines Blocks sichtbar. Daher kann der selbe Name immer wieder benutzt werden. Der eben erwähnte Block (also die Sichtbarkeit eines Cheap-Label) wird durch ‘normale‚ Label gebildet.

Was bringen uns ‚cheap label‚?
Wir hatten schon häufiger das Problem, dass wir in verschiedenen Routinen z. B. Schleifen bilden mussten. Es war jedesmal eine Qual sich eindeutige Labelnamen auszudenken. Häufig wurde etwas wie <Name der Routine>_loop: gemacht. Hier hätten wir jetzt für unsere Schleife das Label spritessetposition_loop: anlegen können, in der nächsten Funktion würden wir dann ein moveall_loop: benötigen usw.. Aber dank der ‚cheap label‚ können wir überall einheitlich @loop: verwenden.
Der folgende Block trifft nicht mehr zu! Doppelte Cheap-Label führen zu einer Fehlermeldung! Allerdings sollte ihr es auch bei den ‚cheap label‚ nicht übertreiben, sonst wird es unübersichtlich:

 

Auch dies trifft nicht mehr zu! Durch die oben erwähnte Änderung der Sichtbarkeit könnt ihr folgenden Block problemlos verwenden! Damit es nicht zu einfach wird, müsst ihr aber eins beachten: Euer ‚cheap label‚ muss vor dem Sprung definiert sein!!
Um dass zu verdeutlichen werft noch einen abschließenden Blick auf diesen Code:

Wenn ihr diesen Code übersetzt, dann wird euch der Assembler einen „invalid branch beq @loop:„ Fehler auswerfen. Das liegt daran, dass der Assembler beim  beq @loop:  davon ausgeht, dass das ‚cheap label‚  @loop:  aus  function_1:  gemeint ist (das ist das einzige, dass er bisher kennt) und da die Sprungweite nun über 128 BYTES liegt, kommt die Fehlermeldung. Ganz übel wird es wenn das Label in Reichweite ist, dann gibt es keine Warnung vom Assembler und euer Programm funktioniert nicht so wie erwartet.

Die ‚cheap label‚ sind wirklich hilfreich. Ich habe sie bisher nur nicht verwendet, da sie beim CBM prg Studio 2.5.3 nicht richtig funktioniert haben.
Also macht euch das Leben nicht unnötig schwer und verwendet, nur wo es Sinn macht, die ‚cheap label‚. Wieder hinfällig, achtet aber unbedingt auf die richtige Reihenfolge (erst ‚labeln‚, dann springen) und benutzt sie nicht inflationär.
Leider führen die Änderungen ab 2.8.0 nun trotzdem dazu, dass es zu Problemen mit meinen Beispielen kommen kann!
Behaltet also die hervorgehobenen Anmerkungen im Gedächtnis, für den Fall, dass sich mal etwas nicht übersetzen läßt. Stoßt ihr auf ein solches Problem, dann bin ich für eine kurze Info dankbar, damit ich die Abschnitte korrigieren kann..

Zurück zu unserer Routine…

Hinter dem  @loop:  holen wir uns den Inhalt des jeweiligen Feldes ins Y-Register. Ist dies negativ, haben wir das leere Feld und müssen keinen Sprite positionieren, also springen wir zum nächsten ‚cheap label‚ @skip:. Wenn der Wert nicht negativ ist, haben wir einen Sprite und müssen den jetzt positionieren. Als erstes merken wir uns das X-Register auf dem Stack, da wir es gleich verändern und es auch als Schleifenzähler fungiert. Um mit der Y-indizierten Adressierung gleich auf die richtigen Register zuzugreifen, müssen wir den Inhalt von Y noch mit zwei multiplizieren. Dazu einfach Y in den Akku kopieren, den Akku um ein BIT nach links ‘shiften‚ und wieder zurück ins Y-Register kopieren. Wir wollen nicht nochmal rechnen, also holen wir uns über die Hilfstabelle spriteposhelper: die richtige Position für den Zugriff auf die Tabelle spritepos:, in der ja unsere Koordinaten stehen, in den Akku. Da wir per X-indizierter Adressierung auf die Tabelle  spritepos:  zugreifen kopieren wir den Akku ins X-Register.
Nun kommt die eigentliche Positionierung, wir holen uns zunächst mit  lda spritepos:,X  die X-Position in den Akku und speichern diese dann mittels  sta SPRITE0X,Y im jeweiligen Register für die Sprite-X-Position. Falls euch nicht ganz klar ist, warum wir das Y-Register für die Adressierung mit zwei multipliziert haben, werft noch mal einen Blick auf die Sprite-Register. Anschließend machen wir dasselbe für die Y-Position.
Jetzt noch den auf dem Stack gemerkten Schleifenzähler wieder ins X-Register holen, verringern und die Schleife abarbeiten, bis alle Felder durchgegangen wurden.
Dann haben wir das Ende der Funktion erreicht und kehren zum Aufrufer zurück.

Als letztes müssen wir unsere Funktion jetzt natürlich noch aufrufen. Sucht das Label  loadnextsprite: und kurz dahinter den Kommentar ;*** Sprites positionieren. Löscht alles bis zum nächsten Kommentar  ;*** Hauptfarbe für alle Sprites auf blau setzen  und ersetzt es mit dem Aufruf unserer neuen Routine:

 

So, wenn ihr das Programm jetzt startet seht ihr…keine Änderung :-(. Wozu nun der ganze Aufwand? Wer alles aufmerksam verfolgt hat, dem sollte der Vorteil aufgefallen sein. Wir können die Sprites jetzt einfach durch Veränderung der Tabelle  tileorder:  beeinflussen.

Im herunterladbaren Projekt findet ihr einen Kommentar, über den ihr das mal testen könnt.

Entfernt einfach das Semikolon vor der BYTE-Anweisung und startet das Programm.

Die Sprites haben sich bewegt, die Hintergründe leider noch nicht.
Die Sprites haben sich bewegt, die Hintergründe leider noch nicht.

Richtig toll sieht es allerdings noch nicht aus, aber darum kümmern wir uns im nächsten Beitrag.


 

Das wars mal wieder, beim nächsten Mal verschieben wir auch den Hintergrund unserer Puzzleteile.

Start im Java Emulator

 


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

Loading...


 

<<< zurück | weiter >>>

 

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

Schreibe einen Kommentar


Beachtet bitte, dass ich eure Kommentare erst manuell freigegeben muß, bevor sie auf der Seite erscheinen! Da ich nicht pausenlos am Rechner sitze, kann es schon mal etwas dauern, bis ein Kommentar für alle sichtbar ist.

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

Protected by WP Anti Spam