2017-05-13 6 views
0

Ich erstelle eine kleine xbox-Anwendung und für den Anfang sollte es erkennen, welches Spiel gerade läuft und dann umgehen und/oder ein Programm starten. Da ich erst kürzlich Polymorphismus gelernt habe, dachte ich, ich könnte es hier implementieren, um an Effizienz zu gewinnen. Unten ist mein Code (nicht so effizient, wie ich dachte, es wäre):Zurückgeben einer polymorphen Klasse

DWORD(__cdecl *XamGetCurrentTitleID)() = (DWORD(__cdecl *)())ResolveFunction("xam.xex", 0x1CF); // Resolves current Game ID 

typedef enum _XBOX_GAMES : DWORD // Enum that holds Game IDs 
{ 
    BOOT_UP = 0x00000000, 
    DASHBOARD = 0xFFFE07D1, 
    FREESTYLEDASH = 0xF5D20000, 
    COD_WORLD_AT_WAR = 0x4156081C, 
    COD_MODERN_WARFARE = 0x415607E6, 
    COD_MODERN_WARFARE_2 = 0x41560817, 
    COD_BLACK_OPS_1 = 0x41560855, 
    COD_MODERN_WARFARE_3 = 0x415608CB, 
    COD_BLACK_OPS_2 = 0x415608C3, 
    COD_GHOSTS = 0x415608fC, 
    COD_ADVANCED_WARFARE = 0x41560914, 
    COD_BLACK_OPS_3 = 0x4156091D, 
    DESTINY = 0x415608F8, 
    GTAV = 0x545408A7 
} XBOX_GAMES; 

DWORD GameChecker() 
{ 
    DWORD lastID = NULL; 

    Game *game; 
    AW aw; BO1 bo1; BO2 bo2; BO3 bo3; Ghosts ghosts; MW2 mw2; MW3 mw3; Dashboard dashboard; 

    for (;;) 
    { 
     if (XamGetCurrentTitleID() != lastID) 
     { 
      switch (XamGetCurrentTitleID()) 
      { 
       case BOOT_UP: 
        // nothing 
        break; 
       case DASHBOARD: 
        game = &dashboard; 
        game->Launch(); 
        break; 
       case COD_MODERN_WARFARE_2: 
        game = &mw2; 
        game->Launch(); 
        break; 
       case COD_MODERN_WARFARE_3: 
        game = &mw3; 
        game->Launch(); 
        break; 
       case COD_GHOSTS: 
        game = &ghosts; 
        game->Bypass(); 
        game->Launch(); 
        break; 
       case COD_BLACK_OPS_1: 
        game = &bo1; 
        game->Launch(); 
        break; 
       case COD_BLACK_OPS_2: 
        game = &bo2; 
        game->Bypass(); 
        break; 
       case COD_BLACK_OPS_3: 
        game = &bo3; 
        game->Bypass(); 
        break; 
       case COD_ADVANCED_WARFARE: 
        game = &aw; 
        game->Bypass(); 
        game->Launch(); 
        break; 
      } 

      lastID = XamGetCurrentTitleID(); 
     } 
    } 

    return 0; 
} 

Wie Sie mir die Wild- verschoben haben sehen können, könnte> Start() und Spiele-> Bypass(), die außerhalb des Schalters Anweisung, weniger Code zu haben und es nur einmal aufzurufen, aber ich wusste nicht, wie ich feststellen konnte, wann ein Spiel eine Umgehung und/oder einen Start benötigt. Das ist mein GameClass:

class Game 
{ 
public: 
    virtual void Bypass() { } 

    virtual void Launch() { } 
}; 

Und das ist die Klasse eines Beispiels Spiel:

// needs bypass and launch called 
class AW : public Game 
{ 
public: 
    void Bypass() 
    { 
     // bypass 
    } 

    void Launch() 
    { 
     Sleep(500); 
     XNotifyUI(L"AW - Loaded!"); 
    } 
}; 

Ich würde gerne wissen, ob es einen Weg gibt, etwas zu tun:

DWORD GameChecker() 
{ 
    DWORD lastID = NULL; 

    Game *game; 

    for (;;) 
    { 
     if (XamGetCurrentTitleID() != lastID) 
     { 
      switch (XamGetCurrentTitleID()) 
      { 
       case BOOT_UP: 
        // nothing 
        break; 
       default: 
        game = &functionThatReturnsClassBasedOnGame(XamGetCurrentTitleID()); // I don't know how to code such an function 
        break; 
      } 

      if (game->needsBypass) 
       game->Bypass(); 

      if (game->needsLaunch) 
       game->Launch(); 

      lastID = XamGetCurrentTitleID(); 
     } 
    } 

    return 0; 
} 

Jede Hilfe wird sehr geschätzt! Vielen Dank für Ihre Zeit.

+1

typedefing dass Enum ist sinnlos. Sie haben die C-Kompatibilität verloren, als Sie eine Basis zur Verfügung gestellt haben. Und C++ erkennt bereits ein 'foo' als' enum foo'. – StoryTeller

+0

'_XBOX' Dies ist kein gültiger Bezeichnername. In jedem Bereich ist ein Name, der mit einem Unterstrich gefolgt von einem Großbuchstaben beginnt, für die Standardimplementierung reserviert. –

Antwort

1

Eine einfache Möglichkeit, Ihr Beispiel zu erreichen, ist wie folgt:

const int NEEDS_BYPASS = 1; 
const int NEEDS_LAUNCH = 2; 

class Game 
{ 
public: 
    virtual ~Game() { } 
    virtual int getFeatures() const { return 0; } 
    virtual void Bypass() { } 
    virtual void Launch() { } 
}; 

class Game_Dashboard : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_LAUNCH; } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"Dashboard - Loaded!"); 
    } 
}; 

class Game_ModernWarfare2 : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_LAUNCH; } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"MW2 - Loaded!"); 
    } 
}; 

class Game_ModernWarfare3 : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_LAUNCH; } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"MW3 - Loaded!"); 
    } 
}; 

class Game_Ghosts : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; } 
    void Bypass() { 
     // bypass... 
    } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"Ghosts - Loaded!"); 
    } 
}; 

class Game_BlackOpts1 : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_LAUNCH; } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"BO1 - Loaded!"); 
    } 
}; 

class Game_BlackOpts2 : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_BYPASS; } 
    void Bypass() { 
     // bypass... 
    } 
}; 

class Game_BlackOpts3 : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_BYPASS; } 
    void Bypass() { 
     // bypass... 
    } 
}; 

class Game_AdvancedWarfare : public Game 
{ 
public: 
    int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; } 
    void Bypass() { 
     // bypass 
    } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"AW - Loaded!"); 
    } 
}; 

Game* getGame(DWORD ID) 
{ 
    switch (ID) 
    { 
    case DASHBOARD: 
     return new Game_Dashboard; 
    case COD_MODERN_WARFARE_2: 
     return new Game_ModernWarfare2; 
    case COD_MODERN_WARFARE_3: 
     return new Game_ModernWarfare3; 
    case COD_GHOSTS: 
     return new Game_Ghosts; 
    case COD_BLACK_OPS_1: 
     return new Game_BlackOpts1; 
    case COD_BLACK_OPS_2: 
     return new Game_BlackOpts2; 
    case COD_BLACK_OPS_3: 
     return new Game_BlackOpts3; 
    case COD_ADVANCED_WARFARE: 
     return new Game_AdvancedWarfare; 
    } 
    return NULL; 
} 

DWORD GameChecker() 
{ 
    DWORD currentID, lastID = 0; 
    Game *game; 

    do 
    { 
     currentID = XamGetCurrentTitleID(); 
     if (currentID != lastID) 
     { 
      lastID = currentID; 

      game = getGame(currentID); 
      if (game) 
      { 
       if (game->getFeatures() & NEEDS_BYPASS) 
        game->Bypass(); 

       if (game->getFeatures() & NEEDS_LAUNCH) 
        game->Launch(); 

       delete game; 
      } 
     } 
    } 
    while (true); 

    return 0; 
} 

jedoch eine bessere Nutzung des Polymorphismus würde eher wie dieses, anstatt sein:

class Game 
{ 
public: 
    virtual ~Game() { } 
}; 

class CanBypass 
{ 
public: 
    virtual void Bypass() = 0; 
}; 

class CanLaunch 
{ 
public: 
    virtual void Launch() = 0; 
}; 

class Game_Dashboard : public Game, public CanLaunch 
{ 
public: 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"Dashboard - Loaded!"); 
    } 
}; 

class Game_ModernWarfare2 : public Game, public CanLaunch 
{ 
public: 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"MW2 - Loaded!"); 
    } 
}; 

class Game_ModernWarfare3 : public Game, public CanLaunch 
{ 
public: 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"MW3 - Loaded!"); 
    } 
}; 

class Game_Ghosts : public Game, public CanBypass, public CanLaunch 
{ 
public: 
    void Bypass() { 
     // bypass... 
    } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"Ghosts - Loaded!"); 
    } 
}; 

class Game_BlackOpts1 : public Game, public CanLaunch 
{ 
public: 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"BO1 - Loaded!"); 
    } 
}; 

class Game_BlackOpts2 : public Game, public CanBypass 
{ 
public: 
    void Bypass() { 
     // bypass... 
    } 
}; 

class Game_BlackOpts3 : public Game, public CanBypass 
{ 
public: 
    void Bypass() { 
     // bypass... 
    } 
}; 

class Game_AdvancedWarfare : public Game, public CanBypass, public CanLaunch 
{ 
public: 
    void Bypass() { 
     // bypass 
    } 
    void Launch() { 
     Sleep(500); 
     XNotifyUI(L"AW - Loaded!"); 
    } 
}; 

Game* getGame(DWORD ID) 
{ 
    switch (ID) 
    { 
    case DASHBOARD: 
     return new Game_Dashboard; 
    case COD_MODERN_WARFARE_2: 
     return new Game_ModernWarfare2; 
    case COD_MODERN_WARFARE_3: 
     return new Game_ModernWarfare3; 
    case COD_GHOSTS: 
     return new Game_Ghosts; 
    case COD_BLACK_OPS_1: 
     return new Game_BlackOpts1; 
    case COD_BLACK_OPS_2: 
     return new Game_BlackOpts2; 
    case COD_BLACK_OPS_3: 
     return new Game_BlackOpts3; 
    case COD_ADVANCED_WARFARE: 
     return new Game_AdvancedWarfare; 
    } 
    return NULL; 
} 

DWORD GameChecker() 
{ 
    DWORD currentID, lastID = 0; 
    Game *game; 
    CanBypass *bypasser; 
    CanLaunch *launcher; 

    do 
    { 
     currentID = XamGetCurrentTitleID(); 
     if (currentID != lastID) 
     { 
      lastID = currentID; 

      game = getGame(currentID); 
      if (game) 
      { 
       bypasser = dynamic_cast<CanBypass*>(game); 
       if (bypasser) 
        bypasser->Bypass(); 

       launcher = dynamic_cast<CanLaunch*>(game); 
       if (launcher) 
        launcher->Launch(); 

       delete game; 
      } 
     } 
    } 
    while (true); 

    return 0; 
} 
+0

https://pastebin.com/ZgdDLHBW es wirft eine schwerwiegende Ausnahme (wenn ich auf dem Armaturenbrett bin) nach dem Drucken "Einstellung Umgehungs/Launcher ...", so denke ich, dass die Besetzung oder etwas hier richtig ist falsch: bypasser = dynamic_cast (Spiel); –

+0

Könnten Sie bitte den von Ihnen angegebenen Code überprüfen? es funktioniert nicht :( –

+0

@ZZ_James: der Code, den ich Ihnen gab funktioniert gut, wie es ist, ich habe es getestet. Wenn es für Sie abstürzt, dann haben Sie es nicht korrekt in Ihr Projekt integriert, aber Sie haben nicht alle angezeigt Ihr Code, nur Ihre Checker-Schleife. Und BTW, Ihre Schleife leckt Speicher, da Sie die Anweisung 'delete game; auskommentiert haben. Und warum verwenden Sie' currentID = XamGetCurrentTitleID()! = 0? XamGetCurrentTitleID(): 0; ' anstelle von 'currentID = XamGetCurrentTitleID();'? Ihre Verwendung von '?:' ist redundant. –

Verwandte Themen