Hello, Guest the thread was viewed64k times and contains 140 replies

last post from oobdoo at the

Portierung von LocoBasic zu Basic V7.0 am Beispiel Frutty Man

  • In diesem Threads soll anhand eines Beispielprogramms gezeigt werden, wie ein LocoBasic-Programm nach Basic V7.0 portiert werden kann. Das portierte Programm soll dabei vom Verhalten und Aufbau möglichst dicht am Originalprogramm sein. Allerdings ist es notwendig, an der einen oder anderen Stelle deutlich abzuweichen... Die Ziele dabei sind: die Möglichkeiten von Basic V7.0 aufzuzeigen, ein Verständnis für LocoBasic zu bekommen und Mut zu machen, andere interessante Basicprogramme zu portieren. Und nun zum Programm...


    Vor (fast) genau 30 Jahren, genauer September 1986, veröffentlichte die Compute das Geschicklichkeitsspiel "Frutty Man" für den Schneider CPC. Geschrieben wurde es von "unserem" oobdoo, der damals noch einen ganz normalen bürgerlichen Namen trug. Die meisten dürften dieses Ereignis verpasst haben, da wir ja alle mehr oder weniger damit beschäftigt waren zu zeigen, dass der Commodore besser ist als der Atari (oder war's umgekehrt?)... Zum Glück hat oobdoo die Screenshots und das Listing auf seine Homepage gestellt, so dass wir jetzt ans Portieren gehen können. Compute bezeichnet Frutty Man als "Gerüst- und Sammelspiel" und hebt den Special Effect beim Absturz der Spielfigur hervor (das ganze Gerüst wird erschüttert). Eine Info, die wir noch brauchen werden...


    Soviel erst mal zur Einstimmung, im nächsten Beitrag geht es dann um den Aufbau des Programms, verwendete Befehle und den gewählten Ansatz. Einige technische Überlegungen finden sich bereits in folgendem Thread: LocoBasic vs. Basic 3.5/7.0. Wobei ich nicht verheimlichen will, dass sich MacBacon und Syshack schon intensiv damit auseinandergesetzt haben...

  • So, erst mal den gebugfixten Code von Syshack holen ( LocoBasic vs. Basic 3.5/7.0) und weiter geht's im Programm. Zur weiteren Bearbeitung des Quellcodes habe ich Notepad++ verwendet - das hat paar nette Details, die das Leben einfacher machen. Als erstes habe ich die zerhächselten Zeilen wieder zusammengesetzt, damit wieder alles schick aussieht. Das Programm ist 274 Zeilen lang, die längste Zeile ist Zeile 1330 mit 236 Zeichen...


    Der grobe Hauptprogrammablauf ist wie folgt (in Klammern die Farbe mit dem der Codeabschnitt markiert ist):

    • Zeile 100- 400 (grün): Initialisieren
      Symbole (=Grafikelemente) definieren, Farbpalette festlegen, Grafikmodus sowie Rand- und Hintergrundfarbe setzen. Außerdem Spielfeldarray und Codefolge für Transparent an/aus festlegen und dann ab nach Zeile 1520
    • Zeile 1520-1600 (cyan): Titelbild zeigen
      ... und auf Feuerknopf warten. Ist der gedrückt - ab nach 410
    • Zeile 410- 510 (gelb): Hauptroutine
      ... (440) nacheinander die Level zeichnen und bei jedem Level
      ... 450-510 Joystick abfragen, Monster- und Spielerbewegung initieren
    • Je nach Todesart Zeile 1310-1400 (Absturz) oder 1610-1640 (Monster berührt) (schwarz)
      ... wenn noch Leben vorhanden sind - weiter nach 440 (Nr. 3 in dieser Liste)
      ... wenn alle Leben aufgebraucht - weiter nach 1410
    • Zeile 1410-1510 (schwarz): Game Over
      ... und dann zum Titelbild


    Die Teil-/Unterprogrammbereiche:

    • Monsterbewegung und -berührung (rot):

      • 520-570 - Vergleich Spielerposition zu Monsterposition und entsprechende Bewegung
      • 880-1250 - die einzelnen Bewegungen
    • Spielerbewegung und Absturzprüfungen (blau):

      • 580-870 - die einzelnen Bewegungen
    • Früchte einsammeln (weiß)

      • 1260 - 1300 - ggf. Erfolgsmeldung fürs Erreichen des Levelzieles
    • Levelroutinen (grün durchgestrichen)

      • 1650 - 1900 - Level 1 zeichnen
      • 1910 - 2220 - Level 2 zeichnen
      • 2230 - 2500 - Level 3 zeichnen
      • 2510 - 2690 - Level 4 zeichnen


    Jenseits der 2700 gibt es noch kleine Unterprogramme für Statustext, Spielfigur malen, Spielfeldarray zurücksetzen usw.



    Soviel zum Codegerüst, als nächstes kommen die verwendeten Variablen...

  • Variablen

    Variablenname Bedeutung
    a Laufvariable, mehrfach verwendet
    an1$ Transparenter Hintergrund beim Zeichnen aktivieren
    an2$ Transparenter Hintergrund beim Zeichnen deaktivieren
    fru Anzahl gesammelter Früchte
    frs Anzahl benötigter Früchte
    gx, gy, gs Position und Schrittgeschwindigkeit des Monsters
    ggx, ggy Alte Position des Monsters
    hsc, sc Highscore, Score
    j Joystick (Position, Feuerknopf)
    lev Aktuelles Level
    ma Anzahl Leben
    qwe Hilfsvariable für Verzögerungsschleifen, Soundeffekte, Startbildschirm...
    ra(20,25) Spielfeld, Inhalt hat folgende Bedeutung:
    10 - Frucht
    5 - Leiter
    4 - Plattform/Boden
    0 - leer
    x, y Position des Spielers
    xx, yy Alte Position des Spielers
    zx, zy Position der jeweiligen Frucht beim Spielfeldaufbau



    Symbole
    Wenn mehrere Charaktere für ein Objekt angegeben sind, dann werden diese Charaktere in der angegebenen Reihenfolge mit transparentem Hintergrund übereinandergezeichnet.

    Objekt Charakter (Ascii-Code)
    Frucht 102 + 101
    Plattform 100
    Leiter 103
    Monster 98 + 97 + 99
    Spielfigur 95 + 96 + 94 + 91 + 93 + 92
  • Hülllffää, mein Frutty Man wird seziert. :schreck!:


    Bei meiner Z80 Umsetzung wollte ich zuerst die Level genau 'malen' wie im BASIC. Das wurde aber zu umständlich, so das ich das über ein Array gelöst hatte.


    ***MacB darf nicht mitlesen***


    Ich habe das mit Excel gemacht: :whistling:Wert in Excel suchen


    ***MacB darf wieder mitlesen***

  • Und nicht nur das... im Moment bin ich am Umstricken, d.h. alle Variablennamen, die länger als zwei Zeichen sind werden auf zwei Zeichen eingekürzt (daher auch die Tabelle oben, da weiß ich, welche Variablennamen frei sind).


    Allerdings kam bereits von MacB der berechtigte Einwand, dass es klüger ist, das Programm vor der Konversion zu entwirren. Ich dagegen finde es besser, wenn zumindest hier im Beispiel die erste portierte Fassung noch erkennbare Parallelen zum Ursprungsprogramm hat.


    Ich werde dafür an anderer Stelle erst mal einige Vereinfachungen vornehmen: es läuft vorerst im Textmodus, die Spielfiguren werden durch unmodifizierte Ascii-Zeichen repräsentiert und Farbe ist monochrom. Das verbessert die Lesbarkeit des Quelltextes und erleichtert das Umstrukturieren. Nach der Umstrukturierung kann es wieder auf hübsch getrimmt werden.


  • Ich werde dafür an anderer Stelle erst mal einige Vereinfachungen vornehmen: es läuft vorerst im Textmodus, die Spielfiguren werden durch unmodifizierte Ascii-Zeichen repräsentiert und Farbe ist monochrom.

    Ok, vorerst. :prof:


    Aber daran denken. Es ist nur da Frutty Man drin, wo sich auch die Antennen vom Frutty bewegen und die Augen vom Monster blinken. :bgdev

  • Deshalb sind also die vielen Blinke-Inks da drin... hab mich schon gewundert ;)


    Und bis die Antennen sich bewegen und die Augen blinken nennen wir es dann Veggie Man. Die sehen auch oft recht farblos aus :bgdev


    Nachtrag: Mann gibt es viele Fallstricke. Locate gibt's zwar in beiden Basicdialekten, gilt aber bei Commodore nur für den Grafikcursor. Window hat zwar die gleiche Bedeutung, aber die Reihenfolge der Parameter ist anders und bei den Cursorpositionen beginnt CBM beim Zählen mit 0 und CPC mit 1. :cursing:

  • Jein... da gibt es paar Haken: einmal eine andere Basis beim Zählen, so dass es richtig heißen müsste: CHAR 1, x-1, y-1, "text"


    Und dann ist p nicht die Farbe, sondern der Paletteneintrag. Die Farbe für p wurde vorher mit INK gesetzt. Oobdoo nutzt das z.B., um das Level "unsichtbar" zu zeichnen (alle INKs schwarz) und erst danach sichtbar zu machen (alle INKs bekommen wieder ihre Farbe) (so zumindest meine Interpretation - Bugfixing im CPC-Emulator ist nicht meine Stärke)

  • eine andere Basis bei Zählen, so dass es richtig heißen müsste: CHAR 1, x-1, y-1, "text"

    Das stellt man natürlich komplett auf nullbasierte Offsets um. Zur Laufzeit umrechnen ist leicht suboptimal. ;)

    Und dann ist p nicht die Farbe, sondern der Paletteneintrag.

    Klar, aber Palettenregister in der Form hat der VIC nun mal nicht. Braucht man hier auch nicht - den Spieler und das Monster kann man per (ggfs. sogar Overlay-)Sprites erzeugen, für den Levelhintergrund reicht das normale Color-RAM völlig aus. Man könnte sogar ECM benutzen.
    Unsichtbar-und-sichtbar-machen ginge am einfachsten mit FAST und SLOW.

  • Ja klar, mir ging's um die korrekte Umsetzung des LOCATE-Befehls. Und wenn da LOCATE x,y steht, dann ist CHAR,x,y,... um eine Zeile und eine Spalte versetzt. Und wenn man sich die Listings so anschaut, muss man mächtig viel ändern. So viele hardcodierte Zahlen...


    Das Palettenregister hat beim CPC noch ne weitere Funktion - werden per INK zwei Farben zugewiesen, werden mit den beiden Farben ein Blinkeffekt erzeugt.


    FAST und SLOW hatte ich schon dafür schon ins Auge gefasst... nebenbei ist damit auch der Effekt von DI und SI mit abgefrühstückt :D

  • Darf man seinen Senf hier dazugeben? Habe mir den Spass mal gemacht und habe Frutty Man für den Plus/4 in BASIC 3.5 (passt ja auch zu 7.0) portiert. Ist aber noch nicht komplett fertig, da ich derzeit eine Fehlermeldung erhalte.


    Out of Memory Error in 560


    Wahrscheinlich liegts an den vielen GOSUB Sprüngen. Zeichensatz ist noch nicht erstellt und die CHR$ müssen noch verändert werden. SOUND Befehle hab ich mal auskommentiert (REM).


  • Darf man seinen Senf hier dazugeben? Habe mir den Spass mal gemacht und habe Frutty Man für den Plus/4 in BASIC 3.5 (passt ja auch zu 7.0) portiert. Ist aber noch nicht komplett fertig, da ich derzeit eine Fehlermeldung erhalte.


    Out of Memory Error in 560


    Wahrscheinlich liegts an den vielen GOSUB Sprüngen. Zeichensatz ist noch nicht erstellt und die CHR$ müssen noch verändert werden. SOUND Befehle hab ich mal auskommentiert (REM).

    Dürfte daran liegen, das ich im Original Frutty Man mit GOSUB in Unterprogramme reinspringe und mit GOTO wieder raus, was auf Dauer nicht funktionieren kann. Hatte MacB festgestellt. Leider kann ich diesen Teil vom Thread nicht wiederfinden. Ist der verloren gegangen beim Thread aufsplitten? ?(

  • Dürfte daran liegen, das ich im Original Frutty Man mit GOSUB in Unterprogramme reinspringe und mit GOTO wieder raus, was auf Dauer nicht funktionieren kann. Hatte MacB festgestellt. Leider kann ich diesen Teil vom Thread nicht wiederfinden.

    Hier

  • Code
    1. 450 do:j=joy(1):gosub 520
    2. 460 if j=0 then goto 450

    Mit dem GOTO 450 wird zum DO gesprungen und somit werden ständig neue Schleifen geöffnet => das ist quasi eine weitere Instanz des mit-GOTO-in-die-falsche-Schachteltiefe-springen-Fehlers.
    In diesem speziellen Fall dürfte es reichen, das DO zu Zeile 449 zu verschieben, aber grundsätzlich geht es halt nicht ohne Aufräumen/Entspaghettifizierung ab.


    EDIT: Bevor das jetzt falsch rüberkommt: Grundsätzlich ist DO/LOOP für solche Aufräumaktionen natürlich genau richtig. Punktweise Optimierungen beseitigen aber nicht die im Original enthaltenen Strukturfehler - daher habe ich bei "meiner Version" erst einmal versucht, das Ganze übersichtlicher zu machen.

  • Darf man seinen Senf hier dazugeben? Habe mir den Spass mal gemacht und habe Frutty Man für den Plus/4 in BASIC 3.5 (passt ja auch zu 7.0) portiert. Ist aber noch nicht komplett fertig, da ich derzeit eine Fehlermeldung erhalte.
    ...

    Auch die meisten char-Befehle haben noch die falschen Koordinaten (Versatz um 1) - siehe oben. Das bitte noch korrigieren :D Wäre auch prima, wenn Du schreibst, welche Sachen Du alles geändert hast (Abfrage Feuerknopf z. B.), damit andere es später beim Konvertieren einfacher haben. Soll ja ein Lernthread werden :)


    @Mac: was hältst Du davon, wenn nach der Simplifizierung die Neustrukturierung begonnen wird?


    Nachtrag: ich sehe gerade, die Versatzkorrektur betrifft nicht nur den char-Befehl, sondern auch das Array mit der Levelinfo - potenzieller Stolperstein.

  • Puh, da hab ich einiges geändert und angepasst. Ich habe hier erstmal eine spielbare Version, welche aber noch Fehler aufweist. Zeichensatz hab ich an die Gegenheiten des Commodore-Computers angepasst (8x8 Pixel) und leicht verändert. Farben müssen noch verändert werden.


    Beim Einsameln der Frucht crasht das Spiel. Ich seh mir das morgen aber mal an. Der Computerfuzzi ist komischerweise noch bei 0,0 Koordinate, wieso weiss ich leider nocht nicht.
    Wie gesagt, sind noch Fehler drin, aber es wird langsam. Für den C128er müssten paar DATAs und 2 POKEs angepasst werden, damit auch dort der Zeichensatz korrekt kopiert und gesetzt wird.


    Ich hoffe, ich kann den Changelog kurz hier wiedergeben:

    • DO-LOOP Schleife im Hauptprogramm genommen, da schneller
    • JOY Werte an Plus/4 angepasst (7 = links, 1 = hoch, 3 = rechts und 5 = runter, sowie Feuerknopf mit 128)
    • SOUND vorerst komplett enfernt
    • doppeltes Level in Zeile 440 entfernt
    • CPC Befehle ala PEN, INK usw. entfernt und durch COLOR ersetzt
    • CPC Befehl LOCATE durch CHAR ersetzt.
    • Spieler- und Computerroutine überarbeitet und von GOSUBS usw. befreit (Ausnahme die Einnahme einer Frucht)
    • Bewegungsvariablen für Spieler ala XM und YM und für den Computer GXM und GYM gesetzt
    • die gesetzten CHR$ Werte (Bildschirmcodes für Zeichen usw.) habe an den Zeichensatz angepasst
    • Spielerinfoanzeige (SCORE usw.) habe ich mal temporär rechts neben des Spielfeld gelegt

    Bitte, bitte, verzeiht mir, wenn es noch wahnsinnig viel zu verbessern gibt. Mein letzte (richtiges) BASIC Coding war 1997.



  • Da ist ein gaaaanz fieser Fehler drin - Du hast die Variablennamen nicht gekürzt (CBM Basic achtet bei Variablennamen nur auf die ersten beiden Zeichen). Alle Variablen, die drei Buchstaben lang sind, müssen auf zwei Buchstaben Länge gekürzt werden - im dritten Beitrag ist die Liste der Variablen, da kannst Du die dreibuchstabigen raussuchen und passende zweibuchstabige ableiten. Dürfte manche Kuriosität im Programmverhalten beseitigen.


    Ansonsten - sieht schon sehr schön aus :thumbup: