我一直在研究游戏的服务器代码。它的效果非常好,但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个文件中处理。
网络事件解码器在通过网络接收的字符串转换后调用适当的方法。
这样做非常有效,但游戏会变得更大,我希望保持干净和模块化。
这个设计是个好主意吗?如果不是,游戏服务器开发中通常使用什么类型的模式来保持面向对象?
由于
答案 0 :(得分:1)
看着你的课程,我会想到command pattern。实际上,以C
结尾的方法看起来非常像命令。如果您有命令界面:
class Command {
virtual void execute() = 0;
}
和每个命令的单独子类,然后NetEventDecoder
可以将接收到的字符串解码为特定命令。
此外,只要您发现自己将相同的数据传递给多个方法,就会暗示有一个类隐藏在那里。例如,您可以将tableNumber
的所有方法拉入Table
类。我也会摆脱Manager
类并更直接地建立关联模型。
例如:
// 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();
}
}