[B+] Ereignis gesteuerte Programmierung

Übersicht BlitzBasic FAQ und Tutorials

Neue Antwort erstellen

D2006

Administrator

Betreff: [B+] Ereignis gesteuerte Programmierung

BeitragDo, Jan 26, 2006 14:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Einführung in Ereignis gesteuertes Programmieren bei Spielen
============================================

Teil 1: Blitz2D, Blitz3D und 'Abrufen'
---------------------------------------------

Blitz2D und 3D basieren beide auf ein Abruf Konzept, genannt "polling".

Die Idee dahinter beschreibt, dass ein Programm, um Informationen über Geräte wie Tastatur, Maus, Joysticks und so weiter herauszufinden, ununterbrochen den Status abrufen muss.

Zum Beispiel fragt ein Programm wie:

Code: [AUSKLAPPEN]
Graphics 640,480,16,1
;
While Not KeyHit(1)
    mx=MouseX()
    my=MouseY()
    Cls
    Text 0,0,mx+","+my
    Flip
Wend
;
End


... ständig die Tastatur ab, um zu prüfen ob die "Esc" Taste gedrückt wurde. Es fragt auch die Maus nach den aktuellen Koordinaten ab, um diese auf dem Bildschirm auszugeben.

Das ist eine simple und leicht verständliche Technik, sie hat aber auch Nachteile:

* Der größte Nachteil ist wohl, dass das Betriebsystem eigentlich ganz anders arbeitet, so dass nur eine eingeschränkte Interaktion mit dem Betriebssystem stattfinden kann.

* "Polling" ist nicht sehr "systemfreundlich", da es andauernd die Aktivität des Benutzers abfragt. Dafür benötigt es natürlich sehr viel CPU Zeit.

* Es ist nicht wirklich effizient - Warum dauernd die Mauskoordinaten abfragen auch wenn der Benutzer sie nicht bewegt? Die obige Schleife führt 3 Abfragen (KeyHit, MouseX und MouseY) aus, welche zu 99% der Zeit durch fehlende Eingaben sinnlos sind. Nur das übrige 1%, wenn der Benutzer auch tatsächlich die Maus bewegt, ist WIRKLICH wichtig.

Teil 2: Ereignis gesteuertes Programmieren
-------------------------------------------------------

Eine Alternative zu "polling" ist "Ereignis gesteuertes" Programmieren. Zwar ist es ein wenig komplexer, aber die Idee dahinter ist trotzdem ziemlich simpel.

Anstatt Dein Programm dauernd die Geräte auf Veränderungen überprüfen zu lassen, wird es über Änderungen vom System informiert. Wenn also entsprechende Veränderungen auftreten, wird ein "Ereignis" (in englisch "Event") generiert und zu deinem Programm geschickt.

Die Grundidee wenn man Ereignis gesteuerte Programme schreibt ist also, dass dein Programm "dasitzt" und wartet das ein Ereignis auftritt, um dieses dann auszuwerten und bestimmte Aktionen folgen zu lassen.

Als Beispiel hier der Code von oben umgeschrieben für das Ereignissystem:

Code: [AUSKLAPPEN]
Graphics 640,480,16,1
;
While WaitEvent()                ;mit WaitEvent() warten wir auf ein Ereignis
    Select EventID()
    case $101                 ;Ein 'Taste gedrückt' Ereignis
        If EventData()=1        ;EventData() ist hier der Scancode der Taste
            End
        Endif
    case $203                ;Ein 'Maus bewegt' Ereignis
        mx=EventX()            ;EventX() ist die neue X-Koordinate der Maus
        my=EventY()            ;EventY() ist die neue Y-Koordinate der Maus
        Cls
        Text 0,0,mx+","+my
        Flip
    End Select
Wend


Warum das besser ist als die erste Methode, wo es doch komplexer aussieht?

* Die Ereignis gesteuerte Version ist komplett "systemfreundlich". Der WaitEvent() Befehl bringt das Programm zu einem kompletten Stopp, solange bis ein Ereignis auftritt. Während dieser "Pause" können andere Programme des Benutzers, die eventuell parallel laufen die komplette CPU Zeit nutzen, ohne von deinem Programm unterbrochen zu werden.

* Es ist auch effizienter. Der Bildschirm wird nur neugezeichnet, wenn die Maus auch bewegt wurde, wohingegen die erste Version ständig den Bildschirm aktualisiert. Zwar könnte man die erste Version umschreiben, um einen ähnlichen Effekt zu erzielen, aber mit Ereignissteuerung ist das viel einfacher. Des Weiteren neigen "polling" Codes von Natur aus dazu ineffizient zu sein!

* Während das gezeigte Beispiel nur mit den Tasten- und Mausereignissen arbeitet, gibt es viele weitere Ereignisse, die vom Programm abgefangen werden können. Das erlaubt einen höheren Grad der Kommunikation zwischen Deinem Programm und dem Betriebssystem.

Noch ein Hinweis:
* Die Bedeutung von EventData(), EventX() und EventY() ist abhängig vom Ereignis selbst. Nicht alle Ereignisse verwenden diese Funktionen.

Teil 3: Die Zeitsteuerung von Spielen mit Hilfe von Timern
------------------------------------------------------------------------

Hier ist ein Beispiel für eine Zeitsteuerung in Spielen:
Code: [AUSKLAPPEN]
Graphics 640,480,16,1
;
timer=CreateTimer( 30 )
ticks=0
;
While WaitEvent()
    Select EventID()

    Case $101
        If EventData()=1 End        ;Beenden wenn "Esc" gedrückt wird

    case $4001                ;Ereignisnummer für ein Timer-Tick Ereignis

        verstrichen=EventData()-ticks    ;EventData() beinhaltet die komplette Anzahl der Timer-Ticks

        For n=1 To verstrichen
            AktaulisiereAlles()
        Next

        ticks=ticks+verstrichen

        ZeichneAlles()
        Flip False

    End Select
Wend


Wahrscheinlich ist die Sache mit den verstrichenen Ticks das einzig annähernd unverständliche hier. Alles was gemacht wird, ist die Berechnung der Anzahl der verstrichenen "Ticks" seit dem letzten Ereignis. Normalerweise ist der Wert von "verstrichen" gleich eins, aber auf langsameren Rechnern kann der Wert auch durchaus höher sein.

Beachte, dass dies vielleicht die beste und einfachste Möglichkeit für frameabhängige Zeitsteuerung ist. Während das Programm wartet, ist die CPU Auslastung des Programms bei 0%.

Teil 4: Zeitsteuerung in Spielen mit Hilfe von VWait / Flip
-----------------------------------------------------------------------

Dies ist ein wenig komplexer, aber nicht viel...

Code: [AUSKLAPPEN]
Graphics 640,480,16,1
;
Repeat
    While WaitEvent()
        Select EventID()
        Case $101
            If EventData()=1 End
        End Select
    Wend

    AktualisiereAlles()
    ZeichneAlles()
    Flip True

Forever


Beachte wie sich die WaitEvent() Schleife verändert hat. Dies ist nötig, da der Flip Befehl potentiell eine Weile zum Ausführen braucht, weil er auf die vertikale Synchronisation wartet.

Während dieser Zeit könnten eine Reihe von Ereignissen aufgetreten sein. Deswegen ist es eine gute Idee all diese Ereignisse "gierig" auszuwerten.

Beachte dass, obwohl auf VWait / Flip basierende Zeitsteuerung die besten Ergebnisse im Hinblick auf Synchronisation liefert, diese Methode nicht sehr "systemfreundlich" ist. Dies ist hauptsächlich darauf zurückzuführen, dass VWait selbst auf "polling" basiert! Darauf hat Blitz keinen Einfluss, weil dieser Befehl vom Grafiktreiber ausgeführt wird.

Tutorial Ende
----------------

Nützlicher Link:
Liste aller Ereignisse, samt der Belegung der Auswertungsfunktion

Tutorial von Mark Sibly
Übersetzt von Daniel Liebetrau
Intel Core i5 2500 | 16 GB DDR3 RAM dualchannel | ATI Radeon HD6870 (1024 MB RAM) | Windows 7 Home Premium
Intel Core 2 Duo 2.4 GHz | 2 GB DDR3 RAM dualchannel | Nvidia GeForce 9400M (256 MB shared RAM) | Mac OS X Snow Leopard
Intel Pentium Dual-Core 2.4 GHz | 3 GB DDR2 RAM dualchannel | ATI Radeon HD3850 (1024 MB RAM) | Windows 7 Home Premium
Chaos Interactive :: GoBang :: BB-Poker :: ChaosBreaker :: Hexagon :: ChaosRacer 2

Neue Antwort erstellen


Übersicht BlitzBasic FAQ und Tutorials

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group