1

私は自分のゲームのサーバーコードに取り組んできました。それは本当にうまく機能しますが、関数の90%は1つのクラスにあります。

通常、私は物事を分割する方法を知るのは非常に簡単だと思います。各オブジェクトがクラスであるか、各ダイアログがクラスであり、その子のロジックを処理します。

この場合、サーバーはリクエストを受信し、他のプレーヤーに通知するか、適切なプレーヤーを処理して通知します。

ヘッダーファイルは次のとおりです。

    class ServerCore : public ServerHost, public NetEventListener,
        public ServerEventProvider
    {
        NetEventDecoder m_dec;
        NetEventEncoder m_enc;
        LoginManager m_login;

        ServerPlayerManager m_playerMan;
        ServerTableManager m_tableMan;

        void sendToTarget();
        void sendToAllActive();
        void sendToActiveNotTarget();
        void sendToTable(int tableNo);



    public:
        ServerCore();
        virtual void onConnect (Lacewing::Server::Client &client);
        virtual void onDisconnect (Lacewing::Server::Client &client);
        virtual void onError (Lacewing::Error &error);
        virtual void onReceive (Lacewing::Server::Client &client, char * data, int size);
        virtual void sendChatMessageC(const std::string& message,ChatAreaEnum area);
        virtual void requestTableC(int tableNo, int seatNo);
        virtual void playerRequestSitC(int tableNumber, int seatNumber);
        virtual void playerStoodUpC();
        virtual void hostGameC(const SpadesGameInfo& info);
        virtual void gameMessageC(SpadesCSMessageEnum message, const std::vector<int>& params);
        virtual void modifyListC(const std::string& player, GroupTypeEnum group, bool add);
        virtual void canceledHostingRequestC();
        virtual void sendInviteC(int tableNo, const std::string& player);

        virtual void loginResult(const std::string& name, ServerPlayer* player,
            const std::string& sessionID, bool success, bool newSession);
        virtual void readyToReceiveLobbyDataC();

        virtual void playerAbandonedGameC();
        virtual void watchTableC(int tableNo);

        virtual void gameCompleted(int tableId);

        virtual void playerWantsPlayAgainC();
        virtual ~ServerCore(void);
    };
}

どうすればこれを小さなクラスに分類できるのか、私にはよくわかりません。それらが実行するタスクは、認証やデータベースからのデータ取得などの他のオブジェクトに渡されますが、現在、すべてのイベントはこの1つのファイルで処理されています。

ネットイベントデコーダは、ネットワーク経由で受信した文字列から変換した後、適切なメソッドを呼び出します。

この方法でそれを行うことは非常にうまくいきますが、ゲームは大きくなるでしょう、そして私はクリーンでモジュール式であり続けたいです。

このデザインは良い考えですか?そうでない場合、ゲームサーバーの開発では、オブジェクト指向を維持するために通常どのような種類のパターンが使用されますか?

ありがとう

4

1 に答える 1

1

クラスを見ると、コマンド パターンが思い浮かびます。実際、 で終わるメソッドはCコマンドによく似ています。コマンド インターフェイスがある場合:

class Command {
  virtual void execute() = 0;
}

コマンドごとに個別のサブクラスを作成するとNetEventDecoder、受信した文字列を特定のコマンドにデコードできます。

また、同じデータを複数のメソッドに渡していることに気付いたときはいつでも、そこにクラスが隠れていることを示しています。たとえば、a を使用するすべてのメソッドをクラスにプルできtableNumberますTableManagerまた、クラスを取り除き、関連付けをより直接的にモデル化します。

例えば:

// A game server contains players and tables
class GameServer {
  map<string, Player *> players;
  map<int, Table *> tables;

  Player *findPlayer(const string &name);
  Table *findTable(int tableNumber);
  ...
}

// A player can perform various actions
class Player {
  string name;

  bool requestSeat(Table *table);
  void standUp();
  ...
}

// A table maintains the status of seats
class Table {
  int tableNumber;

  bool requestSeat(int seatNumber);
  ...
}

上記のGameServerクラスは単にゲームをモデル化しているだけで、ネットワークはまったく扱いません。次にNetEventDecoder、 とServerCoreが連携してネットワーク機能を提供し、 でコマンドを呼び出すことができますGameServer。コマンドの例は次のようになります。

class PlayerStandUpCommand : public Command {
  GameServer *server;
  string playerName;

  void execute() {
    Player *player = server->findPlayer(playerName);
    player->standUp();
  }
}
于 2012-07-24T05:31:49.430 に答える