Ablauf-Script-Engine
Übersicht

![]() |
JolinahBetreff: Ablauf-Script-Engine |
![]() Antworten mit Zitat ![]() |
---|---|---|
Habe eine kleine Ablauf-Script-Engine programmiert. Ok, das klingt komisch ![]() Für jeden Objekttype kann man eigene Scriptbefehle definieren. Das ganze besteht aus zwei Types: Script und Scriptable. Der Script-Type dient zum erstellen, laden und speichern der Scripte sowie die Ausführung, wobei die Ausführung intern geregelt wird über den Scriptable-Type. Erstellen kann man die Scripte natürlich auch mit nem Text-Editor. Der Scriptable-Type stellt ein Objekt dar welches mit dem Script verbunden ist. Dieser Type ist also eine Grundlage und ist deshalb Abstrakt, es muss ein eigener Type erstellt werden der davon ableitet. Hier die wichtigsten Methoden: Type Script - Create(Name:String) 'Um ein Script direkt im Speicher zu erstellen - Open(filename:String) 'Laden von einer Datei - Save(filename:String) 'Speichern - AddLine(line:String) 'Zeile hinzufügen (sinnvoll bei Create) Type Scriptable - Update() 'Aktualisiert das Ganze (inkl. Skript-Abarbeitung) - SetScript(s:Script) 'Festlegen welches Script das Objekt benutzt - SetAction(a:Byte) 'Gegenwärtige Aktion des Objekts festlegen - Start() 'Nur wenn Start aufgerufen wurde macht Update auch was. - Stop() 'Nach dem Stop macht Update nichts mehr (Anfangszustand). - OnCommand(cmd:String, args:String[]) Eventhandler für Scriptbefehle - OnScriptEnd() Eventhandler (Scriptende erreicht) Edit: Hier noch als kleines Demo, für die die keine Lust haben den Code selber zusammen zu bauen ![]() http://zehr.de/blitz3d/test.zip Und hier der Code: Code: [AUSKLAPPEN] Const ACTION_NONE:Byte = 0
'Script-Type --------------------------------------------------- 'Dieser Type wird zum Laden, Speichern oder direkt erstellen benutzt, 'Die Run Methode wird eigentlich nur Intern benutzt und vom Scriptable Type angesteuert. Type Script Field count:Int Field lines:String[] Field Name:String 'Create - Erstellt einen Script-Type und gibt ihn zurück Function Create:Script(name:String) Local s:Script = New Script s.Name = name Return s End Function 'Open - liest eine Datei als Script ein Function Open:Script(filename:String) Local file:TStream = ReadStream(filename) If file = Null Then Return Null Local line:String Local s:Script = New Script While Not Eof(file) line = ReadLine(file) If line <> "" Then If Left(line,1) <> "#" And Left(line,2) <> "//" s.AddLine(line) Else If Lower(Left(line, 9)) = "# script:" s.Name = Mid(line, 11) EndIf EndIf EndIf Wend CloseStream(file) Return s End Function 'Save - Speichert das Script in eine Datei Method Save(filename:String) Local file:TStream = WriteStream(filename) If file = Null Then Return WriteLine(file, "# Script: " + Name) For Local s:String = EachIn lines WriteLine(file, s) Next CloseStream(file) End Method 'AddLine - fügt zu dem Script eine Zeile hinzu Method AddLine(line:String) lines = lines[..count + 1] lines[count] = line count :+ 1 End Method 'SetName - Name des Scripts setzen, zur Identifizierung unter Umständen Method SetName(name:String) Self.Name = name End Method 'GetName - Name des Scripts abrufen Method GetName:String() Return Name End Method 'Run - Ausführen des Scripts (Interaktionsobjekt übergeben) Method Run(Obj:Scriptable = Null) If lines = Null Then Return If Obj = Null Then Return If Obj.CurrentCmd = -1 Or Obj.CurrentCmd >= lines.Length Then Return Local ms:Int = MilliSecs() If ms < Obj.NextCmd Then Return Local args:String[] = Split(lines[Obj.CurrentCmd]) Obj.CurrentCmd :+ 1 args[0] = Upper(args[0]) Select args[0] Case "WAIT" If args.Length > 1 Try Obj.NextCmd = ms + Int(args[1]) Catch ex:Object Obj.NextCmd = ms + 100 End Try EndIf Case "END" Obj.CurrentCmd = 0 Obj.OnScriptEnd() Default If args.Length > 1 Then Obj.OnCommand(args[0], args[1..]) Else Obj.OnCommand(args[0], Null) EndIf End Select End Method End Type 'Scriptable-Type --------------------------------------------------- 'Stellt ein Objekt welches mit einem Script verknüpft ist dar. Type Scriptable Abstract Field Running:Byte Field CurrentCmd:Int Field NextCmd:Int Field CurrentAction:Byte Field Script:Script 'Update - Führt das Script aus (Nur wenn gerade sonst keine Aktion läuft) Method Update() If CurrentAction = ACTION_NONE And Running And Script <> Null Then Script.Run(Self) End Method 'SetScript - Setzt das aktuelle Script Method SetScript(s:Script) Script = s End Method 'SetAction - Setzt die Aktuelle Aktion Method SetAction(action:Byte) CurrentAction = action End Method 'Start - Startet die Ausführung des Scripts Method Start() Running = True CurrentCmd = 0 End Method 'Stop - Stoppt die Ausführung des Scripts Method Stop() Running = False End Method 'OnCommand - Eventhandler der aufgerufen wird wenn vom Script ein Befehl abgearbeitet wird Method OnCommand(cmd:String, args:String[]) End Method 'OnScriptEnd - Eventhandler der beim Scriptende aufgerufen wird Method OnScriptEnd() End Method End Type 'Hilfs-Funktionen ---------------------------------------------------- 'Trennt einen String in mehrere Substrings und gibt ein String Array zurück (Trennzeichen kann angegeben werden) Function Split:String[](str:String, char:String = " ") Local ret:String[] = New String[1] Local length:Int = 1 Local oldpos:Int = 0 Local pos:Int = 0 Local trenn:Byte = Len(char) pos = Instr(str, char) If pos > 0 ret[0] = Left(str, pos-1) While pos > 0 oldpos = pos pos = Instr(str, char, oldpos+trenn) ret = ret[..length + 1] If (pos > oldpos) ret[length] = Mid(str, oldpos + trenn, pos - (oldpos + trenn)) Else ret[length] = Mid(str, oldpos + trenn) EndIf length :+ 1 Wend Else ret[0] = str EndIf Return ret End Function 'Fügt ein String Array zu einem String zusammen mit dem angegebenen Trennzeichen. Function Concat:String(str:String[], char:String = " ") Local ret:String = "" For Local i = 0 To str.length - 1 ret :+ str[i] If i < str.length - 1 Then ret :+ char Next Return ret End Function Nachträglich noch ein Beispiel: Code: [AUSKLAPPEN] Strict
Include "TScript.bmx" 'Aktionen Const ACTION_MOVE:Byte = 1 'Objekt welches Scriptable erweitert Type Test Extends Scriptable Field x, y, tx, ty 'tx, ty = Ziel-Position (für Move) Field speed Method New() 'Standardspeed speed = 2 End Method Method Update() 'Sorgt für den Scriptablauf Super.Update() 'Die Methoden OnCommand bzw. OnScriptEnd werden intern aufgerufen 'Nach dem Update müsste also die aktuelle Aktion gespeichert sein 'Aktion prüfen Select CurrentAction 'Bei MOVE auf das Ziel bewegen Case ACTION_MOVE If x < tx x :+ speed Else If x > tx x :- speed EndIf If y < ty y :+ speed Else If y > ty y :- speed EndIf 'Beim Ziel angekommen Aktion wieder auf nichts setzen, 'so dass der nächste Scriptbefehl abgearbeitet wird. If x = tx And y = ty Then SetAction(ACTION_NONE) End Select End Method 'Zeichnen Method Draw() DrawRect x, y, 20, 20 End Method 'Eventhandler wird aufgerufen wenn ein Befehl abgearbeitet wurde 'cmd = Befehl in Uppercase 'args = Argumente des Befehls als String Array Method OnCommand(cmd:String, args:String[]) Select cmd 'Bei dem Setspeed Befehl den speed setzen auf das erste Argument Case "SETSPEED" speed = Int(args[0]) 'Bei Move das Ziel setzen (1. und 2. Argument) 'Da diese Tätigkeit etwas dauern kann muss hier eine Aktion 'ungleich 0 gesetzt werden (ACTION_NONE = 0) Case "MOVE" tx = x + Int(args[0]) ty = y + Int(args[1]) SetAction(ACTION_MOVE) End Select End Method 'Wird aufgerufen wenn das Script beim END Befehl angelangt ist. 'Ohne den Stop() Befehl läuft das Script als Loop Method OnScriptEnd() Print "Durchlauf abgeschlossen" 'Stop() End Method End Type Graphics 800, 600, 0 'Scripts laden Local s:Script = Script.Open("Test.txt") Local s2:Script = Script.Open("Test2.txt") 'Liste erstellen wo die Scriptable Objekte reinkommen Local list:TList = New TList 'Erstes Scriptable Objekt Local t:Test = New Test t.SetScript(s) t.x = 100 t.y = 100 t.Start() 'Zweites Scriptable Objekt Local t2:Test = New Test t2.SetScript(s2) t2.x = 100 t2.y = 400 t2.Start() 'Der Liste hinzufügen list.AddLast(t) list.AddLast(t2) 'Hauptschleife Repeat Cls 'Alle Objekte in der Liste durchgehen und aktualisieren, Zeichnen For Local test:Test = EachIn list test.Update() test.Draw() Next Flip FlushMem Until KeyHit(KEY_ESCAPE) EndGraphics t = Null t2 = Null list = Null s = Null FlushMem End Und die zwei Scripts: test.txt Code: [AUSKLAPPEN] # Script: Test
SETSPEED 10 MOVE 100 0 WAIT 500 MOVE 0 100 WAIT 500 MOVE -100 0 WAIT 500 MOVE 0 -100 WAIT 500 MOVE 100 100 WAIT 500 MOVE -100 0 WAIT 500 MOVE 100 -100 WAIT 500 END test2.txt Code: [AUSKLAPPEN] # Script: Test2
MOVE 100 0 WAIT 500 MOVE -100 100 WAIT 500 MOVE 100 0 WAIT 500 MOVE -100 -100 WAIT 500 MOVE 200 0 WAIT 500 END Ich weiss dass es nichts besonderes ist, aber vielleicht kanns ja jemand brauchen ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group