![]() |
AW: Skript-Engine integrieren
So,
habe mich jetzt in das PDF zu SE2 eingelesen, das "einbauen" ist mir allerdings nicht geglückt. Zwar bekomme ich keinerlei Fehlermeldungen, dafür aber auch nicht das was ich will. Wenn ich die Dokumentation richtig verstanden habe, brauche ich doch eine Unit die die Prozeduren registriert und den Quelltext der, welche die external-Aufrufe beinhaltet, in einer Konstanten enthält. Auf die sollte ich dann während der Ausführung zugreifen können, richtig? Mein Code:
Delphi-Quellcode:
Das hier wäre der Aufruf, der funktioniert jedoch:
unit Skripting;
interface uses AdSprites, Dialogs, murmel, SysUtils, uSE2Compiler, uSE2UnitCacheMngr, uSE2Errors, uSE2Reader, uSE2PEData, uSE2RunTime, uSE2RunAccess, uSE2UnitManager, uSE2Consts, Murmelspiel_Form1_CODE; procedure Prepare(); procedure ParseSkript(ASkript: String; AMurmel: TMurmel); procedure ZeigeNachricht(ANachricht: String); procedure Murmel_SetXSpeed(AXSpeed: double; AMurmel: TMurmel); procedure Murmel_SetYSpeed(AYSpeed: double; AMurmel: TMurmel); const // diese Variable mit dem Namen der Unit füllen C_UnitName = 'SkriptCommands'; // in diese Variable kommt der komplette Script-Quelltext C_UnitSource = 'unit SkriptCommands;'+#13#10+ #13#10+ 'interface'+#13#10+#13#10+ 'uses Murmel, Skripting;'+#13#10+#13#10+ 'procedure ZeigeNachricht(ANachricht: String); external;'+#13#10+ 'procedure Murmel_SetXSpeed(AXSpeed: double; AMurmel: TMurmel); external;'+#13#10+ 'procedure Murmel_SetYSpeed(AYSpeed: double; AMurmel: TMurmel); external;'+#13#10+#13#10+ 'implementation'+#13#10+#13#10+ 'end.'; var Compiler : TSE2Compiler; RunTime : TSE2RunTime; PEData : TSE2PE; implementation procedure Unit_GetSource(var Target: string); begin Target := C_UnitSource; end; procedure Unit_RegisterMethods(const Target: TSE2RunAccess); begin if Target.HasUnit(C_UnitName) then begin // hier die Funktions-Pointer setzen Target.Method['ZeigeNachricht[0]', C_UnitName] := @ZeigeNachricht; end; end; procedure RegisterUnit; var p : TSE2MethodUnit; begin p := TSE2MethodUnit.Create; p.DoRegisterMethods := Unit_RegisterMethods; p.DoGetUnitSource := Unit_GetSource; p.UnitName := C_UnitName; TSE2UnitManager.RegisterUnit(p); end; procedure ParseSkript(ASkript: String; AMurmel: TMurmel); begin //ShowMessage('Hallo'); //Das Parsen übernimmt nun die S(cript) E(ngine) 2 (http://www.delphipraxis.net/140590-scriptengine-ii-v-0-5-3-2-a-4.html) Compiler := TSE2Compiler.Create; try PEData := Compiler.Compile(ASkript); if PEData <> nil then begin RunTime := TSE2RunTime.Create; try RunTime.AppCode := PEData; RunTime.Initialize; Pause:=true; //Spiel während Skript-Ausführung anhalten RunTime.Run; Pause:=false; RunTime.Finalize; RunTime.AppCode := nil; finally RunTime.Free; end; end; except ShowMessage('Beim Ausführen des Skripts ist ein Fehler aufgetreten!'); end; PEData.Free; end; procedure Murmel_SetXSpeed(AXSpeed: Double; AMurmel: TMurmel); begin AMurmel.XSpeed := AXSpeed; end; procedure Murmel_SetYSpeed(AYSpeed: Double; AMurmel: TMurmel); begin AMurmel.YSpeed := AYSpeed; end; procedure ZeigeNachricht(ANachricht: string); begin ShowMessage(ANachricht); end; initialization RegisterUnit; end.
Delphi-Quellcode:
Vielleicht habe ich auch einfach das Konzept dahinter noch nicht ganz verstanden... :(
Skripting.ParseSkript(Sprite.Skript, self);
Ich hoffe, jemand versteht mich. Vielen Dank! Viele Grüße, I love Delphi! EDIT: Als Skript habe ich folgendes verwendet:
Delphi-Quellcode:
program MyScriptProject;
uses SkriptCommands; begin ZeigeNachricht('Hallo'); end. |
AW: Skript-Engine integrieren
Hi!
So auf die schnelle ohne Delphi kann ich dir auch nicht helfen. Aber ich habs so gemacht, dass ich erst ne ganz kleine Unit geschrieben habe und die dann getestet habe, ob alles funktioniert und erst bei erfolg hab ich die Unit erweitert. Vielleicht machst du das einfach nochmal von vorne und probierst nach jeder neuen Methode aus, ob noch alles funktioniert, dann kannst du den Fehler eingrenzen. ODER: du schmeißt mal den Debugger an und steppst durch dein Spiel um zu schauen ob das Script überhaupt ausgeführt wird oder was los ist. mfg Florian |
AW: Skript-Engine integrieren
Hey,
also ausgeführt müsste es werden, das habe ich mit einem beispielhaften Aufruf von ShowMessage() in der Prozedure ParseSkript() getestet. Leider wüsste ich gar nicht, inwiefern ich die Klasse noch reduzieren sollte: Ich habe lediglich die drei Funktionen/Prozeduren Murmel_SetYSpeed, Murmel_SetXSpeed und ZeigeNachricht() hinzugefügt. Wenn ich diese jedoch nicht mehr habe, dann kann ich ja die Funktionstüchtigkeit nicht mehr prüfen! Mist... Viele Grüße, I love Delphi! |
AW: Skript-Engine integrieren
Ok, ich versuche mal eine Schnell-Anleitung zu geben, wie man das ganze am schnellsten macht (nicht abschrecken von den paar Punkten - habe versucht es möglich genau zu machen.
Die neuen Units, die du gerade erstellt hast, solltest du nicht mehr groß erweitert. Die sind nur dafür da, um die Script-Engine mit deinen Methoden usw. zu füllen. Jetzt baue ich dein Beispiel-Script nach, wie es eigentlich funktionieren sollte (hab gerade kein Delphi zur Hand, daher ist alles nur ausm Kopf heraus geschrieben) Erstelle in deinem Delphi-Projekt eine neue Unit und schreibe folgenden Quelltext hinein:
Delphi-Quellcode:
Folgende Punkte sind im PDF für dich noch wichtig:
unit [was auch immer]
interface procedure RunScript(const ScriptSource: string); implementation uses uSE2Compiler, uSE2RunTime, uSE2PEData; procedure RunScript(const ScriptSource: string); var Compiler: TSE2Compiler; PEData : TSE2PE; RunTime : TSE2RunTime; begin Compiler := TSE2Compiler.Create; try // Compilieren PEData := Compiler.Compile(ASkript); if PEData <> nil then begin // Compilieren erfolgreich - PEData muss nicht manuell // freigegeben werden, da die RunTime das für uns erledigt. // Daher gibt es hier für PEData keinen try-finally-Block RunTime := TSE2RunTime.Create; try RunTime.AppCode := PEData; // RunTime initialisieren RunTime.Initialize; // ausführen RunTime.Run; // aufräumen RunTime.Finalize; finally // wie gesagt, PEData wird hier mit freigegeben RunTime.Free; end; end; finally Compiler.Free; end; end; end.
Was ich auch noch erwähnen wollte: die SEII ist nicht dazu optimiert, ständig den Quelltext zu kompilieren und diesen dann direkt auszuführen. Die SEII ist für das Ausführen von Scripten extrem optimiert (schneller als Pascal-Script, Sysygy, Delphi++, etc...). Daher wäre es sinnvoll, dein Script einmal durch den Compiler zu jagen und dir das TSE2PE-Objekt zu merken. Aber das nur so am Rande, jetzt schau ma erstmal, dass dein Basis-Ding funktioniert ;-) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:59 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz