Tja was soll ich viel sagen.
Es ist kein Rechtschreibfehler, Shaddow tatsächlich mit 2D. Ich hatte mal n richtig gutes Intro, wo man gut erkennen konnte, warum, aber das ist wohl bei der letzten Festplattensäuberung hops gegangen. Mal sehen, wann ich Zeit und Muße habe, ein neues zu machen.
hier nun aber will ich euch die ShaddowEngine vorstellen.
Die Engine ist bisher etwas für Leute, die etwas Ahnung von OGL haben. Sie stellt die Progr[/delphi]ammierumgebung dar, sodass ein Programmierer sich nicht mehr um nervige und zeitaufwenige Dinge, wie HandleEvents, Initalizierung und noch so einiges kümmern muss.
Die Engine wird simpler weise in das momentane Projekt eingebunden und als
Delphi-Quelltext
deklariert.
Danach wird die Engine im OnCreateEreignis des Forms per
Delphi-Quelltext
1: 2:
| Engine := TEngine.Create(Form1,Form1.Handle); Engine.SetupGL(R,G,B,A); |
erstellt.
Da ich Euch hier gerade die Windowsversion dieser Engine vorstelle, werden im Constructor das Fenster und der Handle angebeben. Der vorteil des Handles ist, dass ihr mit hilfe dieses handles auch innerhalb von Panels in einem Fenster zeichnen könnt und nicht immer das ganze Fenster rendern müsst.
Dazu gibt es auch eine SDLVersion, die aber derzeit in der Überarbeitung ist, und dementsprechend nicht mit WindowsForms sondern mit SDLFenstern arbeitet.
R,G,B und A stellen die Standartwerte dar, mit denen der Farbbuffer nach der Leerung gefüllt wird. Das heisst für alle NichtOGLer, dass wenn ihr alles löscht, das Form genau die hier angegebene Farbe bekommt.
Ihr könnt nun im OnCreate noch manuell einige Einstellungen treffen, wie Effekte initalisieren usw., aber darauf gehe ich an späterer Stelle noch einmal detailierter ein.
Wichtig ist noch, dass ihr im OnResizeEvent des Form den Code:
Delphi-Quelltext
und im OnDestroyEvent des Forms den Code:
Delphi-Quelltext
einfügt.
Ersteres sorgt dafür, dass auch bei der Skalierung des Fensters nichts schief geht und letzteres löscht dann fein die Engine.
Tja was soll man sagen. Das ist die Engine ^^
Nun kommt aber das eigentliche Thema, naemlich: "Wie stelle ich nun etwas dar in meiner Engine??"
Das erkläre ich euch jetzt:
Alles Folgende gehoert ins OnIdleEvent der Application. (Anm: Die einfachste Methode der Realisierung ist hierbei: Unter Komponenten die Kategorie "Zusätzlich" öffnen, die Komponente "ApplicationEvents" auf euer Form ziehen und dann das Ereignis OnIdle auswählen. Idle heisst übersetzt Leerlauf. Wenn das Programm also nix zu tun hat, dann führt es diese Prozedur aus.
Innerhalb des IdleEvents müsst ihr nun Engine.DoStart aufrufen, um sie in Gang zu setzen, und am Ende Engine.DoEnd, um sie zu stoppen.
Euer Code könnte also wie folgt aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean); begin with Engine do begin DoStart;
DoEnd; Done:=FALSE; end; end; |
Zwischen DoStart und DoEnd können nun alle beliebigen Rendermethoden, um Objekte darzustellen. Wer nun kein OGL kann, wird auf vorgefertigte Objekte zurueckgreifen müssen. Diese Unit allerdings befindet sich noch in einem Entwicklungsstadium, wird aber bald nachgereicht. Bisher können aber auch NichtOGLler schon nette ParticleEffekte erschaffen, ohne nur einen Hauch Ahnung von OGL.
Doch ersteinmal weiter zu den Features der Engine.
DoEnd ist eine Funktion, die Euch die DrawTime also die Zeit, die sie brauchte, um die Szene zu render, in Millisekunden zurück gibt. Dieser Wert ist gerade für Timebased Movement sehr wichtig und deshalb hier sehr nützlich.
Sobald ihr DoEnd aufruft, wird automatisch ein FPSGraph gezeichnet. Die Position und Größe dieses Graphen könnt ihr durch Manipulation der Constanten in der Globals.pas verändern.
Wenn ihr den Graphen nicht sehen wollt, reicht ein einfaches Engine.SetFPSGraph:=FALSE; und schon wird er nicht gezeichnet.
Nun hier mal noch alle Funktionen der Engine im Überblick:
- Create mit Form- und HandleAngabe
- SetupGl mit den StandartFarbwerten
- InitTextures, die zur Initalisierung von StandartTexturen genutzt werden kann.
- Enable, die die Funktion glEnable mit einer Constanten ala GL_DEPTH_TEST usw. aufruft (für OGLler)
- Disable, siehe Enable nur deaktiviert es nun die Constante
- Resize, um die Fenstergröße anzupassen
- DoStart, initalisiert die StartZeit in Millisekunden und löscht den Farb-, Stencil- und Tiefenbuffer
- DoDraw, wird, sobald die DrawObjekte fertig sind, zum zeichnen der StandartObjekte genutzt
- DoEnd, zeichnet falls nicht deaktiviert den FPSGraph und gibt aktuelle FPSZahl und ParticleZahl in der Caption aus
- DoFullscreen, wird in den Fullscreenmode wechseln. Das ist nur wenig Code und die Funktion nehm ich morgen in Angriff
- DoScreenShot, ist auch noch nicht fertig, wird aber bald soweit sein. Erstellt einen Screenshot vom Handle
- OrthoStart, wechselt in den Orthographischen (2d) Modus, um Objekte nicht perspektivisch Verzerrt auszugeben. Diese Prozedur wird automatisch aufgerufen, bevor der FPSGraph gezeichnet wird.
- OrthoEnd, wechselt wieder zurück in den Perspektivischen (3d) Modus. Diese Prozedur wird automatisch nach dem FPSGraphZeichnen aufgerufen
- DrawFPSGraph, ist eine interne, private Funktion, die vom DoEnd aufgerufen wird.
- SetFPSGraph, enabled oder disabled den FPSGraph über Booleanwerte
- CalculateEffektNumParticles, errechnet, sofern erstellt, die Summe aller gerenderten Particle der ParticleEffekte
- Destroy, deaktiviert alle Schikanen (, auf die ich gleich noch eingehe) und gibt allen Speicher wieder frei.
BugTracker:
-------------
Nun noch die restlichen Features in Zusammenhang mit der Engine.
Mit der Erstellung der Engine wird ein BugTracker erstellt, der die ganze Zeit mitloggt. Am Ende seht ihr genau, wo die Fehler auftraten.
Dieser BugTracker wird auch automatisch an die eingebundenen Units übergeben und loggt dort weiter mit.
Effekt, Container, Particle:
------------------------------
Diese 3 Units beinhalten alles nötige für die ParticleEffekte. Diese Effekte werden folgendermaßen, wie oben schon angedeutet, im OnCreateEvent des Forms nach der Initalisierung der Engine erstellt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28:
| procedure TForm1.FormCreate(Sender: TObject); begin Engine := TEngine.Create(Form1,Form1.Handle); Engine.SetupGL(0,0,0,0);
with Engine do begin SetLength(Effekte,1); Effekte[0] := TEffekt.Create('Feuer',1000,1500,50,30,'spark.bmp','Feuer',TextureManager,BugTracker);
with Effekte[0] do begin SetColor(1,0.7,0.25,FALSE,TRUE,TRUE); SetStartPosition(-0.5,0,0); SetPosition(10,10,0,0.1,0.1,0,TRUE,TRUE,TRUE);
SetParticleDirection(3,3,3,0,0,0,TRUE,TRUE,TRUE); SetParticleSpeed(1.5); SetLineSettings(0,TRUE);
SetAngles(0,360); SetTextureSize(CreateVector( 0.07,-0.07,0), CreateVector(-0.07,-0.07,0), CreateVector(-0.07, 0.07,0), CreateVector( 0.07, 0.07,0)); end; end; end; |
Effekte ist ein dynamisches Array, ihr müsst also vorher die Länge festlegen. Danach erschafft ihr den Effekt. Die Parameter werden ja von der DelphiHilfe erklaert. Dennoch hier noch einmal eine kurze Erklaerung:
1. Parameter: NName: Name des Effekts
2. Parameter: NumParticles: Anzahl der Particle für diesen Effekt
3. Parameter: NStartLiveSpan: Lebenszeit der Particle in Millisekunden
4. Parameter: NEmissionRate: Delayzeit zwischen 2 Emissionen in Millisekunden
5. Parameter: NParticlesPerEmission: Anzahl der bei der Emission ausgestoßenen Particle
6. Parameter: NTexturePath: Pfad der Textur, mit der die Particle dargestellt werden sollen
7. Parameter: NTextureName: Name der Textur
8. Parameter: NTextureManager: TexturenManager, der von der Engine erstellt wird. Zugriff also Engine.TextureManager;
optionaler 9. Parameter: NBugTracker: BugTracker, der von der Engine erstellt wird. Zugriff also Engine.BugTracker;
Ich empfehle hierbei den BugTracker unbedingt mit zu übergeben.
Nun die restlichen Funktionen sollten einfacher zu verstehen sein.
SetColor gibt mit den ersten 3 Werten den RGBFarbCode an und mit den letzten 3, ob die Farbe Randommäßig berechnet werden soll, oder nicht. Dazu später mehr.
SetStartPosition gibt die StartPosition als Vektor vom 0Punkt aus an. Er ist also der Ortsvektor des Effektes.
SetPosition gibt die EmissionsPosition der Particle an. Diese ist nun relativ zur bei SetStartPosition angegebenen Position. Mit den letzten 3 Parametern wird wieder die Randomerrechnung aktiviert.
SetParticleDirection gibt die Richtung an, in die die Particle emittiert werden. Diese Richtung wird allerdings auch, falls angebenen durch SetAngle manipuliert. Mit den letzten 3 Parametern wird wieder die Randomerrechnung aktiviert.
SetParticleSpeed gibt die Geschwindigkeit an, mit der sich die emittierten Particle bewegen.
SetLineSettings gibt an, wie der Emissionspunkt aussieht. 0 steht für einen Punkt, und jeder Wert über 0 für eine Linie, an der entlang emittiert wird. Der zweite Parameter errechnet wieder die RandomEmission.
SetAngles gibt den StartWinkel an und den Endwinkel. Nur ZWISCHEN diesen beiden Winkeln wird emittiert.
SetTextureSize gibt die Größe der Textur an, also damit auch die ParticleGröße.
Nun das wars eigentlich. Nicht alle Funktionen sind zwingend nötig.
Manche wie SetAngles und SetLineSettions können weggelassen werden. Probiert die Funktionen einfach mal aus.
Heraus kommt bei diesen Einstellung folgendes Resultat:
TextureManager:
-----------------
Dieser Manager wird automatisch von der Engine.pas und der Effect.pas verwendet, und lädt alle notwendigen Texturen. Logisch oder ^^ er kann aber auch manuell angesteuert werden über Engine.TextureManager
FontManager:
--------------
Dieser Manager wird von der Engine automatisch aufgerufen und generiert die Font für den FPSGraphen. Er kann aber auch manuell angesteuert werden. Über Engine.FontManager
Ich habe ihm noch ein sehr nützliches Feature eingebaut. Normalerweise verwendet man, um Weite und Höhe von Strings herauszubekommen die TextWidth/Height oder StringWidth/Height von Windows. Bei OSunabhaengiger Programmierung allerdings darf man auf die nicht zurückgreifen, also habe ich mir kurzerhand ne eigene Funktion zur berechnung der Weite und Höhe von Strings in Pixeln geschrieben.
Die könnt ihr durch den FontManager auch aufrufen.
Globals:
----------
Hier sind alle globalen Variablen gespeichert. Seht ruhig mal rein, ihr könnt bisher eigentlich alle verändern. Bei manchen zb. FormHeight und FontWidth müsst ihr es sogar
"protected" Constanten werden dann später als solche kenntlich gemacht.
Tools:
--------
Tja meine Toolsammlung für dieses Projekt.
Übersicht:
- Funktionen des BillBoardSystems für die Effekt.pas
- CreateVector
- PointToPointDistance
- SubtractVector
- IntToStr
- FloatToStr
- GradToBogen // Gradmaß zu Bogenmaß, nenn ich vllt mal in DegToRad um ^^
- CalculateFontSizes
So es gewünscht wird, gibts hier auch noch ne Doku zu allen Funktionen der einzelnen UnterUnits, bisher habe ich ja nur die der Engine erklärt.
Aber nu mach ich erstma Schluss. Lest es und geniesst es ^^
Denn erst Morgen gibs für Euch das erste Release des Projektes zum Austesten