Hallo Besucher, der Thread wurde 1,2k mal aufgerufen und enthält 12 Antworten

letzter Beitrag von He-Man am

Joystickabfrage und Spritebewegung

  • Hallo liebe Assembler-Profis,


    ich bringe mir gerade selbst Assembler bei mit dem Ziel später mal ein einfaches Spiel zu programmieren. Ich beschäftige mich gerade mit dem Thema Joystickabfrage und wie man mit dem Joystick ein Sprite über den Bildschirm bewegt. Jetzt gibt es dafür natürlich mehrere Möglichkeiten und Beispielroutinen im Netz.

    Hierzu meine Fragne:

    In den meisten Fällen habe ich irgendwelche Demoroutinen gesehen, die mit einem Endlos-loop die Speicheradresse für den Joystickport abfragen und auswerten. Wie funktioniert das aber in einem richtigen Spiel? Ich kann mir vorstellen, dass da ja noch viele andere Dinge im Hintergrund passieren und das Programm nicht in einer Endlosschleife nur den Joystick die ganze Zeit abfrägt.

    Ich hab mir dazu meine Gedanken gemacht und eine Joystickabfrage mittels Interrupt gemacht. Das Programm funktioniert und ich kann mein Sprite tatsächlich mit dem Joystick korrekt bewegen. Allerdings bewegt es sich nicht gerade besonders schnell. Woran liegt das? Ist hier die Frequenz, mit der der Interrupt ausgeführt wird, der geschwindigkeitslimitierende Schritt? Und wie coded man das so, dass ich die Geschwindigkeit selbst regulieren kann?


    Ich hab den Code meines Programms hier eingefügt. Gerne könnt ihr mal drüber schauen. Für Verbesserungsvorschläge bin ich dankbar.


    Viele Grüsse,

    He-Man

  • Hi, doch das ist eigentlich die uebliche Variante. Das Sprite bewegt sich jetzt halt mit einer Geschwindigkeit von 50 Pixeln pro Sekunde. Es benoetigt also ca. 6 Sekunden vom linken Rand bis zum rechten. Wenn sich das Sprite schneller bewegen soll, musst Du es eben 2 Pixel pro Interrupt-Aufruf bewegen statt nur 1.


    Bei "Shadow Switcher" ist es so, dass die Spielfigur sich in einem Frame um 2 Pixel bewegt, im naechsten um 1, dann wieder um 2 usw, somit ist die Figur quasi "1.5x" so schnell bzw. bewegt sich 1.5 Pixel pro Frame im Durchschnitt (die Gegner hingegen nur mit 1 Pixel pro Frame). Das faellt aber nicht auf, weil es eine "regelmaessige Unregelmaessigkeit" ist, sozusagen :) also die Figur ruckelt nicht, sondern bewegt sich scheinbar gleichmaessig ueber den Bildschirm (sofern auf echter Hardware ausgefuehrt).

  • Hi ZeHa,


    danke für die Antwort. Was meinst Du mit "die übliche Variante"? Dass der Joystick in einer Endlosschleife abgefragt wird oder mittels Interrupt?


    Das mit der "Pixel pro Frame" Bewegung klingt für mich logisch. Hätte man natürlich auch selbst drauf kommen können. 8) Ich bin noch Anfänger was das Assembler Programmieren angeht. Deshalb natürlich die Frage: Wie verändert man denn die Anzahl der Pixel, die sich pro Frame bewegen?

  • Hier habe ich das Tutorial gehostet (https://www.georg-rottensteine…projectj/step1/step1.html)


    Bei Schritt 4 ist die Joystick-Routine drin:


    https://www.georg-rottensteine…projectj/step4/step4.html



    Im Grunde gibt es eine GameLoop-Routine, die zuerst eine bestimmte Rasterzeile abwartet. Wenn die erreicht ist, wird die Steuerung aufgerufen (1x pro Frame)

  • Ich hab mir natürlich schon den 4. Schritt in Deinem Tutorial vorher angesehen und das Programm mal kurz laufen lassen. Allerdings hat sich da das Sprite mit der gleichen Geschwindigkeit wie bei mir bewegt. Deswegen war mir nicht klar, wie man denn die Geschwindigkeit hier verändern kann.


    Aber danke für die ausführlicherer Erklärung, Endurion und ZeHa. Jetzt hab ich da neuen Input, der mir definitiv weiterhelfen wird.

  • Bei Shadow Switcher habe ich sogar die ganze Bewegungs- und Kollisionsroutine zweimal aufgerufen. In einem Frame nur einmal, in einem zweimal, wie oben erwaehnt. Der Vorteil ist, dass er dann trotzdem pro "Schritt" immer nur 1 Pixel laeuft und die ganzen Kollisionsberechnungen usw. immer "konsistent" ablaufen und nicht einmal so programmiert sein muessen dass sie mit einer Bewegung von 2 Pixeln klar kommen und einmal nur mit 1 Pixel. Hat die Sache deutlich einfacher gemacht, somit erspart man sich viele Bugs und hat eine sauber funktionierende Routine. Zeitlich gesehen wars kein Problem, die direkt zweimal hintereinander aufzurufen. Also das nur mal als Zusatzinfo, gut moeglich dass Du das in Deinem Fall nicht brauchen wirst :)

  • Also den Code habe ich nirgends veroeffentlicht, aber im Prinzip ist es halt so, dass eine Kollisionsroutine immer simpler zu programmieren ist, wenn Du genau weisst, wie viele Pixel die Figuren laufen, als wenn das dynamisch sein kann. Wenn die Figur pro Schritt nur 1 Pixel laeuft, ist alles ganz einfach, dann kannst Du, wenn sie 1 Pixel zu weit in der Mauer bist, dies einfach "korrigieren" oder die Bewegung einfach gar nicht ausfuehren (die Routine vorzeitig verlassen). Wuerde die Figur jedoch mit einer Beschleunigungskurve laufen, dann ist sie mal 2 oder 3 oder 4 Pixel schnell usw, und dann musst Du evtl anders korrigieren, z.B. dass die Figur bei einer Ueberlappung mit der Wand bis exakt an den Wandrand geschoben wird. Wenn Deine Routine nun aber so geschrieben ist, dass sie die Figur eh immer nur 1 Pixel weit bewegt, und Du diese einfach nur im Falle einer hohen Geschwindigkeit oefters nacheinander aufrufst, dann erledigt sich das von allein. Nachteil ist natuerlich eine evtl. hoehere Laufzeit.


    Teilweise wird sowas auch "Fixed Timestep" genannt, allerdings eher bei moderneren Spielen. Hier geht es ja auch teilweise darum, dass die Framerate unterschiedlich sein kann, die Figuren sich aber unabhaengig davon immer gleich schnell bewegen sollen. Auf dem C64 und anderen alten Rechnern hat man ja den Luxus, dass man sich per Interrupt auf eine exakte Framerate verlassen kann.