Posts by Acorn

    Wenn man es Verstanden hat, ist das sehr simpel. Die BD-Engine von Peter Liepa macht das übrigens für die Hauptschleife genauso. Ich verwende das zusätzlich beim Stein/Diamant und der Amöbe. Bei der Amöbe nur, weil man nachdem wachsen überprüfen muss, ob diese noch frei ist.


    Noch was zur Kollision:

    Normalerweise werden nur beim Glühwürmchen und Schmetterling alle vier Richtungen überprüft. Das hat einen großen Nachteil, für den Spieler ist jedoch ein Vorteil. Deshalb sollte man auch beim Spieler ein Kollisionstest einbauen.


    Sonst kann man sowas machen.

    Bekanntlich arbeitet die Engine von links oben an, das Zeile für Zeile. Wenn man beim Glühwürmchen wartet, bis diesen genau unter einem ist, würde beim nächsten Durchgang eine Kollision erkannt. Da der Spieler eine Zeile höher steht als der Glühwürmchen, kann man noch einen Schritt gehen, zeitlich hat die Kollision ja noch nicht stattgefunden. Bewegt man sich in die Laufrichtung des Glühwurms, sieht das im Spiel so aus, als wenn der Spieler genau über dem Glühwürmchen ist. Das kann man sehr schön bei Level I aus BD-II testen.

    In Feld (B) sind alle Zeilennummern, die den liegenden Stein betreffen. Mit Feld (A) werden die entsprechenden Routinen angesprungen.

    Files

    • bd-engine.prg

      (13.75 kB, downloaded 3 times, last: )

    Müssen wir dann alles komplett neu machen. Sprich denn jetzigen Stand anhalten und von vorne beginnen mit deinen vorgeschlagender Version ?

    Wenn es dadurch schneller wird, warum nicht.

    Übrigens, es besteht hier absolut kein Zwang, wenn Du mit der Variante von TheRealWanderer besser klar kommst, warum nicht. Man kann ja das ein oder andere übernehmen.

    Die schlechte Kollisionsabfrage kann man durch mehrfach abfragen deutlich verbessern. Normalerweise wird die Kollision vom Stein ausgelöst, da der Schmetterling ebenfalls eine Kollisionsabfrage für den Spieler und Amöbe enthält, könnte die nach oben Abfrage zusätzlich auf fallenden Stein erweitern. Dann sollte die Kollision mit einem fallenden Stein besser erkannt werden.

    Ich wäre dazu bereit das auch wieder umzuschreiben, wenn es dadurch schneller wird.

    Ich habe das jetzt mal beim liegenden Stein getestet und wir müssen Dich doch nicht in den Wahnsinn treiben. Im direkten Vergleich kann man keinen Unterschied sehen, zweimal Mega65 gestartet und laufen laufen laufen gelassen. Nochmal Glück gehabt, die Abfrage erst unten links und rechts zu testen ist optimal, dadurch wird IF THEN für links rechts selten ausgeführt.

    So wie ich diesen Code verstehe, gehst du da alle Positionen durch das Spielfeld durch, oder sind die Variabeln die Steine.

    Ja ich gehe alle Positionen durch und die Engine arbeitet von oben nach unten, damit wird das Verhalten der BD-Engine genau nachgebildet.

    Könntest du da mal ein kurzes Programm schreiben.

    Ich Versuche das mal kurz zu erklären:

    Mit PEEK(O) wird das aktuelle Objekt ausgelesen. Die Reihenfolge der Objekte geht von CHARDEF 0 - CHARDEF 52.

    CHARDEF 0 ist SPACE

    CHARDEF 1 ist SAND

    usw.

    CHARDEF 13 ist der Stein liegend und 14 fallend.


    Wird mit der Zeile O=O+1:FGOTO A(PEEK(O)) zum Beispiel SPACE gelesen, springt die Routine direkt wieder auf die Zeile. Da in A(0)= die Zeilennummer für die Aktion von Space steht. Bei passiven Objekten wird praktisch die Zeile solange ausgeführt bis ein aktives Objekt gefunden wird. Beim Stein A(13) zeigt der Sprung auf die Routine -> Stein unten, da bei unten mehrere Abfragen möglich sind, wird wieder ein FGOTO B(PEEK(O+40)) verwendet.

    Wenn jetzt unter den Stein ein Space ausgelesen wird, springt die Routine direkt nach Stein fällt runter. Dadurch werden keine unnötigen Abfragen gemacht.

    Mit diesen einen FGOTO ist sofort klar, was zu machen ist, Space = fallen : Stein = rollen : Diamant = rollen : Magische Mauer = Stein zu Diamant : usw.


    Ich hoffe, das Prinzip ist jetzt etwas klarer.

    Ein drumherum Update von mir, über das Basic und seine Eigenheiten mit dem Datentype Real. Ach wäre es schön, wenn Integer nicht nur bei FOR TO NEXT verwendet würde.

    Schleifen sind damit extrem schnell im Vergleich zu Real. Leider sind in der Hauptschleife von BD nur IF THEN nötig und die sind extrem lahmmmmm im Vergleich zu FOR. Das liegt natürlich an den Datentype Real, der deutlich langsamer ist. Bei PEEK und POKE ergibt Real gar keinen Sinn, aber selbst da wird intern mit Real gerechnet. Man kann sogar solchen einen Unsinn schreiben A=53280.999:POKE A,1. Kurz noch, es gibt das Binäre verschieben mit << >>, das auch langsamer als * oder / ist hmmmm.

    Aber zurück zu IF THEN und die viel schnellere Alternative dazu.


    Hier mal eine Zeile der Abroll-Routine -> Stein/Diamant.

    Code
    1. 60 IF PEEK (O+39) =. THEN IF PEEK (O-L) =. THEN NEXT
    2. 60 FGOTO A(PEEK(O+39))
    3. 65 FGOTO A(PEEK(O-L ))
    4. 70 NEXT

    Im Bench benötigt eine Schleife von 10000 ca. 1,95 Sekunden und mit FGOTO nur 1,34. Und das auch nur, weil ich hier den Punkt verwenden kann, sonst wäre IF noch langsamer. Man könnte jetzt einfach FGOTO verwenden und gut ist, aber der arme Drachen müsste sich Tage und Nächte lang in den Code einlesen. Und sich durch eine Wüste von DIM Feldern kämpfen, um Zeilennummern anzulegen oder zu ändern.


    Mit FGOTO würde das in etwas so aussehen.

    Code
    1. 20 O=O+1:FGOTO A(PEEK(O)) : REM Hauptschleife
    2. 30 FGOTO B(PEEK(O+40)) : REM Stein (liegt) unten
    3. 40 FGOTO C(PEEK(O+39)) : REM Stein (liegt) links unten
    4. 50 FGOTO D(PEEK(O+41)) : REM Stein (liegt) rechts unten
    5. 60 FGOTO C(PEEK(O-1 )) : REM Stein (liegt) links
    6. 70 FGOTO D(PEEK(O+1 )) : REM Stein (liegt) rechts
    7. 80 POKE O,.:POKE O-1,14:GOTO 20 : REM Stein (liegt) links bewegen -> Stein fallend
    8. 90 POKE O,.:O=O+1:POKE O,14:GOTO 20 : REM Stein (liegt) rechts bewegen -> Stein fallend

    Für den fallenden Stein werden nochmal drei DIM Felder benötigt. Bei den anderen aktiven Objekten kommen nochmal unzählig Felder dazu. Man könnte dann sogar die Zeilen im Programm so legen, das die häufig ausgeführten Zeilen möglich oben im Programm liegen. Allein die Sprünge für jedes Feld zu definiert, damit jedes Objekt richtig behandelt wird, kostet viel Zeit und besonders viel, wenn sich ein Fehler eingeschlichen hat.


    Jetzt die Frage IF THEN belassen oder DIM und damit Drachen in den Wahnsinn treiben mit A(0)=20:A(1)=20. Übrigens, jedes Feld hat eine Dimension von (52), das sind viele Sprünge, die man eintragen muss. Aber allein das Entfernen von ON GOTO durch FGOTO führte zu ein spürbares Speedup, obwohl jetzt hohe Zeilennummern benutzt werden. Mit Einser schritte von 0 ab sollte für ein weiteres Speedup sorgen, aber das ist erst beim fertigen Spiel sinnvoll.

    Bei TheRealWanderer Ansatz werden nur die aktiven Objekte verwaltet. Durch das Aufteilen in mehrere Array braucht man nur die Position der Objekte, zu speichern.

    In der Hauptschleife wird je ein Element pro Array bearbeitet. Sobald ein Array komplett bearbeitet ist, wird sofort wieder mit dem erste begonnen, deshalb werden auch die Objekte unterschiedlich schnell bewegt. Um das zu verhindern, müsste man für die kürzeren Array einen Mittelwert berechnen, damit alle gleich schnell abgearbeitet werden.

    Ahhh ich weiß was du meinst und das ist ein echtes Problem. Ein Gegner wird von einem Stein erschlagen, im Bildschirmspeicher ist das Position X vom Stein und X+40 für den Gegner. Die Position vom Stein im Array ist bekannt, da dieser die Explosion ausgelöst hat, da könnte man einfach eine Position wählen, die außerhalb des Spielfelds liegt. Beim Gegner ist Position logischerweise unbekannt, dafür müsste man das Array durchsuchen welches Objekt POS X+40 belegt und diesen ebenfalls außerhalb des Spielfelds legen. Aber wenn die Explosion weitere Gegner erwischt, müssten diese ebenfalls gesucht und entfernt werden. Bei vielen Gegnern wie im Level M könnte das extrem langsam sein. Und es könnten eventuell noch weitere Nebenwirkungen beim Diamanten-Array auftreten, wenn die Schmetterlinge sich in Diamanten verwandeln und den Platz von vorhandenen Diamanten einnehmen. Dann sind im Array zwei oder mehr Einträge vorhanden, für ein und demselben Diamanten und beim Herunterfallen erscheinen diese dann.


    Mir fällt leider keine bessere Lösung ein, als alle Array zu durchsuchen und die doppelten Einträge zu entfernen.

    Habe Level 4 mit dem Schmetterling etwas durchgetestet. Damit ist mir Folgendes aufgefallen oder passiert. Beim ersten Start des Levels drehen die Schmetterlinge falsch herum. Nachdem man ein Leben verloren hat, variiert die Drehrichtung, mal drehen alle richtig, mal nur einige. Das Erschlagen eines Schmetterlings mit einem Stein ist sehr ungenau, obwohl der Stein am Fallen ist, dreht der Schmetterling einfach um. Wenn das Erschlagen gelingen, kann man die Diamanten nur von oben an sicher einsammeln, ansonsten kann es passieren das man dabei erschlagen wird. Ab und zu passiert sogar etwas ganz komisches, nachdem erschlagen eines Schmetterlings sind in der letzten Box ganz rechts plötzlich zwei Schmetterlinge vorhanden. Die Kollision durch die Schmetterlinge ist praktisch nicht vorhanden, solange der Spieler nicht im Weg steht. Damit die Kollision besser funktioniert, musst du vorher alle vier Richtungen überprüfen, ob sich dort der Spieler oder die Amöbe befindet.

    Die Zeilennummeren werde ganz am Schluß änderen. Jetzt möchte ich sie nur großräumig auslegen damit ich zwischendrinen was einpflanzen kann wenn es nötig ist.

    Warum benutzt du den Label Mode nicht, da hat man das Problem erst gar nicht.

    Acron warum benutz du nicht Restor mit Zeilennummer. Das setzt den interen Zeiger von Read Data direkt auf auf diese Datazeilen. Dann könnte die Zeile 240 eventuell so ausehen

    Bei den Leveldaten war das nicht nötig, da alle Level einfach nur angezeigt werden. Im fertigen Spiel wird das Restore Zeilennummer sogar gebraucht, sobald der Spieler das Level wiederholen muss.


    Was ich mir auch überlegt habe, das komplette Programm mit eine neuen Variabelsystem zu versehen

    Mit den Namen der Variablen kämpfe ich auch und das Find/Replace arbeitet leider nicht zuverlässig. Blöderweise gibt es im Basic-Editor des C64Studio keine Deklarierung von Variablen-Namen / Labels usw., dann hätten wir das Problem erst gar nicht.


    Ach wäre sowas schön und übersichtlich, ein Traum so in Basic zu programmieren.


    !DEFVAR SPACE=L

    !DEFVAR STEIN=S

    !DEFVAR DIAMANT=D

    !DEFKON UNTEN=40

    !DEFKON LINKS=-1

    !DEFLAB STEIN_LIEGT

    !DEFLAB DIAMANT_LIEGT


    HAUPT_SCHLEIFE

    ON GOTO STEIN_LIEGT,DIAMANT_LIEGT


    STEIN_LIEGT

    IF PEEK(SCREEN+POS+UNTEN) = SPACE THEN POKE SCREEN+POS+UNTEN,STEIN : POKE SCREEN+POS,SPACE : GOTO HAUPT_SCHLEIFE

    Wie sage TheRealWanderer, wir brauchen nachher alles an Optimierung was geht.

    Eine große Bremse beim Erzeugen der Level ist das Auswerten, welche Farbe bei Zeichen X benötigt wird. Leider sind solche IF THEN Geschichten von ein gewissen D. immer Gift für Basic, da diese viel zu viel Zeit kosten. Das Berechnen der Pseudo-Werte kostet ebenfalls sehr viel Zeit, weil hier jeder Überlauf nachgebildet werden muss.

    Und wieder ist hier IF THEN der Übeltäter, der das ganze deutlich ausbremst. Dabei wäre gar kein IF THEN nötig, wenn man den Variablentyp Byte verwenden könnte, da dieser beim Überlauf kein ?ILLEGAL QUANTITY ERROR erzeugt. Leider gibt es keine Möglichkeit so einen Überlauf abzufragen und damit bleibt nur der Umweg.

    Aber ein IF THEN kann man ersetzen, und zwar durch FOR A%=0 TO 799 : NEXT, das ist auch merklich schneller. Als letztes bleiben die hohen Zeilennummern, die bremsen ebenfalls etwas. Dann habe ich noch das Binäre schieben gefunden, leider ist das kaum schneller als IF THEN, weil man mit A&=A&<<7 verschieben muss.

    Ein rollen von A&=A&>>2 wäre bestimmt schneller gewesen, das wird aber nicht angeboten.


    Für den Schleim (Glibber) aus Boulder Dash II, wird ebenfalls die Pseudo-Routine benötigt. Deshalb habe ich auch im Programm Leveldaten die Routine angepasst, da der Schleim mit den zuletzt erzeugten Werten weiter rechnet. Ich verwende immer noch Integer und Byte, da der Typ Real zur Zeit mit vielen Konstanten der Haupt-Routine belegt ist.

    Das Programm vom C64 läuft jetzt auf dem Mega65, dafür musste ich nur die Adresse vom Bildschirmspeicher auf 2048 setzen. Zusätzlich habe ich die schöne Kino-Grafik (online Textkorrektur) von Drachen geklaut, teilweise aber mit andere Farben für die Zeichen versehen.


    Genug der Worte, es ist etwas schneller aber nicht viel hust hust.

    Files

    Das Programm mit den Variablentype REAL funktioniert nur wegen dieser Zeile nicht mehr korrekt.


    51145 PA=PA+P2/2:IF PA>255 THEN PA=PA AND 255


    Und damit es wieder richtig läuft.


    51145 PA=PA+P2/2AND255:IF PA>255 THEN PA=PA AND 255


    Verwende mal für P1 und P2 den Type BYTE.

    Es liegt an der Adresse für das Farbram, wenn du dir die Zeile 8500 genau anschaust, wird dir sofort klar, warum das .......... lalalala $D800 lalala -$0800 = OH hollala $D000.

    Sorry Snoopy, das kannste natürlich nicht riechen, das Programm zum Arbeiten sieht so aus. Das Umstellen auf FGOTO kostet später aber kaum Zeit, da man die Sprünge einfach in Datazeilen umwandeln kann, das ist auch viel besser als alles mit DIM O(1)=2 zu definieren. Sobald Drachen mit meiner Engine anfängt, werde ich ihm die den aktuelle Sourcecode geben. Bis dahin werde ich das ein oder andere noch eingebaut haben.



    Werde aber erst mal die Engine von TheRealWanderer und deine Aufbauroutine soweit fertig machen das man einiger maßen damit spielen kann.

    In der Engine von TheRealWanderer ist noch ein blöder Bug drin, beim Abrollen der Steine/Diamanten fehlt das Bewegen zur Seite.

    Mit vielen Feldern für die Sprünge kann man auf FGOTO wechseln, das würde ich aber erst machen, wenn das Programm so weit steht. Bei Änderungen wegen Bugs oder verschieben von Zeilen müsste man die Felder sonst von Hand anpassen. Es ist jetzt noch weniger übersichtlich als mit ON GOTO, da man die Sprungziele nicht mehr sieht, dafür aber einen Tick schneller. Und alles, was irgendwie Geschwindigkeit bringt, sollte man auch ausnutzen, denn es gibt mit Level I einen harten Brocken.

    FGOTO hat sogar den Nachteil, das man keine variierende Sprungziele benutzen kann. Der liegende Stein erschlägt keine Gegner, deshalb springt die Routine wieder nach Zeile 2, beim fallenden Stein wird der Gegner erschlagen und springt nach Zeile 35.


    Hier mal die aktuelle Objekt-Liste


    1 = Space -> Zeile 2

    2 = Sand -> Zeile 2

    3 = Stein liegt -> Zeile 3

    4 = Stein fällt -> Zeile 8

    5 = Diamant liegt -> Zeile 13

    6 = Diamant fällt -> Zeile 18

    7 = Stahl -> Zeile 2

    8 = Mauer -> Zeile 2

    9 = Spieler -> Zeile 23

    10 = Flag von Stein unten aufheben -> Zeile 12

    11 = Levelende -> Zeile 1

    12 = Flag von Spieler unten aufheben -> Zeile 34

    13 = Explosion 1 -> Zeile 65

    14 = Explosion 2 -> Zeile 66

    15 = Explosion 3 -> Zeile 67

    16 = Explosion 4 -> Zeile 68

    17 = Flag von Diamant unten aufheben -> Zeile 22

    18 = Glühwurm 1 -> Zeile 69

    19 = Glühwurm 2 -> Zeile 76

    20 = Glühwurm 3 -> Zeile 83

    21 = Glühwurm 4 -> Zeile 90

    22 = Flag Glühwurm 2 unten aufheben -> Zeile 97


    Die Reihenfolge der Objekte ist auch noch nicht optimal, die würde ich nochmal neu sortieren.

    Zum Beispiel würde ich den Sand mit Space tauschen, da dieser häufiger vorkommt, mit der Hoffnung das der erste Sprung bei On Goto schneller ist als der nächste.

    Habe jetzt noch ein paar Objekte hinzugefügt, damit man auch mal einen echten Level testen kann. Da alle 800 Felder getestet werden, ist die Geschwindigkeit deutlich langsamer als die Engine von TheRealWanderer.