Irrlicht - from Noob to Pro: Klassen in Irrlicht verwenden
Voraussetzungen
[Bearbeiten]In diesem Teil des Buches geht es darum, eine komplette Szene in Irrlicht zu erstellen und den Würfel aus dem vorhergehenden Teil des Buches in eine eigene Klasse zu packen. Dieser Würfel muss dann abgeleitet werden von Irrlichts ISceneNode-Klasse, um Ihn in einen Szene-Manager von Irrlicht registrieren zu können. Sie sollten verstanden haben
- wie 3D-Objekte aufgebaut sind,
- wie die Farbwerte von Vertices angegeben werden,
- mehrere indexdefinierte Dreiecke dargestellt werden,
- wie eine Zeitmessung in das Programm eingebaut wird und
- wie man ein Objekt über seine Matrix dreht.
Falls Sie sich in diesen Bereichen noch nicht sicher sind, dann werfen Sie doch einen Blick in den vorhergehenden Teil des Buches. Wenn Sie sich in der Definition von Klassen in C++ nicht sicher sind, so empfehle ich Ihnen einen Blick auf das Kapitel "Klassen" im Buch C++-Programmierung.
Die Klasse CWuerfel erstellen
[Bearbeiten]Wir wollen hier nun für den Würfel aus dem vorhergehenden Kapitel eine Klasse erstellen, welche sich CWuerfel nennt. Dazu benötigen wir ersteinmal 2 neue Dateien, welche wir in unser Projekt neben der Quellcodedatei main.cpp einfügen.
Benötigte Dateien
[Bearbeiten]Wir benötigen für unsere Klasse
- eine neue Header-Datei, gespeichert unter CWuerfel.h sowie
- eine neue Quellcode-Datei, gespeichert unter CWuerfel.cpp.
Um diese zu erstellen, klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den OrdnerHeaderdateien,dann auf Hinzufügen und dann auf Neues Element. In den nachfolgenden Dialog fügen Sie die neue Headerdatei CWuerfel.h hinzu. Verfahren Sie anschließend im Projektmappen-Explorer mit dem Ordner Quellcodedateien entsprechend, um die Quellcodedatei CWuerfel.cpp hinzuzufügen.
Einfügen eines Include-Guard
[Bearbeiten]Bevor Sie nun beginnen, den Code einzugeben, sollten Sie einen sog. "Include-Guard" einfügen, welcher die doppelte Einbindung einer Header-Datei verhindert, da dies sonst zu einer Fehlermeldung führt. Öffnen Sie nun die Headerdatei CWuerfel.h und fügen Sie den Guard mit folgendem Code ein:
//"Include-Guard"
#ifndef __CWuerfel_H
#define __CWuerfel_H
#endif
|
Wenn Sie nun den Quellcode eingeben, so fügen Sie Ihn zwischen
#define __CWuerfel_H
und
#endif
ein. Somit kann die Deklaration der CWuerfel-Klasse nur einmal eingebunden werden.
Einbinden von Irrlicht
[Bearbeiten]Da wir für die Deklaration Klassen und Datentypen aus Irrlicht verwenden, müssen wir dieses auch einbinden. Dies tun wir in der Header-Datei mit folgendem Code :
//Einbinden der Header-Datei von Irrlicht
#include <Irrlicht.h>
//Einbinden der Namespaces
using namespace irr;
using namespace core;
using namespace video;
|
Ableiten der Klasse
[Bearbeiten]Da die Würfel-Klasse in einem ISceneManager verwendet werden soll, müssen wir sie aus der Irrlicht-eigenen Klasse ISceneNode ableiten, um Sie später zum Rendern im Szene-Manager von Irrlicht registrieren zu können. Erstellen Sie in der Header-Datei CWuerfel.h nun folgendes Grundgerüst der Würfel-Klasse :
class CWuerfel : public scene::ISceneNode
{
public:
//Konstruktor
CWuerfel::CWuerfel(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id);
protected:
};
|
Der Konstruktor der Klasse wird uns durch die Ableitung von ISceneNode vorgegeben und dient der Kommunikation zwischen Irrlicht und unserer Würfel-Klasse. Die Parameter haben folgende Bedeutung :
- scene::ISceneNode* parent definiert, ob die Node einer "Eltern-Node" folgen soll. Falls dies nicht der Fall ist, so verwendet man die Root-Node des Szene-Managers, wodurch sie keine Parent-Node zugewiesen bekommt.
- scene::ISceneManager* mgr definiert den Szene-Manager, in welchem die Node registriert werden soll.
- s32 id bestimmt die ID-Nummer der Node, um Sie eindeutig identifizieren zu können. Da wir momentan nur einen Würfel verwenden, können wir z.B. die "1" verwenden.
In der Quellcode-Datei CWuerfel.cpp fügen Sie nun folgendes Grundgerüst ein :
//Einbinden der Header-Datei von Irrlicht
#include <Irrlicht.h>
//Einbinden der Headerdatei der Würfel-Klasse
#include "CWuerfel.h"
//Einbinden der Namespaces
using namespace irr;
using namespace core;
using namespace video;
//!Der Konstruktor für die Würfel - Klasse
CWuerfel::CWuerfel(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id)
: scene::ISceneNode(parent, mgr, id)
{
}
|
Kommunikation mit Irrlicht
[Bearbeiten]Um nun den Datenaustausch mit Irrlicht zu gewährleisten, müssen wir noch ein paar Prozeduren einbauen, welche die korrekte Darstellung in der Engine ermöglichen, da Irrlicht seine zu zeichnenden Objekte ("Nodes") auf ein paar Eigenschaften abfragen will. Diese sind folgende ...
Registrierung der Node
[Bearbeiten]Um überhaupt eine Einbindung zu erreichen, muss die Node im Szene-Manager registriert werden. Dieser prüft, ob die Node als "sichtbar" markiert ist und fügt diese zu den zu zeichnenden Nodes hinzu. Dies geschieht durch folgenden Code (in der Quellcode-Datei CWuerfel.cpp) :
//!Registriert den Würfel im Szene-Manager von Irrlicht zum Rendern
void CWuerfel::OnRegisterSceneNode()
{
if (IsVisible) //Falls sichtbar ...
SceneManager->registerNodeForRendering(this); //zum Zeichnen registrieren
//Aufruf des Registriervorgangs
ISceneNode::OnRegisterSceneNode();
}
|
In der Header-Datei bindet man diese Prozedur dann wie folgt ein :
virtual void OnRegisterSceneNode(); //Registrieren des Würfels im Szene-Manager
Anzahl der verwendeten Materialien
[Bearbeiten]Da Irrlicht wissen will, wieviel Materialien der Würfel verwendet, werden wir diesem mit folgendem Code gerecht :
//!Gibt die Anzahl der von uns verwendeten Materialien zurück
u32 CWuerfel::getMaterialCount() const
{
return 1;
}
|
Da wir nur ein Material haben, können wir den Wert "1" zurückgeben. In der Header-Datei wird dies definiert durch :
virtual u32 getMaterialCount() const; //Anzahl der Materialien übergeben
Übergeben eines Materials
[Bearbeiten]Da Irrlicht zum Rendern die / das Material(ien) abruft, verlangt die ISceneNode-Klasse die direkte Übergabe eines Materials in Form von
//Gibt ein bestimmtes Material zurück
video::SMaterial& CWuerfel::getMaterial(u32 i)
{
return mat;
}
|
Dies wird in der Header-Datei Deklariert durch
virtual video::SMaterial& getMaterial(u32 i); //Ein bestimmtes Material übergeben
. Des weiteren können wir im protected-Abschnitt der Header-Datei ein Material mit
SMaterial mat;
deklarieren.
Übergeben der Bounding-Box
[Bearbeiten]In Irrlicht werden Bounding-Boxen zur Kollisionserkennung sowie zum Culling verwendet. Da dies eine Variable erfordert definieren wir diese mit
core::aabbox3d<f32> ABox;
In der Header-Datei müssen wir nun die Deklaration der Funktion angeben mit
virtual const core::aabbox3d<f32>& getBoundingBox() const; //Die Bounding-Box übergeben
In der Quellcodedatei sieht diese Funktion dann so aus :
//!Gibt unsere Bounding-Box an Irrlicht zurück
const core::aabbox3d<f32>& CWuerfel::getBoundingBox() const
{
return ABox;
}
|
Programmieren des Rendervorgangs
[Bearbeiten]Da wir nun Irrlicht die erforderlichen Daten zum Zeichnen übergeben haben, überschreiben wir hier einfach den Rendervorgang der ISceneNode-Klasse mit unserem eigenen Code, da wir unseren Würfel selbst zeichnen wollen. Deshalb deklarieren wir in der Header-Datei
virtual void render(); //Zum Zeichnen des Würfels
Nun geht es daran, den Rendervorgang in der Quellcode-Datei zu programmieren. Da wir aber bisher nur das Material deklariert haben, benötigen wir im protected-Abschnitt unserer Klasse in der Header-Datei noch die Arrays für die Indicies und die Vertices. Diese erstellen wir mit
S3DVertex cwVertices[8]; //Das Array vom Typ S3DVertex zum Speichern der Vertices
und
u16 uiIndicies[36]; //Das Array für unsere Indicies
Nun können wir den Rendervorgang programmieren, in welchem wir uns zuerst einen Zeiger auf den Video-Treiber holen, mit welchem wir das Material für unseren Würfel festlegen. Danach bestimmen wir, dass wir die Weltkoordinaten der Node (nicht wie im vorhergehenden Beispiel der kompletten Szene) verwenden wollen, da wir sonst alles bewegen würden. Dies führt bei der Anwendung mehrerer Würfel zu Problemen. Anschließend sind wir soweit, den Würfel zeichnen zu lassen :
//!Zeichnet unseren Würfel
void CWuerfel::render()
{
//Den Treiber einholen
video::IVideoDriver* driver = SceneManager->getVideoDriver();
//Das Material festlegen
driver->setMaterial(mat);
//Wir verändern hier die Weltkoordinaten ...
driver->setTransform(ETS_WORLD, AbsoluteTransformation);
//Zeichnen des Würfels
driver->drawIndexedTriangleList(
&cwVertices[0], //Zeiger auf das erste Element im Vertices-Array
8, //Anzahl der Elemente im Vertices-Array
&uiIndicies[0], //Zeiger auf das erste Element in Indicies-Array
12); //Anzahl der zu zeichnenden Dreiecke
}
|
Festlegen der Größe
[Bearbeiten]Wir wollen nun eine Prozedur einbauen, in welcher die Größe des Würfels angegeben wird. Der Würfel soll um den Nullpunkt erstellt werden. Die Vertices sollen über die Breite-, Höhe- und Tiefenangabe errechnet werden. Dazu benötigen wir ein paar Hilfsvariablen, welche die Dimensionen des Würfels speichern :
f32 fMaxLinks, fMaxRechts, //Zur Definition der Grenzen im Koordinatensystem
fMaxVorne, fMaxHinten,
fMaxOben, fMaxUnten,
cwWidth, cwHeight, cwDepth; //Zum Speichern der Dimensionen des Würfels
|
Nun vermerken wir die Dimension des Würfels einfach in den Hilfsvariablen unserer Klasse. Zuerst aber deklarieren wir die Prozedur mit
void SetSize(f32 fWidth, f32 fHeight, f32 fDepth); //Größe des Würfels angeben
in der Header-Datei und bauen diese Funktion dann anschließend in die Quellcode-Datei ein:
//!Setzt die Größe des Würfels auf die angegebenen Werte
void CWuerfel::SetSize(f32 fWidth, f32 fHeight, f32 fDepth)
{
cwWidth = fWidth; //Speichern der Dimensionen ...
cwHeight = fHeight; //in den Hilfsvariablen ...
cwDepth = fDepth; //der Klasse
}
|
Erstellen der Vertices
[Bearbeiten]Da wir nun die Vertexdaten berechnen können, wollen wir dies als eine Prozedur im protected-Bereich der Header-Datei deklarieren :
void Create_Vertices(); //Zum Erstellen der Eckpunkte
Da die Dimensionen in den Hilfsvariablen bekannt sind, können wir uns daran machen, die Grenzen des Würfels im Koordinatensystem zu berechnen und dann in den Hilfsvariablen
fMaxLinks, fMaxRechts, fMaxVorne, fMaxHinten, fMaxOben, fMaxUnten
zu speichern, was uns das definieren der Vertices erleichtert. Danach verwenden wir diese Hilfsvariablen zum Erstellen des Vertices-Array. Die Funktion in der Quellcode-Datei sieht wie folgt aus :
//!Erstellt die Eckdaten des Würfels
void CWuerfel::Create_Vertices()
{
/**** Linke und rechte Grenze ****/
/*********************************/
//Rechter Rand
fMaxRechts = cwWidth / 2.0f; //z.B. 3 : 2 = 1.5
//Linker Rand
fMaxLinks = (fMaxRechts - cwWidth); //z.B. 3 : 2 = 1.5 - 3 = -1.5
/**** Vordere und hintere Grenze ****/
/************************************/
//Hinterer Rand
fMaxHinten = cwDepth / 2.0f;
//Vorderer Rand
fMaxVorne = (fMaxHinten - cwDepth);
/**** Obere und untere Grenze ****/
/*********************************/
//Oberer Rand
fMaxOben = cwHeight / 2.0f;
//Unterer Rand
fMaxUnten = fMaxOben - cwHeight;
//Vorne
cwVertices[0] = S3DVertex(fMaxLinks, fMaxUnten, fMaxVorne,0,0,0,SColor(255,255,0,0),0,0); //Punkt A
cwVertices[1] = S3DVertex(fMaxLinks, fMaxOben, fMaxVorne,0,0,0,SColor(255,0,255,0),0,0); //Punkt B
cwVertices[2] = S3DVertex(fMaxRechts,fMaxUnten, fMaxVorne,0,0,0,SColor(255,0,0,255),0,0); //Punkt C
cwVertices[3] = S3DVertex(fMaxRechts,fMaxOben, fMaxVorne,0,0,0,SColor(255,0,0,255),0,0); //Punkt D
//Hinten
cwVertices[4] = S3DVertex(fMaxLinks, fMaxUnten, fMaxHinten,0,0,0,SColor(255,255,255,0),0,0); //Punkt E
cwVertices[5] = S3DVertex(fMaxLinks, fMaxOben, fMaxHinten,0,0,0,SColor(255,0,255,255),0,0); //Punkt F
cwVertices[6] = S3DVertex(fMaxRechts,fMaxUnten, fMaxHinten,0,0,0,SColor(255,255,0,255),0,0); //Punkt G
cwVertices[7] = S3DVertex(fMaxRechts,fMaxOben, fMaxHinten,0,0,0,SColor(255,0,0,255),0,0); //Punkt H
}
|
Festlegen der Bounding-Box
[Bearbeiten]Die Bounding-Box stellt ebenfalls einen (ggf. rechteckigen) Würfel dar, welcher die Node umgibt. Man kann diesen Würfel nun durch die Vertexdaten definieren, da diese ja die Aussengrenzen unseres Würfels darstellen. Die Definition in der Header-Datei lautet
void Create_BoundingBox();//Zum Erstellen der Bounding-Box
Das Definieren der Bounding-Box wird nur durch einen Durchlauf durch das Vertices-Array erreicht, da die Box die Vertices als interne Eckpunkte speichert. Dies geschieht in der Quellcode-Datei mit :
//!Erstellt unsere Axis Aligned Bounding Box
void CWuerfel::Create_BoundingBox()
{
ABox.reset(cwVertices[0].Pos); //Reset in Initialisierung auf den ersten Vertex
for (s32 i=1; i<8; ++i) //Hinzufügen der restlichen Vertices
ABox.addInternalPoint(cwVertices[i].Pos);
}
|
Definieren der Indicies
[Bearbeiten]Auch dies erledigen wir durch eine einfache Prozedur, welche mit
void Create_Indicies(); //Zum Erstellen des Indicies-Array
in der Header-Datei definiert wird. Anschließend kopieren wir die Indicies aus einem lokalen Array in das globale Array, um Zugriff aus dem Rendervorgang zu haben. Dies sieht wie folgt aus:
//!Erstellt das globale Indicies-Array
void CWuerfel::Create_Indicies()
{
//Zuerst als lokales Array definieren ....
u16 ind[36] = {0, 1, 2, //A->B->C=Dreieck1 (Vorderseite)
2, 1, 3, //C->B->D=Dreieck2 (Vorderseite)
3, 6, 2, //D->G->C=Dreieck3 (Rechte Seite)
3, 7, 6, //D->H->G=Dreieck4 (Rechte Seite)
6, 7, 5, //G->H->F=Dreieck5 (Rückseite)
5, 4, 6, //F->E->G=Dreieck6 (Rückseite)
5, 1, 4, //F->B->E=Dreieck7 (Linke Seite)
4, 1, 0, //E->B->A=Dreieck8 (Linke Seite)
1, 5, 7, //B->F->H=Dreieck9 (Oberseite)
7, 3, 1, //H->D->B=Dreieck10 (Oberseite)
4, 0, 6, //E->A->G=Dreieck11 (Unterseite)
6, 0, 2};//G->A->C=Dreieck12 (Unterseite)
//... und dann ins globale Array kopieren
for (u8 i=0; i<36; i++)
uiIndicies[i] = ind[i];
}
|
Einbauen der Zeitsteuerung
[Bearbeiten]Um den Würfel zeitgesteuert drehen zu können, benötigen wir 4 Prozeduren, welche das ganze ermöglichen :
- eine Prozedur, welche die Zeitspanne festlegt, nach der der Würfel gedreht werden soll (Fachbegriff dafür ist Delta Time),
- eine Prozedur, welche sich den letzten Moment merkt, in dem der Würfel gedreht wurde,
- eine Prozedur, welche die aktuelle Zeit als Parameter übergeben bekommt und welche diesen Zeitpunkt dann speichert und
- eine Prozedur, die nach Ablauf der Delta Time den Würfel um einen bestimmten Winkel dreht.
Festlegen der Zeitspanne (Delta Time)
[Bearbeiten]Diese Funktion speichert die Delta Time in einer Variable in unserer Würfel-Klasse, welche deklariert wird durch :
u32 uDeltaTime; //Zeitspanne bis zu jeder Drehung
In der Header-Datei definieren wir nun eine Prozedur, welche die Delta Time als Parameter übergeben bekommt und diese dann abspeichert :
void SetDeltaTime(u32 uiDeltaTime); //Zum Festlegen der Zeitspanne bis zur Drehung
Nun können wir die Funktion in der Quellcode-Datei programmieren :
//!Übergibt die Zeitspanne, nach der eine Drehung stattfinden soll
void CWuerfel::SetDeltaTime(irr::u32 uiDeltaTime)
{
this->uDeltaTime = uiDeltaTime;
}
|
Speichern des Zeitpunkts der letzten Drehung
[Bearbeiten]Hierzu deklarieren wir eine Variable in unserer Klasse mit
u32 uZuletztGestoppt; //Die letzte gestoppte Zeit
sowie die Prozedur zur Speicherung des Zeitpunkts in der Header-Datei durch
void SetTimePos(u32 uiTime); //Zum Speichern des letzten Moments der Drehung
Danach programmieren wir die Prozedur in der Quellcodedatei durch :
//!Merkt sich den letzten Moment der Drehung des Würfels
void CWuerfel::SetTimePos(irr::u32 uiTime)
{
this->uZuletztGestoppt = uiTime;
}
|
Übergeben der aktuellen Zeit
[Bearbeiten]Auch hierfür deklarieren wir in der Header-Datei zuerst eine Variable mit
u32 uAktuelleZeit; //Zum Speichern der aktuellen Zeit
und anschließend eine Prozedur mit
void TellCurrentTime(u32 uiTime); //Zum übergeben der aktuellen Zeit
Dann können wir diese programmieren mit :
//!Übergibt die aktuelle Zeit an die Würfel-Klasse
void CWuerfel::TellCurrentTime(irr::u32 uiTime)
{
this->uAktuelleZeit = uiTime;
}
|
Diese aktuelle Zeit muss dann bei jedem Programmdurchlauf übergeben werden, damit die Zeitsteuerung des Würfels funktioniert.
Die Zeitgesteuerte Drehung
[Bearbeiten]Da nun die Zeitsteuerung eingebaut ist, geht es an die Drehung des Würfels. Dazu benötigen wir eine Variable in unserer Klasse, welche den aktuellen Winkel des Würfels speichert. Diese deklarieren wir durch
f32 fWinkel; //Unser Winkel für die Rotation des Würfels
Nun geht es um die eigentliche Funktion zum Drehen, welche bei jedem Programmdurchlauf aufgerufen werden muss, um die Zeitsteuerung sowie die Drehfunktion der Würfel-Klasse aktuell zu halten. Diese deklarieren wir in der Header-Datei durch
void TurnIfDesired(); //Dreht den Würfel nach Ablauf der Zeitspanne
In dieser Funktion fragen wir zuerst ab, ob die festgelegte Delta Time abgelaufen ist. Falls das der Fall ist, dann erhöhen wir den Winkel und Drehen den Würfel und die Y- und Z-Achse. Die Funktion sieht wie folgt aus :
//!Dreht den Würfel nach Ablauf der Delta-Time
void CWuerfel::TurnIfDesired()
{
//Gewünschte Zeit vergangen ?
if (this->uAktuelleZeit >= (this->uZuletztGestoppt + this->uDeltaTime))
{
//Aktuellen Zeitmoment der Drehung speichern
this->SetTimePos(this->uAktuelleZeit);
//Den Winkel erhöhen
this->fWinkel += 0.5f;
//Nicht über 360 Grad drehen
if (this->fWinkel > 360) this->fWinkel = 1;
}
//Rotation ausführen
this->setRotation(core::vector3df(0,this->fWinkel,this->fWinkel));
}
|
Zurückgeben eines Debug-Strings
[Bearbeiten]Falls es mal bei Objekten zu Problemen in der Darstellung kommt, so ist es immer eine recht gute Hilfe, einen sog. Debug-String zur Hand zu haben. Wenn man diesen in Irrlicht anzeigt, dann lassen sich manche Fehler im Programm wie z.B. nicht initialisierte Variablen, Rechenfehler etc. leichter aufspüren.
Hierzu deklarieren wir diese Funktion in der Header-Datei mit
stringw GetDebugString(); //Gibt den Debug-String des Würfels zurück
In diesem Fall verwenden wir einen Rückgabewert vom Typ stringw, welcher in Irrlicht deklariert ist. Dieser Datentyp ist sehr gut für diese Zwecke geeignet, da er uns viel Konvertierungsarbeit erspart. Diese Konvertierungsroutinen sind im Datentyp bereits implementiert und werden selbstständig angewandt, falls es erforderlich ist. Kommen wir nun zur Programmierung der Funktion in unserer Würfel-Klasse :
//!Gibt uns einen Debug-String des Würfels zurück
stringw CWuerfel::GetDebugString()
{
//Den Debug-String erstellen
stringw str("fMaxRechts : "); str += this->fMaxRechts;
str += L"\nfMaxLinks : "; str += this->fMaxLinks;
str += L"\nfMaxOben : "; str += this->fMaxOben;
str += L"\nfMaxUnten : "; str += this->fMaxUnten;
str += L"\nfMaxVorne : "; str += this->fMaxVorne;
str += L"\nfMaxHinten : "; str += this->fMaxHinten;
str += L"\ncwWidth : "; str += this->cwWidth;
str += L"\ncwHeight : "; str += this->cwHeight;
str += L"\ncwDepth : "; str += this->cwDepth;
str += L"\nfWinkel : "; str += this->fWinkel;
str += L"\nuAktuelleZeit : "; str += this->uAktuelleZeit;
return str; //Rückgabe aus der Funktion
}
|
Diesen String lassen wir uns dann später in Irrlicht-Fenster mit anzeigen.Gratulation, Sie haben ihre Würfel-Klasse fertig ! Nun wollen wir sie noch verwenden.
Anwenden der Würfel-Klasse
[Bearbeiten]Einbinden von Irrlicht und der Würfel-Klasse
[Bearbeiten]Da wir nun Irrlicht und die Würfel-Klasse verwenden wollen, binden wir beides ein und deklarieren den Namespace von Irrlicht :
//Einbinden der Header-Datei von Irrlicht
#include <irrlicht.h>
//Einbinden der Header-Datei unserer Würfel-Klasse
#include "CWuerfel.h"
//Einbinden der Namespaces
using namespace irr;
using namespace core;
using namespace video;
|
Erstellen des Device und einholen des Video-Treibers
[Bearbeiten]Dies geht in gewohnter Weise mit :
//Unser Irrlicht-Device erstellen und initialisieren
IrrlichtDevice *device =
createDevice( video::EDT_OPENGL, dimension2d<u32>(640, 480), 32,
false, false, false, 0);
//Konnte das Device erstellt werden ?
if (!device)
return 1; //Falls nicht, Fehlercode zurückgeben und Programm abbrechen
//Den Text des Hauptfensters festlegen
device->setWindowCaption(L"Einen Würfel-Klasse in Irrlicht !");
//Den Videotreiber erstellen und Zeiger aus dem Device abholen
IVideoDriver* driver = device->getVideoDriver();
|
Einbinden des Szene-Managers und des GUI
[Bearbeiten]Nun erstellen wir einen Szene-Manager, welcher u.a. unsere Nodes verwaltet und diese zeichnet.
//Einen Szene-Manager erstellen und Zeiger aus dem Device abholen
scene::ISceneManager* smgr = device->getSceneManager();
|
Da wir einen Debug-String darstellen wollen, benötigen wir einen Zugriff auf die GUI-Funktionen (GUI = Graphical user interface) von Irrlicht. Danach erstellen wir ein Text-Klasse zum Anzeigen des Debug-Strings und registrieren diese im GUI-Manager :
//Einen GUI_Manager erstellen und Zeiger aus dem Device abholen
gui::IGUIEnvironment* guienv = device->getGUIEnvironment();
//Ein Text-Element definieren und an den GUI-Manager übergeben
gui::IGUIStaticText* GUI_debug_text = guienv->addStaticText
(L"",rect<s32>(5, 5, 200, 200),false,true,0,-1,false);
|
Die Parameter der Text-Klasse haben folgende Bedeutung :
- zuerst wird der anzuzeigende Text angegeben. Das "L" vor dem Text sagt aus, dass es sich um einen Wide-String handelt,
- dann wird das Rechteck definiert, in dem der Text angezeigt werden soll,
- der zweite Parameter gibt an, ob der Text einen Rahmen haben soll,
- der dritte legt fest, ob der automatische Zeilenumbruch aktiviert werden soll,
- der vierte legt fest, ob ein Parent zugewiesen werden soll,
- der fünfte bestimmt die ID des Textes ("-1" = keine benötigt) und
- der sechste und letzte Parameter bestimmt, ob der Hintergrund des Textes farbig gefüllt werden soll.
Einbinden einer Kamera
[Bearbeiten]Da wir nun einen Szene-Manager haben, binden wir auch eine Kamera ein. Dieses erfolgt durch :
//Eine Kamera erstellen
smgr->addCameraSceneNode(0, core::vector3df(0,-2,0), core::vector3df(0,0,0));
|
Die Parameter definieren,
- ob die Kamera eine Parent-Node hat (ist sehr gut zur Objektverfolgung),
- der Positionsvektor der Kamera und
- der Positionsvektor, auf den die Kamera blicken soll.
Definieren des Würfels
[Bearbeiten]Nun definieren wir zuerst einen Würfel vom Typ unserer CWuerfel-Klasse. Danach stellen wir die Delta Time der Zeitsteuerung ein und übergeben die aktuelle Zeit als Stopzeit, damit der erste Moment der Drehung definiert ist :
//Einen Würfel der Klasse CWuerfel erstellen
CWuerfel *Wuerfel = new CWuerfel(smgr->getRootSceneNode(), smgr, 1);
//Nach welcher Zeit(ms) soll die Szene gedreht werden ?
Wuerfel->SetDeltaTime(50); //50 Millisekunden
//Letzte Zeitmessung initalisieren
Wuerfel->SetTimePos(device->getTimer()->getTime());
|
Anzeigen des Debug-Strings
[Bearbeiten]Im Programmdurchlauf können wir nun den Debug-String in eine lokale Variable speichern und über das GUI-Interface in Irrlicht anzeigen lassen :
//Den Debug-String erstellen und abholen
stringw sDebStr = Wuerfel->GetDebugString();
//Den Debug-String in der Irrlicht-GUI anzeigen
GUI_debug_text->setText(sDebStr.c_str());
|
Übergeben der Zeit und Drehen des Würfels
[Bearbeiten]Da die Zeitsteuerung die aktuelle Systemzeit zur Zeitmessung benötigt, müssen wir diese der Würfel-Klasse übergeben. Ist diese dann dort gespeichert, rufen wir die Prozedur auf, welche entscheidet, ob der Würfel gedreht werden muss :
//Aktuelle Zeit mitteilen
Wuerfel->TellCurrentTime(device->getTimer()->getTime());
//Nach Ablauf der Zeitspanne den Würfel drehen
Wuerfel->TurnIfDesired();
|
Der Quellcode zum Beispiel
[Bearbeiten]Sie finden den Quellcode