Heute programmiere ich eine Console
Übersicht

![]() |
bruZardBetreff: Heute programmiere ich eine Console |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hier will ich einmal die Frage "Wie programmiere ich eine Console" bearbeiten, da sie ja desöfteren gestellt wird.
Zunächst klären wir einmal was eine Console tut: Offenbar schaltet man sie mit einer Taste ein und aus und man kann mit ihr Eigenschaften innerhalb des Games verändern. Soweit so gut, aber wie kann man dies auf ein BB Programm übertragen? Um das zu erläutern müssen wir uns den Begriff STATE anschauen: Ein State ist ein Zustand, ihr drückt zuhause auf den Lichtschalter, die Glühbirne geht in den State "an", Ihr drückt nocheinmal und der State wechselt auf "aus". Um die Console zu aktivieren und zu deaktivieren tun wir nichts anderes, wir drücken einen Schalter: Code: If KeyHit(15) Then zeige_console=1-zeige_console Mit einem Druck auf die Tabulatortaste wechselt der Inhalt von "zeige_console" zwischen 0 und 1, ist "zeige_console" gleich 1, wird sie angezeigt, ansonsten nicht. Ok, wir können jetzt die Console ein und ausschalten, jetzt muss das nur noch einen Sinn machen. Für die Eingabe in die Console sollte eine Input-Routine verwendet werden die den normalen Programmablauf nicht anhält, demzufolge fällt die BB Funktion "Input()" für uns flach, wir benötigen mehr Power. Betrachten wir uns einmal die Funktion GetKey(), sie erfasst die Tastatureingaben und liefert uns einen ASCII Code zurück der dem eingegebenen Zeichen entspricht. Mit Chr() können wir aus diesem Code wieder ein Zeichen machen. Stopp: Wie soll die Console eigentlich verwaltet werden? Natürlich in einer eigenen Funktion welche sich in einem Include befindet. Das erlaubt es den Code auch in anderen Projekten zu verwenden, während man dabei nur marginale Veränderungen vornehmen muss. Jetzt stellt sich die Frage was wir denn alles brauchen um die Funktion in einem eigenen Modul "am Leben" zu halten. Nun, zunächst einmal müssen wir eine globale Variable definieren in die wir den Text speichern der zur Zeit eingegeben wird. Ich nenne sie einfach einmal "cline$" (abgeleitet von current line). Mit diesen Dingen haben wir jetzt folgenden Code: Code: Global cline$ Function Console() key=GetKey() End Function Nicht sehr umfangreich und kaum nützlich. Um das zu ändern fügen wir den Code zur Texteingabe hinzu, dazu führen wir eine weitere globale Variable ein, welche uns sagt ob die Console gerade offen ist: show_con. Ab jetzt nehmen wir nur noch Eingaben entgegen wenn die Console auch offen ist: Code: Global cline$ Global show_con = False Function Console() If show_con key=GetKey() EndIf End Function Super, Eingaben werden in key geschrieben ... damit können wir aber nichts anfangen, wir brauchen den Kram in einem String ... deshalb bekommt unsere globale Variable cline$ jetzt einen Job. Um sicher zu stellen dass nur sichtbare Zeichen in den String geschrieben werden beschränken wir die Annahme von Zeichen auf den Bereich 32 bis 255. Code: Global cline$ Global show_con = False Function Console() If show_con key=GetKey() If key>=32 And key<=255 Then cline$=cline$+Chr(key) EndIf End Function Schon besser, alles was sich tippen lässt wird nun auch in cline$ gesichert. Das aber nur wenn die Console auch offen ist. Da wir in der Hauptschleife nur den Aufruf Console zu stehen haben wollen, muss der Code zum switchen in die Funktion, wir dieser aussieht hatten wir oben schonmal: Code: Global cline$ Global show_con = False Function Console() If KeyHit(15) Then show_con=1-show_con If show_con key=GetKey() If key>=32 And key<=255 Then cline$=cline$+Chr(key) EndIf End Function Repeat Cls Console Flip Until KeyHit(1) End Was haben wir jetzt? Wir haben eine Console die sich ein und ausschalten lässt und die Möglichkeit den String cline$ mit Zeichen zu füllen wenn die Console offen ist. Super, aber man sieht nichts, weder dass die Console offen ist, noch dass etwas geschrieben wird ... ausgesprochen unvorteilhaft. Wir benötigen mehr Daten: Code: Global cursor Global cursor_time = MilliSecs() Global cursor_speed= 250 Die neue Variable cursor sagt uns ob der Cursor gerade angezeigt wird, cursor_time beinhaltet den Zeitpunkt an dem der Cursor zuletzt angezeigt wurde und cursor_speed gibt uns die Blinkgeschwindigkeit an. Jetzt müssen wir nur noch abfragen wie spät es jetzt ist, feststellen ob die Blinkgeschwindigkeit erreicht wurde und dann den Cursor umschalten: Code: Global cline$ Global show_con = False Global cursor Global cursor_time = MilliSecs() Global cursor_speed= 250 Function Console() If KeyHit(15) Then show_con=1-show_con If show_con key=GetKey() If key>=32 And key<=255 Then cline$=cline$+Chr(key) ; Cursor anzeigen If MilliSecs()-cursor_time>cursor_speed cursor=1-cursor cursor_time=MilliSecs() EndIf If cursor x=StringWidth(cline$) Text x,0,"_" EndIf EndIf End Function Repeat Cls Console Flip Until KeyHit(1) End WOW, ein schöner blinkender Cursor ... fügen wir nun die Ausgabe der derzeit eingegebenen Zeichen hinzu: Code: Global cline$ Global show_con = False Global cursor Global cursor_time = MilliSecs() Global cursor_speed= 250 Function Console() If KeyHit(15) Then show_con=1-show_con If show_con key=GetKey() If key>=32 And key<=255 Then cline$=cline$+Chr(key) ; Cursor anzeigen If MilliSecs()-cursor_time>cursor_speed cursor=1-cursor cursor_time=MilliSecs() EndIf If cursor x=StringWidth(cline$) Text x,0,"_" EndIf Text 0,0,cline$,0,0 EndIf End Function Repeat Cls Console Flip Until KeyHit(1) End Nun könnt Ihr die Console ein und ausschalten, den eingegebenen Text anzeigen und auch noch einen lustig blinkenden Cursor anzeigen ... ... Morgen klären wir dann das Geheimnis der Backspace- und Returntaste, wie man den eingegebenen String verarbeitet und werden uns Beispiel anschauen wie so eine Console sinnvoll zu verwenden ist... stay t00ned. |
||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
![]() |
bruZard |
![]() Antworten mit Zitat ![]() |
---|---|---|
Teil II
Bisher kann man zwar alles eingeben was man möchte, man kann es jedoch weder editieren, noch die Eingabe bestätigen. Um das zu realisieren müssen wir die ASCII Codes vor 32 prüfen und dann die entsprechende Aktion ausführen. Kümmern wir uns zunächst um Backspace. Der ASCII Code für Backspace lautet 8, wir prüfen also ob dieser Code bei GetKey() angekommen ist und checken dann noch ob der String noch lang genug ist um ein Zeichen entfernen zu können: Code: If key=8 And (Len(cline$)-1)>=0 cline$=Left(cline$,Len(cline$)-1) Mit dieser Zeile tun wir folgendes: Wir prüfen zunächst ob die Tastatureingabe dem ASCII Code 8 entspricht, was ja die Backspace Taste ist, checken dann ob der bisher eingegebene Text noch einen Zeichenabzug verträgt und nehmen dann den linken Teil des Strings und schreiben ihn zurück. Weiter gehts mit der Return/Enter Taste. Wenn diese gedrückt wird, soll der String gelöscht werden, die Console soll sich schliessen und der eingegebene Text analysiert werden. Die Analyse erledigen wir durch ein Select ... Case Konstrukt, einen String sollte wohl jeder löschen können. Code: If key=13 show_con=0 ; Gleichheitszeichen suchen eq=Instr(cline$,"=") If eq ; Wir trennen den String am Gleichheitszeichen cmd$=Lower(Trim(Left(cline$,eq-1))) par$=Trim(Right(cline$,Len(cline$)-eq)) Select cmd$ ; Hier wird der String vor dem = analysiert End Select Else ; Es wurde ein String ohne = eingegeben Select Lower(cline$) ; Hier werden die Eingaben analysiert. End Select End If cline$="" End If Was haben wir jetzt hier. Zunächst einmal wird die Console nach Return geschlossen, das erledigt show_con=0. Dann schauen wir nach ob es sich um eine Wertzuweisung handelt indem wir nach einem Gleichheitszeichen suchen. Wurde eines entdeckt trennen wir den String in zwei Teile, genau am Gleichheitszeichen. Trim soll sicherstellen dass der String auch dann erkannt wird wenn der User vor und/oder nach dem Gleichheitszeichen ein Leerzeichen getippt hat. Mit Lower wandeln wir den Variablennamen in Kleinbuchstaben um, das erleichtert den Vergleich. Wurd kein Gleichheitszeichen gefunden, gehen wir davon aus dass der User einen einzelnen Befehl eingetippt hat. Beispielsweise quit um das Programm zu beenden. Damit das Programm quit auch erkennt muss es in das Select ... Case Konstrukt. Code: Select Lower(cline$) Case "quit" : End End Select Sehr einfach. Eine Variablenzuweisung ist ebenso simpel, so können wir z.B. die Blinkgeschwindigkeit des Cursors direkt in der Console ändern: Code: Select cmd$ case "cursorspeed" : cursor_speed=Int(par$) End Select Das war auch schon das ganze Geheimnis. Ihr könnt natürlich auch ein Leerzeichen anstatt dem Gleichheitszeichen als Trennung verwenden. Durch Erweiterungen können auch Parameterketten, welche durch Kommatas getrennt sind, verarbeitet werden. Für die meisten Anwendungen sollte dieser Code hier aber genügen. Zum Abschluss nocheinmal der komplette Code: Code: Global cline$ Global show_con = False Global cursor Global cursor_time = MilliSecs() Global cursor_speed= 250 Function Console() If KeyHit(15) Then show_con=1-show_con If show_con key=GetKey() If key>=32 And key<=255 Then cline$=cline$+Chr(key) ; Backspace If key=8 And (Len(cline$)-1)>=0 cline$=Left(cline$,Len(cline$)-1) ; Return If key=13 show_con=0 ; Gleichheitszeichen suchen eq=Instr(cline$,"=") If eq ; Wir trennen den String am Gleichheitszeichen cmd$=Lower(Trim(Left(cline$,eq-1))) par$=Trim(Right(cline$,Len(cline$)-eq)) Select cmd$ ; Hier wird der String vor dem = analysiert case "cursorspeed" : cursor_speed=Int(par$) End Select Else ; Es wurde ein String ohne = eingegeben Select Lower(cline$) ; Hier werden die Eingaben analysiert. case "quit" : End End Select End If cline$="" End If ; Cursor anzeigen If MilliSecs()-cursor_time>cursor_speed cursor=1-cursor cursor_time=MilliSecs() EndIf If cursor x=StringWidth(cline$) Text x,0,"_" EndIf Text 0,0,cline$,0,0 EndIf End Function Repeat Cls Console Flip Until KeyHit(1) End Viel Spass beim erweitern! |
||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
graythread |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Mh, sehr fein gemacht, nur sollteste den letzten Code entweder lauffähig machen, oder es nur bei der Funktion belassen (repeat...until weglassen). | ||
![]() |
bruZard |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmm, der Code läuft ... zudem sollte jemand, der ein Spiel mit Console schreiben will, in der Lage sein die paar Zeilen in ein Include auszulagern. | ||
PIV 2,4GHz - 1GB DDR 333 - ATI Radeon9600 - WinXP - DX9.0c - BMax 1.14 - B3D 1.91 - 1280x1024x32
User posted image |
![]() |
Mr.Keks |
![]() Antworten mit Zitat ![]() |
---|---|---|
Nett geschrieben ![]() ... Aber, he, kann es sein, dass du der totale Fan von Consolen bist? Sonst habe ich die noch so ziemlich keinem in der Community gesehen. Bei dir gibt es immer Consolen. Du hast ja vor längerer Zeit ja auch mal eine ins Codearchiv gepostet und so ![]() |
||
MrKeks.net |
@uzingLG |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Toll! Sehr nützlich!
Aber es hatte den selben Bug wie Timemill: man kann auch was eingeben, wenn man die Konsole geschlossen hat. Lösung: FlushKeys vor Funktionsende (nach endif) das hab ich aus dem neuesten timemill source |
||
![]() |
Triton |
![]() Antworten mit Zitat ![]() |
---|---|---|
Inarie hat Folgendes geschrieben: Nett geschrieben
![]() ... Aber, he, kann es sein, dass du der totale Fan von Consolen bist? Sonst habe ich die noch so ziemlich keinem in der Community gesehen. Bei dir gibt es immer Consolen. Du hast ja vor längerer Zeit ja auch mal eine ins Codearchiv gepostet und so ![]() Nun, ich benutze auch immer eine ![]() Nur veröffentliche ich nie was, wo das anwendung findet. :/ |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group