The Network Component
To use a client component, you
have to derive a class from it and, in that derived
class, override the necessary functions. Those functions are few and are needed
only to convey when a connection to the server is achieved or to receive
incoming
game messages.
To use the client network
component, begin by deriving your own class from
cNetworkClient:
class cClient : public cNetworkClient
{
private:
virtual bool connect_complete(const DPNMSG_CONNECT_COMPLETE* msg);
virtual bool receive(const DPNMSG_RECEIVE* msg);
};
To pass messages to the
application, the derived application object needs only one
public function to siphon in received messages. Why only one? The client needs
to
know when a connection is established to the server, which is the purpose of the
connect_complete function.
By using a global variable (g_connected)
that represents the connection status, the
client network component can update the state of the connection as follows:
#define CLIENT_WIDTH 640
#define CLIENT_HEIGHT 480
#define ACTION_MOVE_UP 1
#define ACTION_MOVE_RIGHT 2
#define ACTION_MOVE_DOWN 4
#define ACTION_MOVE_LEFT 8
#define ACTION_ATTACK 16
cApp* g_app;
cNetworkAdapter* g_adapter;
bool g_connected;
const float g_angles[13] = { 0.0f,
0.0f, 1.57f, 0.785f, 3.14f,
0.0f, 2.355f, 0.0f, 4.71f,
5.495f, 0.0f, 0.0f, 3.925f };
/****************************************************************************************************/
bool cClient::connect_complete(const DPNMSG_CONNECT_COMPLETE* msg)
{
g_connected = (msg->hResultCode == S_OK);
g_app->set_local_player(msg->dpnidLocal);
return true;
}
bool cClient::receive(const DPNMSG_RECEIVE* msg)
{
g_app->receive(msg);
return true;
}
/****************************************************************************************************/
void cApp::set_local_player(DPNID player_id)
{
EnterCriticalSection(&m_update_cs);
m_players[0].player_id = player_id;
LeaveCriticalSection(&m_update_cs);
}
Use the matching cApp::receive
function for the cClient::receive function:
bool cApp::receive(const DPNMSG_RECEIVE* msg)
{
sMsg* msg_ptr = (sMsg*) msg->pReceiveData;
switch(msg_ptr->header.type)
{
case MSG_GET_PLAYER_INFO: // add a player to list
case MSG_CREATE_PLAYER:
create_player(msg_ptr);
break;
case MSG_DESTROY_PLAYER: // remove a player from list
destroy_player(msg_ptr);
break;
case MSG_STATE_CHANGE: // change state of player
change_player_state(msg_ptr);
break;
}
return true;
}
Notice that the receive function
immediately processes incoming messages appropriately
by calling separate functions for each type of game message.