Posts by TheRealWanderer

    Super, Danke. Ich hab mal ein epub draus gemacht, hoffe ich habe die Metadaten richtig hinbekommen - Autor "Player One", Titel "64", Untertitel "Neue Welt"?

    Der Titel ist „Player One 64 - Neue Welt“. (Hommage an den Autor)


    Der Autor des ursprünglichen Werks ist Player One, aber ich kann ja nicht unter seinem pseudonym die Fortsetzung veröffentlichen.


    Autor am besten leer lassen.

    Oder wird es auch eine deutsche Version geben?

    Ich habe tatsächlich darüber nachgedacht. Aber der Aufwand ist zu groß. Es ist ja nicht mit dem einfachen Übersetzen getan.
    Bei den Eingaben durch den Spieler ist die Satzstellung in den meisten Fällen ganz anders. Das würde ein immenser Aufwand werden.
    Das kann - wenn wir das Spiel fertig haben - gern jemand anderes übernehmen ;)


    Da fällt mir spontan Maniac Mansion mit Michael ein. Es nutzt die gleichen Farben, und auch da mußte man natürlich Kompromisse machen, aber möglich ist es dort offensichtlich, einen Farbigen darzustellen.

    Wenn man will, bekommt man das mit entsprechendem Aufwand hin, das ist klar. Aber wir wollten jetzt erstmal das Spiel vorantreiben. Es sind von Courage schon einige Aufwendige Routinen enthalten, z.B. um die Sprite-Sprite/Sprite-Char Prioritäten korrekt zu setzen, damit Larry auch hinter und vor etwas lang gehen kann.

    Derzeit müssen wir aber schon wegen dem RAM aufpassen. Es wird teilweise schon echt eng, gerade bei Locations, von denen man es nicht erwartet...

    Und wir wollen uns nicht in zu viele "Kleinigkeiten" verstricken, sonst zieht sich die Entwicklung in die Länge.

    Wie Courage schon schrieb:


    Derzeit sind die Änderungen aus technischer Sicht notwendig gewesen.
    Und der vorhandene Wortschatz wird halt um das ein oder andere Wort, welches heute so nicht mehr verwendet wird, geändert. Wir haben aber auch schon ein paar Worte hinzugefügt, sodass die Anzahl der Worte sich schlussendlich nicht großartig verändern wird.

    Kleinere Rätseländerungen sind auch bereits drin. Auch dabei haben wir darauf geachtet, dass die Texte dazu passend zum Spiel sind, sodass jemand, der Larry nicht kennt es wahrscheinlich gar nicht bemerken würde, das etwas Neues dazu gekommen ist. Und für die, die Larry kennen, fühlt es sich (hoffentlich) passend an…

    Alles in Allem behalten wir aber die Atmosphäre vom Original bei.

    Als alter Larry Fan werde da schon drauf achten 😉

    Nachdem ich nun noch "etwas" an meinem ByteCode-Interpreter gearbeitet habe, möchte ich dazu ein paar Details erzählen.


    Vorab: Ich bin kein guter Coder, aber dass ich sowas überhaupt hinbekommen habe, ist schon ein echter Erfolg für mich. Die Möglichkeiten sind inzwischen so umfangreich, dass meine Dokumentation dafür derzeit 12 A4 Seiten in Anspruch nimmt. Ohne diese Dokumentation steige ich schon selbst nicht mehr durch :D

    Abgesehen davon würde ich ihn mit dem dadurch erworbenen Wissen nun ganz anders Programmieren. So wie er derzeit ist, ist er in bester Spaghetti-Code Struktur erstellt und leider nicht auf Speicherplatzverbrauch (was den eigentlichen ByteCode angeht) optimiert. Das lässt sich nun im Nachgang (für das bestehende Projekt) nicht mehr so ohne weiteres ändern, da der ByteCode selbst inzwischen so umfangreich ist (bestimmt insgesamt so 5-10kb händisch erstellt), dass wohl etliche Stunden draufgehen würden, den wieder anzupassen. Aber vielleicht dann für das nächste Projekt...


    Aber zurück zum ByteCode:

    Wofür ist der ByteCode Interpreter:

    Damit werden Eingaben, die ein Spieler in einem Spiel getätigt hat ausgewertet und entsprechende Aktionen eingeleitet.

    Vorher wurden die Eingaben aber bereits in Token umgewandelt.

    Die Aktionen können entweder bestimmte Textausgaben sein oder es werden Trigger gesetzt, die irgendwelche Veränderungen im Spielablauf bewirken.


    Es gibt "normalen" ByteCode, BlockByteCode, MultiByteCode und KontextByteCode. Wobei die verschiedenen ByteCodearten beliebig miteinander kombiniert werden können. Die Begrifflichkeiten habe ich so für mich gewählt, ob die so allgemeingültig wären, weiss ich nicht, aber ist vom Grundsatz auch egal.


    1. Normaler ByteCode:


    !byte 10,$02,$00,$73,$00,$F0,42,1,$F0,%00000000


    Erläuterung:

    10 Länge des ByteCodes

    $02-$F0 Eingaben des Spielers in Token sowie Endkennung.

    42,1,$F0 Textausgaben (Text 42 aus aktuellem Raum) und Endkennung.

    %00000000 BinärFlag, damit werden weitere Aktionen gesteuert, z.B. ob Voraussetzungen oder Inventargegenstände notwendig sind, ob man in der Nähe von etwas sein muss, ob Textausgaben unterdrückt werden sollen und Trigger gesetzt werden sollen.
    Wenn das entsprechende Bit gesetzt ist, werden weitere Bytes angehängt und ausgewertet.



    2. BlockByteCode:


    !byte $BC
    !byte 9,$02,$00,$A7,$00,$99,$99,$F0
    !byte 8,$02,$00,$00,$00,$A7,$00,$F0

    !byte 10,$02,$00,$00,$00,$A7,$00,$99,$99,$F0

    !byte $BC
    !byte 10
    !byte 62,1,$F0,%00001000,$FF,$FF,<Nähe_zu_irgendwas,>Nähe_zu_irgendwas


    $BC Kennzeichnet den Beginn und das Ende eines Blocks und enthält die verschiedenen Eingaben des Spielers.

    Dann kommt eine neue Längenkennung und der Rest ist wie bei normalem ByteCode.


    3. MultiByteCode


    !byte 27,$90,$00,$A7,$00,$99,$99,$F0,$E9,%01100111,7,129,0,176,0,$F0,%00000000
    !byte $E9,%01010101,14,0,129,0,130,0,$F0,%00000000


    Der Anfang ist wie normaler ByteCode, dann kommt ein Steuerzeichen ($E9) mit dem noch Bedingungen abgefragt werden können. Das darauf folgende BinärFlag gibt diese Bedingungen vor (hier: keine Negierung, Inventar, Flag für Sprung bei Nichterfüllung, 5 Bits für Nummer des Gegenstandes (hier Gegenstand 7)). Das nächste Byte gibt vor, um wieviel Bytes weiter gesprungen werden soll bei Nichterfüllung. Bei Erfüllung werden 2 Texte (hier Texte 129 und 176 aus den globalen Texten) ausgegeben und der Code bis zum BinärFlag ausgeführt. Ansonsten gehts beim nächsten $E9 weiter.


    4. KontextByteCode


    !byte %10000000+15,%01000000,$FF,$FF,<Nähe_zu_irgendwas,>Nähe_zu_irgendwas
    !byte $02,$00,$09,$00,$F0,4,1,$F0,%00000000


    Wenn im ersten Byte des ByteCodes Bit 7 gesetzt ist, dann wird der ByteCode nur ausgeführt, wenn ein bestimmter Kontext gesetzt ist.
    Der Kontext ist hier %01000000:

    01 für Spieler muss in der Nähe zu etwas bestimmten sein.

    Die weiteren Bits würden ausgewertet, wenn entweder ein Gegenstand oder eine andere Voraussetzung vorliegen müssen.


    5. ByteCodearten Kombiniert


    !byte $BC
    !byte %10000000+8,%00000000,$11,$00,$9E,$00,$F0
    !byte 6,$11,$00,$6D,$00,$F0
    !byte 8,$11,$00,$6D,$00,$9E,$00,$F0
    !byte 8,$93,$00,$30,$00,$22,$00,$F0
    !byte 12,$93,$00,$30,$00,$09,$00,$11,$00,$9E,$00,$F0
    !byte 6,$93,$00,$9E,$00,$F0
    !byte 10,$93,$00,$30,$00,$09,$00,$9E,$00,$F0
    !byte $BC
    !byte 63

    !byte $E9,%11010010,52,0

    !byte $E9,%10001010,23,1, $EA,$FF,$FF,<Nähe_zu_irgendwas,>Nähe_zu_irgendwas,0,1

    !byte $E9,%10100100,6,15,1,$F0,%10000000,12
    !byte $E9,%10100101,6,15,1,$F0,%10000000,12

    !byte $E9,%10100110,6,16,1,$F0,%10000000,9

    !byte $E9,%10001010,23,1

    !byte $E9,%10100111,7,20,1,8,1,$F0,%00000000

    !byte $E9,%00000111,18,1,18,1,$F0,%10000000,5


    Hier werden ByteCode, BlockByteCode, MultiByteCode und KontextByteCode kombiniert verwendet.

    Das ist schon ein ByteCode mit umfangreichen Abfragen und Verzweigungen.


    Wofür sind die ByteCodeArten:


    1. normaler ByteCode ist dafür, wenn aus einer bestimmten Eingabe nur eine bestimmte Ausgabe resultiert.


    2. BlockByteCode ist dafür, dass mehrere Eingaben des Spielers eine bestimmte Ausgabe/Aktion erzeugen. Das spart Speicher, da nicht für jede einzelne Eingabe eine eigene ByteCodeZeile mit den zugehörigen Ausgaben erzeugt werden muss.


    3. MultiByteCode heißt, dass "wenn-dann-sonst" Szenarien abgebildet werden können.


    4. KontextByteCode bedeutet, dass zuerst auf einen Kontext geprüft wird, bevor Auswertung von Eingaben und die daraus resultierenden Ausgaben bearbeitet werden. Z.B. Spieler steht auf einer Leiter, oder hat einen bestimmten Gegenstand oder eine andere Voraussetzung liegt vor.


    Weiteres dazu beim nächsten Mal ;)

    Welcher Hänger war das?

    Ich konnte nur einmal kompilieren, danach musste ich - wenn ich nach einer Änderung neu kompilieren wollte - erst das c64studio beenden und neu starten.

    Oh, das ist aber ärgerlich. Ist mir noch nicht untergekommen. Wäre interessant zu wissen was diesen Hänger verursacht hat.

    Das ist eine gute Frage.
    Das tritt wahrscheinich nur unter bestimmten Voraussetzungen auf.

    Wir arbeiten gleichzeitig, also parallel/online an unserem Projekt, welches auf einem FTP Server liegt. Vielleicht hatte das auch damit zu tun.

    Wir haben aus Speichergründen auch keine 2. (Bit)Map für die Begrenzungs- und Triggerlinien verwendet, sondern Berechnen diese.

    Zudem halten wir auch alle ca 1100 Worte, die der Parser versteht, komplett im Speicher. Allein diese Kosten knapp 10kb.

    Aus Interesse: Nutzt ihr da irgendwelche raffinierten Strukturen? Würde sich da so was wie ein TRIE oder was ähnliches lohnen? Oder ist das "nur" eine Tabelle?

    Im Prinzip eine einfache Tabelle, in der die Wörter mit den zugehörigen Tokens abgelegt sind.

    Diese Tabelle ist entsprechend der Anfangsbuchstaben der jeweiligen Wörter unterteilt, sodass bei der Suche eines eingebenen Wortes nicht die gesamte Tabelle durchsucht werden muss, sondern bei dem entsprechenden Buchstaben begonnen wird.

    Courage und ich haben uns bewusst dafür entschieden, Bitmap ohne Vektorgrafik zu verwenden. Bitmap einfach deswegen, weil damit die Grafik fast 1:1 - natürlich mit diversen Nachbearbeitungen - übernommen werden kann. Wobei Sprites und kleinere Sachen nachgepixelt werden müssen. Hintergrundbilder können konvertiert werden.


    Ich halte eine echte AGI Engine zwar für möglich, aber aufgrund des Overheads zum einen speichermäßig und zum anderen im Bezug auf die Ausführungsgeschwindigkeit für zu heftig für den c64, zumindest in dem Umfang, wie es im Original ist.

    Man würde bei einer Vektorgrafik den Bildaufbau beobachten können, weil der einfach zu langsam läuft. Ein Bild ist dann schneller geladen, als per Vektor aufgebaut. Und wenn man es erst in einen Buffer schreibt, kostet das nochmal 10kb...

    Wir wollten lieber ein Bild mit allem drum und dran komplett im Speicher halten, auch, damit man vom Speichermedium unabhängig ist. D.h. während der Entwicklung verwenden wir das WiC64. Später kann es aber ohne großen Aufwand auf andere Speichermedien angepasst werden (Modul, Diskette etc.). Wobei wir am Überlegen waren, bei einer Diskettenversion einen Trackloader oder ähnliches zu verwenden.


    Wir haben aus Speichergründen auch keine 2. (Bit)Map für die Begrenzungs- und Triggerlinien verwendet, sondern Berechnen diese.

    Zudem halten wir auch alle ca 1100 Worte, die der Parser versteht, komplett im Speicher. Allein diese Kosten knapp 10kb.

    Dazu 10kb Bitmap, später Musik ca. 4-5Kb, Sprites (viele), Softsprites, Chars usw.

    Viele kb Texte (allein die globalen Texte rd. 5,5kb), die zur Verfügung stehen müssen (einmal die, die nur in dem Bild gehen und andererseits die, die überall funktionieren müssen).

    Daneben dann noch ein Bytecode-Interpreter, um Eingaben auszuwerten. Der Bytecode hat, wenn er vollständig ist auch 2-3kb (ggf.mehr).

    Und dann muss der ganze Code für den restlichen Kram auch noch irgendwo hin.


    Wen dann noch ein echte AGI Engine hinzukäme, wäre das schon sehr eng (bis zu fast nicht 1:1 machbar).


    Daher ist AGI kein Thema für uns. Wir halten eine native Umsetzung in Assembler auf dem c64 für den besten Weg. Außerdem sind die meisten Routinen ja schon fertig.


    BTW: Auf Diskussionen zu Interpretern, Engines oder Vektorzeichungen (so beeindruckend sie auch sind!) gehen wir hier nicht weiter im Detail ein, weil das nicht in unserem Fokus ist.

    Diskussionen dazu bitte in extra Threads :)


    Für Vorschläge und Ideen zum Game selbst sind wir natürlich aber offen.

    Ob dann alles umgesetzt wird ist dann aber eine andere Sache ;)

    Im Wiki steht was dazu:


    Beim C64 kann der Dateiname weitestgehend aus den PETSCII(CHR$)-Zeichen 32-122 bestehen (Leerzeichen, Sonderzeichen, Ziffern und Buchstaben sowie den mittels Taste SHIFT über die Buchstaben-Tasten erzeugbaren Sonderzeichen bzw. Großbuchstaben, entsprechend dem gerade aktiven Zeichensatz), außer den Jokerzeichen "*" und "?", sowie den Zeichen ":", "@", ",", die eine spezielle Bedeutung beim jeweiligen Gerät (etwa als Trennzeichen für Floppy-Befehle, Laufwerksbezeichnung, usw.) haben, sowie des PETSCII-Zeichens 96. Leerzeichen ohne nachfolgende andere erlaubte Zeichen werden abgeschnitten.

    Ich freue mich schon riesig auf MI@c64 :)


    Die Logik ist das eine, die Grafik ist das andere. Und das "andere" kann es in sich haben. Courage, Nordischsound und ich (also RetroBytes) sind auch gerade an einem Port von etwas und da müssten wir hier und da schon echt überlegen, wie man was am besten macht...


    Ich drücke den Jungs auf alle Fälle die Daumen!