Aktuelle Zeit: 18.04.2024, 09:27

Alle Zeiten sind UTC + 1 Stunde




Ein neues Thema erstellen Auf das Thema antworten  [ 2 Beiträge ] 
Autor Nachricht
BeitragVerfasst: 03.10.2008, 17:35 
Offline

Registriert: 16.01.2008, 12:31
Beiträge: 79
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.


Nach oben
 Profil  
 
BeitragVerfasst: 05.10.2008, 15:32 
Offline

Registriert: 16.01.2008, 12:31
Beiträge: 79
So hier jetzt die etwas bessere Version, wobei ich mir nicht sicher bin welche mir wirklich besser gefällt. ^^

Also wir erzeugen für jedes Event das wir versenden wollen jweils eine Klasse

Code:

class EventCreateMap : public irr::SEvent {
private:
  irr::s32 maxSystemValue;
  irr::s32 maxPlanetsValue;

public:
  EventCreateMap(void) { }
  ~EventCreateMap(void) {}

  void SetSystemCount(irr::s32 val) {
    maxSystemValue = val;
  }
 
  irr::s32 GetSystemCount(void) {
    return maxSystemValue;
  }
 
  void SetPlanetsCount(irr::s32 val) {
    maxPlanetsValue = val;
  }
 
  irr::s32 GetPlanetsCount(void) {
    return maxPlanetsValue;
  }
};

class EventMapCreated : public irr::SEvent {
private:
public:
  EventMapCreated(void) {}
  ~EventMapCreated(void) {}
};


Abschicken tuen wir das Event dann wie folgt.
Code:
EventCreateMap e;
e.EventType = ::EET_USER_EVENT;
e.SetSystemCount(maxSystems);
e.SetPlanetsCount(maxPlanets);
e.UserEvent.UserData1 = ::EV_CREATE_MAP;
this->deviceValue->postEventFromUser(e);


empfangen tuen wir es so und erzeugen dann das 2. Event als praktisch als Antwort.

Code:
    case irr::EET_USER_EVENT: {
      switch(eventArgs.UserEvent.UserData1) {
        case ::EV_CREATE_MAP: {
          EventCreateMap *data = (EventCreateMap*)&eventArgs;
          this->gameMapValue->CreateRandom(data->GetSystemCount(), data->GetPlanetsCount(), 10);
          EventMapCreated 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



Unter .NET kann man übrigens wunderbar statt der ENUM's die den Typ angeben typeof bzw. gettype verwenden um den Typ des Objektes zu prüfen. Was von beidem tatsächlich schneller ist kann ich nicht sagen.


Nach oben
 Profil  
 
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 2 Beiträge ] 

Alle Zeiten sind UTC + 1 Stunde


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de