Da ich das ganze gerade selbst verwendet habe nun eine kleine Anleitung.
Nehmen wir mal an wir wollen eine Map erzeugen in der Sternensysteme enthalten sind und in jedem System n Planeten.
Meine Struktur sieht in etwa wie folgt aus.
Code:
GameClass
* GameStateManager
* GameStateIntro
* GameStateNewGame
* GameStateOptions
* GameStateRunning
* GameMap
Jeder GameState repräsentiert einen Zustand im Spiel, man könnte auch sagen einen Menüpunkt der ausgewählt wurde, starten tuen wir mit dem
GameStateIntro.
Der zeigt ein Menü an in dem man dann
New Game sagen kann, dann wechseln wir in den nächsten GameState usw.
Wie man sieht müsste ich um im GameState
GameStateNewGame an das Objekt für die Karte zu kommen diverse Methoden einbauen in GameStateManager und in die GameClass.
Viel eleganter finde ich jedoch einfach ein Event zu verwenden.
Wir erzeugen also ein Event
erzeuge Map und warten auf die Antwort die auch wieder per Event kommt.
Als erstes benötigen wir eine Struktur mit der wir lustig Event's durch die Gegend schicken, ich habs erstmal recht simpel gemacht, und ein Enum für unsere eigenen EventsID's
UserEvents.h
Code:
#pragma once
#include <irrlicht.h>
enum EventIDs {
EV_CREATE_MAP,
EV_MAP_CREATED
};
struct tEventStruct {
irr::s32 int1, int2, int3;
irr::u32 uint1, uint2, uint3;
irr::core::stringw string1, string2, string3;
};
Man muss noch wissen das GameClass bei mir von IEventReceiver erbt, von da aus verteile ich dann die Events an den GameStateManager und dann weiter an die einzelnen GameStates.
Hier mal zur Info wie so ein GameState bei mir aussieht
Code:
class IGameState {
protected:
irr::IrrlichtDevice *deviceValue;
CGameStateManager *gsMgrValue;
irr::core::stringw nameValue;
public:
IGameState(void) {}
~IGameState(void) {}
virtual void OnEnter(irr::IrrlichtDevice *device, irr::s32 screenWidth, irr::s32 screenHeight) {
this->deviceValue = device;
}
virtual void OnUpdate(irr::f32 elapsedTime) = 0;
virtual void OnRender(void) = 0;
virtual void OnLeave(void) = 0;
// Taste down
virtual void OnKeyDown(irr::SEvent eventArgs) =0;
// Taste up
virtual void OnKeyUp(irr::SEvent eventArgs) = 0;
// Maus bewegt
virtual void OnMouseMove(irr::SEvent eventArgs) = 0;
// linker Mausbutton gedrückt
virtual void OnLMouseButtonDown(irr::SEvent eventArgs) = 0;
// mittlerer Mausbutton gedrückt
virtual void OnMMouseButtonDown(irr::SEvent eventArgs) = 0;
// rechter Mausbutton gedrückt
virtual void OnRMouseButtonDown(irr::SEvent eventArgs) = 0;
// Wheel bewegt
virtual void OnMouseWheel(irr::SEvent eventArgs) = 0;
// GUI Events
virtual void OnGUIEvent(irr::SEvent eventArgs) = 0;
virtual void OnUserEvent(irr::SEvent eventArgs) = 0;
virtual void SetName(irr::core::stringw name) { this->nameValue = name; }
virtual irr::core::stringw GetName(void) { return this->nameValue; }
};
So wieder zum Thema, wir befinden uns also an der Stelle an der die Map erzeugt werden soll, wir fragen vom User die Werte ab, in diesem Fall
Anzahl Systeme und
Anzahl Planeten je System.
Dann machen wir folgendes.
Code:
tEventStruct data;
irr::SEvent e;
data.int1 = maxSystems;
data.int2 = maxPlanets;
e.EventType = ::EET_USER_EVENT;
e.UserEvent.UserData1 = ::EV_CREATE_MAP;
e.UserEvent.UserData2 = (irr::s32)&data;
this->deviceValue->postEventFromUser(e);
Wir erzeugen also eine Struktur vom Typ
tEventStruct und schicken den Pointer auf diese Struktur als 2. Parameter mit.
in unserer GameClass sieht die OnEvent-Methode in etwa so aus.
Wir empfangen hier das Event, in dem unser Pointer auf unsere Struktur steckt, erzeugen die Map und schicken ein neues Event los.
Code:
switch(eventArgs.EventType) {
case irr::EET_USER_EVENT: {
switch(eventArgs.UserEvent.UserData1) {
case ::EV_CREATE_MAP: {
tEventStruct *data = (tEventStruct*)eventArgs.UserEvent.UserData2;
this->gameMapValue->CreateRandom(data->int1, data->int2, 10);
irr::SEvent e;
e.EventType = ::EET_USER_EVENT;
e.UserEvent.UserData1 = ::EV_MAP_CREATED;
this->deviceValue->postEventFromUser(e);
break;
} // end EV_CREATE_MAP
default: {
this->gsMgrValue->OnUserEvent(eventArgs);
break;
} // end default
} // end switch
} // end irr::EET_USER_EVENT
}
Und empfangen tuen wir das ganze dann mit folgendem Code.
Auch hier bekommen wir wieder einen Pointer auf die Struktur die wir losgesendet haben.
Code:
void CGameStateNewGame::OnUserEvent(irr::SEvent eventArgs) {
tEventStruct *data = (tEventStruct*)eventArgs.UserEvent.UserData2;
switch(eventArgs.UserEvent.UserData1) {
case ::EV_MAP_CREATED: {
// Todo : Das Spiel kann nun eigentlich starten
this->gsMgrValue->CreateGameState(::GS_RUNNING);
break;
} // EV_MAP_CREATED
} // end switch
}
EDIT:
Unter der Dusche ist mir gerade eingefallen das dies eigentlich die quick&dirty Methode ist, morgen überarbeite ich das hier nochmal, dann gibts die Version die auch ohne Probleme mit .NET funktioniert.