Selbstgeschriebene Spiele für die Commodore PET/CBM-Reihe

  • Hallo Jungs,


    ich bastle gerade an einem Basic-Spiel für den 8032-SK.

    Was mich da immer so unglaublich nervt: Baut man in eine Schleife mehr als 2-3 Print/Bildschirmpoke-Befehle ein, wird die Mühle unerträglich langsam.

    Basic (gepaart mit meiner Stümperhaftigkeit) eben.

    Ich will diesen Thread nutzen, um von euch zu erfahren, was ihr schon so an Spielen für die Commodore PET/CBM-Reihe programmiert habt.

    Da es im Forum einige Threads gibt, könnte man ja gerne "Links" aus diesen Threads hier einfügen, um eine Art Sammler zu erstellen.


    Von "meinem" Spiel gibt es noch nix Sehenswertes, ausser diesen Screenshots- es wird eine Art Snake für Arme. Den Namen ändere ich noch, denn mit Snake hat es nix mehr zu tun. :D

    Für Arme deshalb, weil ich die Schlange nicht wieder kleiner werden lasse. Sie bleibt von der Startposition zur aktuellen Position also eine lange "Linie".

    Warum? Na weil Basic einfach zu langsam ist, die Schlange auf- und nach einiger Zeit hinten wieder abzubauen. (Zumindest bekomme ich das nicht performant genug hin- kann auch daran liegen)

    Dafür ist das Spielprinzip ein wenig abgewandelt, damit es noch halbwegs Sinn macht.

    Man muss Futterbälle einsammeln, darf dabei nicht an die Außenwände und an die Objekte im Level stoßen.

    Die Futterbälle sind zufällig angeordnet, und man kann durch seine eigene Schlange durch"graben". Das kostet allerdings Energiepunkte, deshalb muss man hier überlegt vorgehen.

    Es wird mehrere Levels geben und der Schwierigkeitsgrad erhöht sich einfach durch die Menge an Objekten, gegen die man nicht stoßen darf.

    Eigentlich echt fad- aber hey, es gibt Soundausgabe! :D








    Wenns fertig ist, kommt es natürlich hier zum Download, Jungs! 8o


    Egal- was mit Assembler und AHNUNG wirklich geht, zeigt uns in der heutigen Ausgabe der 8-Bit-Guy.

    Er ist zwar ein dezent paranoider Waffennarr (ja, leider), und seit der letzten Folge ein IBM-Vernichter- aber was Programmieren angeht, läuft der Laden bei ihm:

    https://www.youtube.com/watch?v=uyf7tiSO9vo


    Also dann: Legt los- dann stellen wir uns alle eine CBM/PET-Spielesammlung auf, die ihresgleichen sucht! :sunny:


    Viele Grüsse,

    Matthias

  • Für Arme deshalb, weil ich die Schlange nicht wieder kleiner werden lasse. Sie bleibt von der Startposition zur aktuellen Position also eine lange "Linie".

    Warum? Na weil Basic einfach zu langsam ist, die Schlange auf- und nach einiger Zeit hinten wieder abzubauen. (Zumindest bekomme ich das nicht performant genug hin- kann auch daran liegen)

    Eine performante Schlange kann man einfach mit einem Ringpuffer erzeugen. In dem Ringpuffer speicherst du alle Positionen der Schlange. Eine Indexvariable markiert die nächste Position im Ringpuffer. Immer wenn du die Schlange weiterbewegst, erhöhst du die Index-Variable um 1, liest die Bildschirmposition aus dem Ringpuffer, löschst die Schlange an dieser Position und schreibst die neue Position der Schlange an diese Position in den Ringpuffer (und auf den Bildschirm). Wenn die Indexvariable das Ende des Arrays erreicht hat, setzt du sie auf 0 zurück (Ringpuffer eben).


    Der Vorteil dieser Methode ist, dass eine längere Schlange nicht langsamer wird. Du musst nur das Array vergrössern.

    • i-Telex 7822222 dege d

    • technikum29 in Kelkheim bei Frankfurt

    • Marburger Stammtisch

    Douglas Adams: "Everything, that is invented and exists at the time of your birth, is natural. Everything that is invented until you´re 35 is interesting, exciting and you can possibly make a career in it. Everything that is invented after you´re 35 is against the law of nature. Apply this list to movies, rock music, word processors and mobile phones to work out how old you are."

  • Was mich da immer so unglaublich nervt: Baut man in eine Schleife mehr als 2-3 Print/Bildschirmpoke-Befehle ein, wird die Mühle unerträglich langsam.

    Basic (gepaart mit meiner Stümperhaftigkeit) eben.

    Hast du schon mal PETSPEED probiert?

    Der Compiler ist sehr gut, in meiner Jugendzeit habe ich intensiv damit gearbeitet.




    Ich will diesen Thread nutzen, um von euch zu erfahren, was ihr schon so an Spielen für die Commodore PET/CBM-Reihe programmiert habt.

    Als Kind war ich sehr angetan von dem Arcade Hit "Donkey Kong Junior".

    Deswegen habe ich einst den ersten Level von DKJ in Assembler implementiert.


    https://www.forum64.de/index.p…spiel-donkey-kong-junior/








    Original Arcade:


  • Für Arme deshalb, weil ich die Schlange nicht wieder kleiner werden lasse. Sie bleibt von der Startposition zur aktuellen Position also eine lange "Linie".

    Warum? Na weil Basic einfach zu langsam ist, die Schlange auf- und nach einiger Zeit hinten wieder abzubauen. (Zumindest bekomme ich das nicht performant genug hin- kann auch daran liegen)

    Eine performante Schlange kann man einfach mit einem Ringpuffer erzeugen. In dem Ringpuffer speicherst du alle Positionen der Schlange. Eine Indexvariable markiert die nächste Position im Ringpuffer. Immer wenn du die Schlange weiterbewegst, erhöhst du die Index-Variable um 1, liest die Bildschirmposition aus dem Ringpuffer, löschst die Schlange an dieser Position und schreibst die neue Position der Schlange an diese Position in den Ringpuffer (und auf den Bildschirm). Wenn die Indexvariable das Ende des Arrays erreicht hat, setzt du sie auf 0 zurück (Ringpuffer eben).


    Der Vorteil dieser Methode ist, dass eine längere Schlange nicht langsamer wird. Du musst nur das Array vergrössern.

    Hallo Detlef,


    danke für die Info, das kucke ich mir mal an- auch, wenn ich noch nicht ganz weiß, wie ich das Programm aufbauen soll.

    Aber: Ich will's lernen! Nur so kommt man da ja weiter.


    Hallo! :)


    PETSPEED kenne ich noch nicht, da les ich mich mal ein- danke dafür! :)

    Wäre schon genial, allerdings läuft das nicht mit einem petSD+, oder?


    Dein Spiel ist der Hammer- und auch noch in Assembler geschrieben, WIE GENIAL!


    DANKESCHÖN! Interessant, dass sich die Idee im entfernten "deckt". Falls ich endlich mal Zeit finden sollte, geh ich die Analyse des Codes an.

    *edit* Puh, mein "Spiel" ist um den Faktor 10 kleiner und weit weniger animiert. Da steht noch VIEL Arbeit an. :)


    Viele Grüsse,

    Matthias

    Einmal editiert, zuletzt von CBM_Ba ()

  • Wichitg ist halt immer den langsamen Teil zu reduzieren !!


    Das ist in Deinem Fall der Bildschirmaufbau. Und den bekommt man massiv beschleunigt, wenn man eben nur des Ende der Schlange löscht und den neuen Wert (Kopf) zeichnet. Dann muß man alles andere gar nicht malen.

    Und dafür eignet sich dieser Ringpuffer gut. Aber den muß man erstmal kapiert haben - ist aber nicht schwer.


    Was auch noch so eine Sache ist, die sich beschleunigen läßt, ist die Abfrage des Anstoßens an Objekt ( Collision Check ). Das ist bei einem zu fressenden Objekt noch trivial. Aber wenn man mehrere "Freßpunkte" anlegen will, müßte man ja z.B. den Schlangekopf gegen alle diese testen, oder auch gegen Hindernisse, wie in dem einen Bild.

    Den Aufwand kann man durch geschicktes Anlegen der Daten extrem reduzieren, z.B. indem man das Spielfeld in Felder unterteilt und dann nur das Feld durchtestet, in dem sich der Schlangenkopf gerade befindet. Oder z.B. spaltenweise die Objekte einsortier, so daß man nur eine einzelne Spalte gezielt abfragen muß. Ungünstig dagegen ist etwa eine Struktur, wo man Punkt in einem (x,y) Muster unsortiert reinschreibt. Etwa als Array mit x%() und y%(). Da hat man keine vorgegebene Info drin und muß dann alles gegentesten. Alternativ könnte man sowas regelmäßig sortieren, aber das macht es dann eher noch langsamer.


    Für den Randbereich - also die Umrandung mit '*' - kann man sich auch als totaler Non-Assembler Benutzer mal ranwagen, das in Assembler zu probieren. Das bekommt man nämlich ganz gut hin, wenn man sich da bißchen eingelesen hat, und dann ist es ungefähr einen Faktor 100 schneller als wenn man das mit BASIC malt. Aufruf mit SYS oder USR sollte vermutlich auch beim PET schon gehen.

    -- 1982 gab es keinen Raspberry Pi , aber Pi und Raspberries

  • Danke euch!


    Die Kollisionsabfrage, sowie das Zeichnen der Schlange -> alles bereits mit Poke 32768+x,y realisiert.

    Aktuell ist es ja nicht wirklich sooo langsam. Aber eben noch ohne das Löschen des Endes der Schlange. Mal sehen, wann ich Zeit finde, daran bisschen weiterzuwursteln. Spass macht es auf alle Fälle jetzt schon. (Fragt mich nicht, weshalb... :D )


    Viele Grüsse,
    Matthias

  • RINGPUFFER?!? RIIIIIINGGGPUFFFEEER!! >:(::vodoo::



    Jungs, dies ist das Ergebnis von 2,5h „nachdenken“.

    Ich sag ja: Programmieren ist nicht unbedingt etwas, was zu meinen herausragenden Fähigkeiten gehört.

    Ich muss dazu sagen, dass ich keinerlei Hilfe aus dem Netz beansprucht habe, weil ich das so lösen wollte.

    Prinzipiell funktioniert das Programm und zeichnet eine Schlange von 10 Zeichen Länge. ABER: Alle 90 oder 100 Positionen bleibt eine aus 10 Zeichen bestehende Schlange auf dem Bildschirm stehen. Mir ist schon klar, weshalb: Weil der Zähler den Ringpuffer wieder auf 10 setzt, wenn er auf 100 ist...

    Ich bekomme es aber nicht hin, das der Zähler so läuft, dass er stur immer die letzten 10 Zeichen der Schlange mit Leerzeichen überschreibt! :(

    Das sind typische Hirnblockaden von mir- macht mich dann so Irre, dass ich irgendwann aufgeben muss, bevor ich durchdrehe.


    Dabei ist die Lösung sicherlich simpel... wie so oft. :(

  • Na wer nichts macht, kann nichts falsch machen. Ich finde es super, dass du dich damit beschäftigst - man kann nur lernen ! Jeder, der programmiert kennt die Stunden, wo man vorm Rechner sitzt, auf den Bildschirm starrt, mehrere Kaffee zu sich nimmt, und irgendwann dreht man 2 Zahlen rum und das Programm läuft... :)

    Wenn ich das so sehe, denke ich, ich muß unbedingt einen meiner CBM Rechner mal wieder aufbauen. Da hab ich schon länger nichts mehr gemacht. Grüne Schrift auf schwarzem Hintergrund ist einfach beautiful !!


    Gruß Jan

  • Da gebe ich dir recht, Jan! :)


    Allerdings hat detlef oben ja beschrieben, wie es klappt- aber ich verstehe nicht, wie ich das umsetzen muss. :(

    Ein Wahnsinn, Andere lachen über so eine Lappalie- für mich ist sie annähernd unüberwindbar. War schon immer so, auch bei Mathe/Geometrie. Ich denk da wohl zu kompliziert, und dann blockiert irgendwas.

    Mei... ich versuche mich jetzt einfach zu entspannen. :D


    Und den CBM- jaaaapp, den solltest du aufbauen! ;)


  • Wie geil ! Ich hatte genau das gleiche Telefon in der gleichen Farbe auf meiner Floppy 8050 stehen, allerdings nicht angeschlossen, nur als Deko..

    Ich hab allerdings keinen 4032, sondern einen 8032 und einen 3008 mit 32kb Board.


    ich vertippe mich leider bei der grafischen Tastatur immer. Wenn ich zB Anführungszeichen setzen will, drücke ich instinktiv SHIFT und 2 (die ja da nicht ist). Dann kommt natürlich das Petscii-Grafikzeichen. Außerdem suche ich die Cursor-Tasten jedes Mal unten rechts auf der "Haupttastatur", weil ich es vom Cevi so gewöhnt bin... Ah ja, un bei der INS/DEL Taste verhau ich mich auch immer... :wand:



    Gruß Jan

    Einmal editiert, zuletzt von Jan1980 ()

  • Ja - Ringpuffer eben. Hab' ja schonmal oben geschrieben, daß das kein total einfaches Konzept ist. Es ist aber gar nicht so völlig daneben aufgebaut. Hat ein paar "Quirks" und ein paar davon machen dann das komische Beeenden nach 90 Positionen.


    Ich mach mal nur so ein paar Bemerkungen, daß Du evtl. damit nochmal neu nachdenken kannst, das wird also keine Komplettlösung.


    Zum einen ist die Idee am Ringpuffer tatsächlich die, daß man wirklich alle Werte darin vorhält. Wenn man also eine Schange mit 10 Elementen haben will, dann reicht auch ein Ringpuffer von "10"er Größe.


    Das Zweite, was immer gut ist, ist, daß man Werte vorbelegt. Du startest hier z.B. mit einem relativ undefinierten X und Y. Das kann dann auch mal gut danebengehen, bis zum "Freeze" der Maschine, weil dann ja irgendwohin gepoket wird. Ebenso ist auch ein Test auf die obere Grenz ganz gut.


    Das Hauptproblem ist dann aber am Wechsel beim Erreichen des oberen Endes des Puffers. Auch wenn der bei Dir hier 100 Elemente hat und davon nur 90 benutzt werden ( eigentlich ja sicher 101 und 91, da die RP(0) ja sicher auch eine gültige Position für Daten wäre ), ist ein wesentlich problematisches Ding, daß Du bei AP=AP+1 ( Zeile 180 ) einen Überlauf abfängst und bei AP=10 weitermachst, wenn die 100 erreicht worden ist. In Zeile 420 löscht Du dann aber bei RP(AP-10) den Punkt - und das ist natürlich nicht das Ende der aktuellen Schlange - denn die ist ja noch bei RP(100-10).

    Um das halbwegs anschaulich zu umschiffen, kann man sich am Besten einen zweiten Pointer AP einrichten - etwa als 'APBACK'. Damit läßt sich das dann schon in dieser RP(100) Struktur zum Laufen bekommen, indem man das AP und das APBACK unabhängig voneinander erhöht und beim 100er auf 0 setzt ( oder auch auf 10 ).


    Das ist dann aber noch kein Ringpuffer ! Zumindest nicht so wie es gemeint war.

    Aber der wesentliche Unterschied ist dann nur noch, daß AP und APBACK ( also Anfang und Ende der Schlange ) dort nur um genau einen Wert auseinanderliegen. Es ist quasi ein Oroborus, wo das Ende immer von dem Kopf innerhalb der Datenstruktur "verfolgt" wird. Und da das so ist kann man dort dann auch in jeder Runde einfach ein APBACK=AP machen und AP neu berechnen, womit automatisch der Überlauf am Ende berücksichtigt ist.



    Ansonsten: Denk nochmal über X und Y nach. Ich finde das mit den beiden Variablen zwar schon sehr anschaulich, aber dann sollte man evtl. Y für die Vertikale benutzen. Eigentlich reicht aber auch eine Variable und man schreibt dann X=X+1 für seitliche Bewegung und X=X+40 für die Vertikale.



    edit-add-on : Was evtl. noch eine andere Überlegung sein könnte, die Du mal machen könntest - ich weiß ja nun nicht, wie Du genau über sowas nachdenkst - wäre, Dir mal zu überlegen, was genau jeweils in den Positionen RP(0), RP(1) ... RP(10) drinsteht. Jeweils am Start des Programmes und dann zu dem Zeitpunkt, wenn wieder AP=10 gesetzt worden ist. Und zwar in der ersten Durchlaufrunde im Vergleich zur zweiten und dritten usf.

    -- 1982 gab es keinen Raspberry Pi , aber Pi und Raspberries

    3 Mal editiert, zuletzt von ThoralfAsmussen ()

  • Andere lachen über so eine Lappalie- für mich ist sie annähernd unüberwindbar. War schon immer so, auch bei Mathe/Geometrie. Ich denk da wohl zu kompliziert, und dann blockiert irgendwas.

    Mei... ich versuche mich jetzt einfach zu entspannen.


    Nicht schlimm - das ist nämlich alles einfach eine Übungsfrage. Man darf sich halt nicht unterkriegen lassen und das allermeiste ist bei sowas nicht wirklich schwer. Einfach mal ein Päuschen machen und dann mit neuem Schwung nochmal drüber brüten. Irgendwann kommt dann die Erleuchtung. Und bißchen Rumprobieren schadet manchmal auch nichts.



    Sehr schöne Anlage übrigens !

    -- 1982 gab es keinen Raspberry Pi , aber Pi und Raspberries

  • Hey Jan!


    Telefon Deko: CHECK.

    Vertippen: CHECK. :D -> allerdings da genau umgekehrt, trotz C64. Ich mache oft den (unglaublich fatalen) Fehler, dass ich auf dem 8032-SK versehentlich SHIFT + RUNSTOP drücke. Und was passiert dann?! Er lädt das erste Programm vom petSD+ Laufwerk! Hat mich schon bei manchem Programmierversuch Nerven gekostet, wenn die Arbeit der letzten Stunde einfach überschrieben worden ist.

    Deshalb schalte ich das petSD+ jetzt immer ins Menü, dann ist es nicht betriebsbereit.



    Juhu auch an dich und vielen Dank für die Ausführungen! :)


    Das mit X und Y, sowie die fehlende Begrenzung dieser Werte ist Absicht- es handelt sich wirklich nur erstmal um eine grobe Testversion, um eine fehlerfreie Schlange beliebig einstellbarer Länge zu erzeugen.

    Später erfolgen ohnehin Levelränder mit Kollisionsabfrage, auch fassse ich X+Y schon in den IF-Abfragen zu "P" zusammen, damit die Addition nicht mehr gemacht werden muss. Dies hab ich bei meinem ersten Versuch einer Abwandlung von Snake weiter oben im Thread bereits so umgesetzt. Und jupp- X und Y... seit ich Geometrie zum ersten Mal gehört hab, verwechsle ich die Variablen für horizontal und vertikal... es geht mir also seit >30 Jahren nicht in den Kopf!!! Sowas ist wirklich nervig, ich finde auch keine Eselsbrücke, um die Variablen einer Säule des Diagramms zuordnen zu können. :D


    Zum Thema Ringpuffer... ja, irgendwie ist mir das alles zu "logisch". Komisch zu erklären. Ich denke da dann oft viel zu kompliziert und über x-Ecken... :(

    War schon immer ein großes Thema- bereits in der Schulzeit. Gib mir materielle Dinge, und ich baue was daraus. Versuche mir, die mathematische Theorie dahinter auf einem Papier zu veranschaulichen- und ich bin raus. :( Kann einen in den Wahnsinn treiben, hat aber dennoch für einen Matheabschluss gereicht. :D


    Ich sitze dann also da, und weiß eigentlich, wo das Problem liegt... Anfang und Ende der Schlange müssen 10 Positionen auseinanderliegen. Soweit ist mir das klar. Lediglich das Programmieren dieser "Fähigkeit" fällt mir so schwer. Denn dann stelle ich mir die Frage, wie ich umsetzen soll, dass das Programm erstmal zehn Zeichen schreibt, bevor es anfängt, die darüber hinausgehenden mit Leerzeichen zu überschreiben.

    Deshalb der Spagat mit dem -10, was natürlich dazu führt, dass alle 90 Zeichen 10 Zeichen stehenbleiben, weil im Ringpuffer Unsinn steht... :(

    Ich versuche jetzt einfach mal, zwei rollierende Puffer zu bauen. Einer für Anfang der Schlange, der andere mit 10 Positionen Versatz das Ende. Der Puffer braucht dann auch nur 10 Zeichen zu speichern- auch hier wieder: ich WEISS es ja, kann's aber nicht umsetzen! :(

    Evtl. bekomme ich das ja doch noch gebacken.


    Die Variablen ließ ich mir auch eine zeitlang anzeigen, um zu erkennen, wo es hakt. NUR: Das wusste ich ja vorher bereits... ach, doof zu erklären. :D


    Jedenfalls vielen Dank für deine Erklärung, auch an detlef . Wenn ich am WE Zeit finde, starte ich unvoreingenommen einen zweiten Versuch.


    Viele Grüsse,

    Matthias

  • Hallo Matthias,


    also erstmal finde ich es gut, dass du lesbares Basic programmierst und nicht gleich diese verkrüppelten Schreibweisen verwendest (z.B. Punkt statt 0), die man inzwischen überall findet. Leerzeichen im Programm und nicht jede Zeile bis zum Ende vollgepackt findet man inzwischen leider auch selten. CHR$(147) statt Sonderzeichen sorgt dafür, dass man den Programmcode auch mal in Textform posten und per Copy&Paste einfach in Vice einfügen kann. Deswegen unten auch die Kleinschrift.

    Optimieren kann man später immer noch, wenn man an irgendwelche Speicher- oder Geschwindigkeitsgrenzen stösst. Oder man jagt das Programm einfach durch einen Compiler oder Compactor.



    Ich konnte es mir natürlich nicht verkneifen, das mal selber zu programmieren. So würde das bei mir aussehen. Wie gesagt, unoptimiert aber dafür lesbar.


    Vorsicht. Spoiler! ;)


    • i-Telex 7822222 dege d

    • technikum29 in Kelkheim bei Frankfurt

    • Marburger Stammtisch

    Douglas Adams: "Everything, that is invented and exists at the time of your birth, is natural. Everything that is invented until you´re 35 is interesting, exciting and you can possibly make a career in it. Everything that is invented after you´re 35 is against the law of nature. Apply this list to movies, rock music, word processors and mobile phones to work out how old you are."

    3 Mal editiert, zuletzt von detlef ()

  • Ein Ringbuffer ist eine sehr einfache aber wirksame Konstruktion.


    • ein Buffer mit (n) Elementen -- Array
    • Anzahl Elemente im RB -- Integer Variable
    • Lesezeiger (index in array) -- Integer Variable
    • Schreibzeiger (index in array) -- Integer Variable


    Für einen RB mit 100 Elementen (n = 100) könnte eine Implementierung so aussehen



    Initialisierung:

    • Anzahl Elemente = 0
    • Lesezeiger = 0
    • Schreibzeiger = 0


    Element in RB schreiben
    :

    • WENN <Anzahl Elemente> größer/gleich 100 DANN Abbruch - Buffer voll
    • Buffer[Schreibzeiger] = <neues Element>
    • <Schreibzeiger> inkrementieren
    • <Anzahl Elemente> inkrementieren
    • WENN <Schreibzeiger> größer/gleich 100 DANN <Schreibzeiger> = 0


    Element aus RB lesen
    :

    • WENN <Anzahl Elemente> = 0 DANN Abbruch - Buffer leer
    • <Lese Element> = Buffer[Lesezeiger]
    • <Lesezeiger> inkrementieren
    • <Anzahl Elemente> dekrementieren
    • WENN <Lesezeiger> größer/gleich 100 DANN <Lesezeiger> = 0
  • CBM_Ba


    Habe gerade alte Disketten von meinem Philips P2000M (Z80 mit 2.5MHz) durchgesehen.


    Habe ein BASIC WURM-Programm gefunden. (Wie SNAKE)


    WURM-PHILIPS-P2000M.zip


    Dort dürfte der Ringpuffer auch implementiert sein. Vielleicht kannst Du Dir dort Anregungen holen.


    Hinweis: INKEY$ liest ein Zeichen von Tastatur ein, ohne zu warten.


    Gruß, PAW

  • Ein Ringbuffer ist eine sehr einfache aber wirksame Konstruktion.


    • ein Buffer mit (n) Elementen -- Array
    • Anzahl Elemente im RB -- Integer Variable
    • Lesezeiger (index in array) -- Integer Variable
    • Schreibzeiger (index in array) -- Integer Variable

    Für die Schlange braucht man übrigends keine getrennten Lese- und Schreibzeiger, da der Buffer, bei entsprechender Initialisierung, immer komplett gefüllt ist. Ist also eine vereinfachte Version des Ringbuffers.

    • i-Telex 7822222 dege d

    • technikum29 in Kelkheim bei Frankfurt

    • Marburger Stammtisch

    Douglas Adams: "Everything, that is invented and exists at the time of your birth, is natural. Everything that is invented until you´re 35 is interesting, exciting and you can possibly make a career in it. Everything that is invented after you´re 35 is against the law of nature. Apply this list to movies, rock music, word processors and mobile phones to work out how old you are."

    Einmal editiert, zuletzt von detlef ()

  • ..da bin ich ja mal gespannt, was du da zusammenbastelst - wird das dann beim Treffen schon "testbar" sein?

    ich bin signifikant genug:razz:

  • Für die Schlange braucht man übrigends keine getrennten Lese- und Schreibzeiger, da der Buffer, bei entsprechender Initialisierung, immer komplett gefüllt ist. Ist also eine vereinfachte Version des Ringbuffers.


    Aber es ist wesentlich einfacher zu verstehen - wenn man sich das beim ersten Mal mit zwei solchen Zeigern hinbastelt. Wenn man es dann kapiert hat, kann man das auch noch auf einen reduzieren.



    Habe ein BASIC WURM-Programm gefunden. (Wie SNAKE)


    WURM-PHILIPS-P2000M.zip


    "W O R M Y" ... hab ich ja auch woanders schonmal gehört.


    Ist aber ein übles Basic. Mit allerlei hin-und-her Gespringe und GOSUBs allerorten. So richtig ein Löschen habe ich beim Drüberschauen nicht gesehen. Evtl. wird die Schlange da auch einfach nur länger. Benutzt wird aber auf jeden Fall mal ein Puffer und zwei Pointer - einmal HEADPT, einmal TAILPT.


    Daneben gibt es eine anscheinend unvermeidliche Warteschleife und ein seltsames Zufallszahlenkonstrukt

    180 Y%=RND(1)*10:IF Y%<=0 OR Y%>9 THEN 180


    sowas habe ich wirklich noch nicht gesehen ... und es taucht in Zeile 140 so ähnlich nochmal auf.

    -- 1982 gab es keinen Raspberry Pi , aber Pi und Raspberries

  • "W O R M Y" ... hab ich ja auch woanders schonmal gehört.


    Ist aber ein übles Basic. Mit allerlei hin-und-her Gespringe und GOSUBs allerorten. So richtig ein Löschen habe ich beim Drüberschauen nicht gesehen. Evtl. wird die Schlange da auch einfach nur länger. Benutzt wird aber auf jeden Fall mal ein Puffer und zwei Pointer - einmal HEADPT, einmal TAILPT.

    Ich hab da auch mal kurz reingeschaut und hab's gleich wieder zugemacht. Es gibt Programme, die will man (ich) nicht verstehen. ;)

    Meistens hat man es dann schneller neu geschrieben.

    • i-Telex 7822222 dege d

    • technikum29 in Kelkheim bei Frankfurt

    • Marburger Stammtisch

    Douglas Adams: "Everything, that is invented and exists at the time of your birth, is natural. Everything that is invented until you´re 35 is interesting, exciting and you can possibly make a career in it. Everything that is invented after you´re 35 is against the law of nature. Apply this list to movies, rock music, word processors and mobile phones to work out how old you are."

  • Ein Ringbuffer ist eine sehr einfache aber wirksame Konstruktion. ...


    deleted_03-24 ... Wissensdatenbank ?(!) , evtl. ergänzt um das gespoilerte Programm und den "WORM" von CBM_ba , wenn er 'fertisch' ist ?

    Da wären dann aber noch LiFo, FiFo und Queue zu erwähnen ... :)

  • Für die Schlange braucht man übrigends keine getrennten Lese- und Schreibzeiger, da der Buffer, bei entsprechender Initialisierung, immer komplett gefüllt ist. Ist also eine vereinfachte Version des Ringbuffers.


    Naja, das ist eine Frage der Betrachtungsweise ...

    ... Je nachdem wie man den RB einsetzt beim SNAKE Problem.



    Ich persönlich würde den Ringbuffer lesend UND schreibend benutzen.


    Solange die Schlange sich bewegt, gibt es immer ein Lese- und ein Schreibvorgang.


    Sobald die Schlange wächst gibt es nur einen Schreibvorgang.


    ===========


    Der Clou ist doch, dass die Schlange sich nur am Kopf und Schwanz "bewegt", der Körper bleibt gleich.


    Wenn also die Schlange sich bewegt, ist die neue Position des Kopf ein neues Element im RB (ein Schreibvorgang).


    Wenn der Schwanz nachläuft, ist es ein Löschvorgang der Schwanzposition (also ein Lesevorgang im RB).


    ===========


    Die Bewegung der Schlange wäre also ein:

    • ermitteln der Richtung der Bewegung des Kopf (N, S, O oder W) -- Xdir und Ydir -- (0,-1),(0,1),(1,0),(-1,0)
    • finde neue Position des Kopf (Xneu, Yneu) = (Xalt + Xdir, Yalt + Ydir)
    • Grafik :: Neuen Kopf zeichnen an (Xneu, Yneu)
    • Grafik :: Alten Kopf löschen --> Körper zeichnen an (Xalt, Yalt)
    • Ringbuffer schreiben (Xneu, Yneu)
    • Wenn (Xneu, Yneu) ist FUTTER ---> Fertig (Schlange wächst)
    • Schwanzposition (Xtail, Ytail) aus RB lesen
    • Grafik :: Alten Schwanz löschen an (Xtail, Ytail)
    • Neue Schwanzposition (Xtail, Ytail) aus RB lesen -- NON DESTRUCTIV!!!
    • Grafik :: Neuen Schwanz zeichnen an Position (Xtail, Ytail)
  • Da wären dann aber noch LiFo, FiFo und Queue zu erwähnen ... :)

    Eigentlich ging es ja um ein Snake-Programme. Der Puffer war nur Mittel zum Zweck. ;)

    • i-Telex 7822222 dege d

    • technikum29 in Kelkheim bei Frankfurt

    • Marburger Stammtisch

    Douglas Adams: "Everything, that is invented and exists at the time of your birth, is natural. Everything that is invented until you´re 35 is interesting, exciting and you can possibly make a career in it. Everything that is invented after you´re 35 is against the law of nature. Apply this list to movies, rock music, word processors and mobile phones to work out how old you are."

  • Ich persönlich würde den Ringbuffer lesend UND schreibend benutzen.

    Solange die Schlange sich bewegt, gibt es immer ein Lese- und ein Schreibvorgang.

    Sobald die Schlange wächst gibt es nur einen Schreibvorgang.

    Na, dann bin ich mal auf deine Lösung gespannt und dann legen wir das mal nebeneinander und schauen, was einfacher ist (und schneller). ;)

    Meine Lösung habe ich ja oben schon gespoliert.

    • i-Telex 7822222 dege d

    • technikum29 in Kelkheim bei Frankfurt

    • Marburger Stammtisch

    Douglas Adams: "Everything, that is invented and exists at the time of your birth, is natural. Everything that is invented until you´re 35 is interesting, exciting and you can possibly make a career in it. Everything that is invented after you´re 35 is against the law of nature. Apply this list to movies, rock music, word processors and mobile phones to work out how old you are."

  • Na, dann bin ich mal auf deine Lösung gespannt und dann legen wir das mal nebeneinander und schauen, was einfacher ist (und schneller). ;)

    Meine Lösung habe ich ja oben schon gespoliert.


    Die Bewegung der Schlange wäre also ein:

    • ermitteln der Richtung der Bewegung des Kopf (N, S, O oder W) -- Xdir und Ydir -- (0,-1),(0,1),(1,0),(-1,0)
    • finde neue Position des Kopf (Xneu, Yneu) = (Xalt + Xdir, Yalt + Ydir)
    • Grafik :: Neuen Kopf zeichnen an (Xneu, Yneu)
    • Grafik :: Alten Kopf löschen --> Körper zeichnen an (Xalt, Yalt)
    • Ringbuffer schreiben (Xneu, Yneu)
    • Wenn (Xneu, Yneu) ist FUTTER ---> Fertig (Schlange wächst)
    • Schwanzposition (Xtail, Ytail) aus RB lesen
    • Grafik :: Alten Schwanz löschen an (Xtail, Ytail)
    • Neue Schwanzposition (Xtail, Ytail) aus RB lesen -- NON DESTRUCTIV!!!
    • Grafik :: Neuen Schwanz zeichnen an Position (Xtail, Ytail)
  • Juhu werte Progammierer! (Ich bin keiner :D )


    Zuerst: Vielen Dank für all den Input (A$)!


    Die Ausführungen von detlef verstehe ich noch am ehesten, allerdings geht mir auch da absolut nicht in den Kopf, weshalb die Schlange brav erst die Länge "L" macht, bevor sie gelöscht wird... Ich komm nicht drauf, selbst wenn ich Zeile für Zeile einzeln betrachte. :(

    Heute saß ich wenigstens "nur" 1,5h vor dem 4032, ehe ich das Handtuch geworfen habe. Das Programm läuft (habe ja Detlefs Version verwendet und nur ein wenig eingekürzt), ich konnte auch Kollisionsabfragen und die Abfrage nach neuen Leckerlis inkl. Verlängerung der Schlange implementieren. Im Prinzip ist also ein Basic-Snake dank eurer Hilfe jetzt kein Thema mehr. Das ist schonmal klasse- aber unbefriedigend, weil ich nicht alleine draufkomme. :D


    Um zu verstehen, weshalb dieser Ringpuffer funktioniert, habe ich all mein zusätzliches Zeug wieder aus dem Programm gelöscht (vorher auf der 8250 gesichert) und versucht, es Schritt für Schritt anzugehen. Hier die Minimalversion, welche einwandfrei funktioniert und eine Schlange mit 10 Zeichen zaubert:


    (Man hätte noch DIM RP(L) schreiben können, ist aber in diesem Fall egal.)

    So, wenn ich nun RUN eingebe, läuft die Schlange nach rechts weg.

    Zeile 220 schreibt ein Leerzeichen an 32768+RP(AP), also beim ersten Schritt der Schlange an die obere linke Bildschirmecke.

    Soweit noch klar.

    Dann kommt 240, hier wird an die Stelle 32768+P, also im ersten Schritt an 32769 das erste Schlangenkörperteil gezeichnet- es ist somit an der zweiten Cursorposition der ersten Zeile.

    Anschließend- und genau da bin ich jetzt raus- schreibt man diese Position in den Ringpuffer (250), welcher im Anschluss um eins hochgezählt wird (260).

    In 270 beginnt der Spaß von vorne.

    Und jetzt kommt der totale Irrwitz, den ich partout nicht verstehen kann:

    P wird eins hochgezählt, da die Schlange im zweiten Durchlauf auch nach rechts fährt (ich drücke keine Taste, also muss das so sein).

    Somit entspricht in Zeile 250 RP(AP)=2, oder? Und AP=1.

    Wenn ich dies in der nächsten Runde dann auf den Bildschirm poke, müsste doch genau diese Stelle gelöscht werden- obwohl die Schlange erst ein Zeichen lang ist?! Weshalb wird die Schlange aber erst brav 10 Zeichen lang, bis die älteste Position mit einem Leerzeichen überschrieben wird?

    Suspekterweise funktioniert es aber einwandfrei... ich bin echt raus.


    Da seht ihr mal: Selbst mit simpelster Vorlage kapiere ich nicht, wie dieses Programm laufen kann... auch wenn ich schwarz auf grün sehe, dass es das tut.
    Meinen vollsten Respekt an die Jungs, die sowas verstehen! Für mich sind das unüberwindbare Themen.


    Diddl , deine Ausführungen in #18 sind sicherlich richtig- ich verstehe aber wirklich nur Bahnhof. HILFE! Man könnte mir auch ein Buch in chinesisch hinlegen... ich "verkopfe" da einfach und nix geht mehr. :(


    Shadow-aSc :

    Evtl. programmiere ich bis dahin ein bisserl weiter... allerdings ist der Elan gerade komplett im Keller, weil ich nicht verstehen kann, wie dieser Ringpuffer arbeitet... bzw. WESHALB er dies tut. :D

    Bissl dran rumwursteln werd ich sicherlich, mit mehreren Leuten macht das sicher Gaudi!


    Der ein- oder andere erinnert sich sicher an mein Interesse, Assembler zu lernen. In solchen Momenten denke ich mir wieder ganz laut "VERGISS ES".

    Das ist ja noch 1000x verzwickter und für mich deshalb noch unlogischer (eben, weil es wohl total logisch ist).


    Manchmal fühle ich mich wie ein Idiot. Echt komisch.


    Viele Grüsse,

    Matthias