Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming / GameProg / RPG_Programming_2ed.pdf
Скачиваний:
243
Добавлен:
12.02.2016
Размер:
12.06 Mб
Скачать

Джим Адамс

Чтобы применить предоставляемую данным классом возможность воспроизведения MP3, воспользуйтесь следующим фрагментом кода:

cMP3 MP3;

//Инициализация объекта класса

MP3.Init();

//Визуализация файла и начало воспроизведения if(MP3.Render("song.mp3") == TRUE)

MP3.Play();

//Ждем завершения песни

while(MP3.Playing() == TRUE);

// Выключаем все

MP3.Shutdown();

Сетевое ядро

В предыдущей главе вы увидели, как просто использовать DirectPlay. Теперь

вы узнаете, как работать с DirectPlay, используя сетевое ядро. Сетевое ядро содержит три класса: cNetworkAdapter, cNetworkServer и cNetworkClient.

Запрос адаптера с cNetworkAdapter

Вы используете cNetworkAdapter для перечисления установленных в

вашей системе TCP/IP-устройств. Чтобы установить соединение вам

необходимо знать GUID устройства, и его получение является целью класса cNetworkAdapter. Вот как выглядит объявление класса:

class cNetworkAdapter

 

 

{

 

 

protected:

 

Список адаптеров

DPN_SERVICE_PROVIDER_INFO *m_AdapterList; //

unsigned long m_NumAdapters;

//

Количество адаптеров

// Пустой обработчик сетевых сообщений – необходим static HRESULT WINAPI NetMsgHandler(

PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer) { return S_OK; }

public:

cNetworkAdapter(); // Конструктор ~cNetworkAdapter(); // Деструктор

BOOL

Init();

//

Инициализация объекта класса

BOOL

Shutdown(); //

Завершение работы объекта

 

 

//

(освобождение памяти)

long GetNumAdapters(); // Получение количества

//установленных адаптеров

//Сохранение имени адаптера в буфере

//(Num от 0 до количества адаптеров минус 1)

BOOL GetName(unsigned long Num, char *Buf);

netlib.narod.ru

341

Глава 6. Создаем ядро игры

//Возвращает указатель на GUID адаптера

//(Num от 0 до количества адаптеров минус 1)

GUID *GetGUID(unsigned long Num);

};

Использовать класс cNetworkAdapter просто: вызовите функцию Init, запросите количество установленных адаптеров, а затем начинайте извлекать имена адаптеров и их GUID. Когда завершите работу с объектом, вызовите Shutdown для освобождения внутренних ресурсов класса.

Я вернусь к использованию класса cNetworkAdapter в следующих двух подразделах. А сейчас давайте перейдем к классу cNetworkServer.

Серверы и cNetworkServer

На серверной стороне сети вы имеете дело с классом cNetworkServer,

который позволяет инициализировать серверные объекты DirectPlay, открыть игровую сессию и обрабатывать входящие и исходящие сетевые

сообщения. В данном разделе вы увидите, как я оборачиваю операции серверной стороны в представленный ниже класс cNetworkServer:

class cNetworkServer

{

protected:

IDirectPlay8Server *m_pDPServer; // Объект сервера

BOOL m_Connected;

// Флаг запуска узла

// Имя и пароль сессии (хранятся как ASCII-символы) char m_SessionName[MAX_PATH];

char m_SessionPassword[MAX_PATH];

long m_Port;

//

Используемый порт

long m_MaxPlayers; //

Максимально допустимое

 

//

количество игроков

long m_NumPlayers; //

Текущее количество игроков

// Обработчик сетевых

сообщений

static HRESULT WINAPI NetworkMessageHandler( PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer);

// Перегружаемые функции для различных // сетевых сообщений

virtual BOOL AddPlayerToGroup( DPNMSG_ADD_PLAYER_TO_GROUP *Msg) { return TRUE; }

virtual BOOL AsyncOpComplete( DPNMSG_ASYNC_OP_COMPLETE *Msg) { return TRUE; }

virtual BOOL ClientInfo(

DPNMSG_CLIENT_INFO *Msg) { return TRUE; } virtual BOOL ConnectComplete(

DPNMSG_CONNECT_COMPLETE *Msg) { return TRUE; } virtual BOOL CreateGroup(

 

DPNMSG_CREATE_GROUP *Msg) { return TRUE; }

 

virtual BOOL CreatePlayer(

 

DPNMSG_CREATE_PLAYER *Msg) { return TRUE; }

 

virtual BOOL DestroyGroup(

 

DPNMSG_DESTROY_GROUP *Msg) { return TRUE; }

 

 

342

netlib.narod.ru

Джим Адамс

virtual BOOL DestroyPlayer( DPNMSG_DESTROY_PLAYER *Msg) { return TRUE; }

virtual BOOL EnumHostsQuery( DPNMSG_ENUM_HOSTS_QUERY *Msg) { return TRUE; }

virtual BOOL EnumHostsResponse( DPNMSG_ENUM_HOSTS_RESPONSE *Msg) { return TRUE; }

virtual BOOL GroupInfo(

DPNMSG_GROUP_INFO *Msg) { return TRUE; } virtual BOOL HostMigrate(

DPNMSG_HOST_MIGRATE *Msg) { return TRUE; } virtual BOOL IndicateConnect(

DPNMSG_INDICATE_CONNECT *Msg) { return TRUE; } virtual BOOL IndicatedConnectAborted(

DPNMSG_INDICATED_CONNECT_ABORTED *Msg) { return TRUE; } virtual BOOL PeerInfo(

DPNMSG_PEER_INFO *Msg) { return TRUE; } virtual BOOL Receive(

DPNMSG_RECEIVE *Msg) { return TRUE; } virtual BOOL RemovePlayerFromGroup(

DPNMSG_REMOVE_PLAYER_FROM_GROUP *Msg) { return TRUE; } virtual BOOL ReturnBuffer(

DPNMSG_RETURN_BUFFER *Msg) { return TRUE; } virtual BOOL SendComplete(

DPNMSG_SEND_COMPLETE *Msg) { return TRUE; } virtual BOOL ServerInfo(

DPNMSG_SERVER_INFO *Msg) { return TRUE; } virtual BOOL TerminateSession(

DPNMSG_TERMINATE_SESSION *Msg) { return TRUE; }

public:

cNetworkServer(); // Конструктор ~cNetworkServer(); // Деструктор

IDirectPlay8Server *GetServerCOM(); // Возвращает объект сервера

BOOL Init();

//

Инициализирует сетевой сервер

BOOL Shutdown(); //

Выключает сетевой сервер

// Начинает сессию на узле

BOOL Host(GUID

*guidAdapter, long Port,

char

*SessionName, char *Password = NULL,

long

MaxPlayers = 0);

BOOL Disconnect();

// Завершение сессии

BOOL IsConnected();

// Проверяет, запущена ли сессия

// Передача необработанных данных или текстовой строки

BOOL Send(DPNID dpnidPlayer, void *Data,

unsigned long Size, unsigned long Flags=0); BOOL SendText(DPNID dpnidPlayer, char *Text,

unsigned long Flags=0);

//Принудительное отключение игрока

BOOL DisconnectPlayer(long PlayerId);

//Получение IP-адреса игрока или сервера в указанный буфер

BOOL GetIP(char *IPAddress, unsigned long PlayerId = 0);

//Получение имени игрока

BOOL GetName(char *Name, unsigned long PlayerId);

// Получение номера используемого порта long GetPort();

netlib.narod.ru

343

Глава 6. Создаем ядро игры

//Иолучение имени сессии и пароля

BOOL GetSessionName(char *Buf); BOOL GetSessionPassword(char *Buf);

//Получение максимально возможного и текущего

//количества игроков

long GetMaxPlayers(); long GetNumPlayers();

};

Для того, чтобы использовать класс cNetworkServer (точно так же как и класс cNetworkClient, о котором мы поговорим в следующем разделе), вы наследуете собственный класс, используя cNetworkServer в

качестве базового. Это необходимо потому что требуется перегрузка

обработчиков сообщений вашими собственными функциями. В классе cNetworkServer представлены все сетевые сообщения, так что

наследуемый класс не пропустит важной информации.

Чтобы начать сессию вам необходим GUID адаптера, имя сессии,

необязательный пароль и максимально возможное количество игроков (0 означает, что ограничений нет). При вызове cNetworkServer::Host

DirectPlay инициализирует подключения и возвращает управление вам. После этого вы можете начать ожидание входящих сообщений. Ваша работа — закачивать входящие сообщения и поступать с ними так, как считаете нужным. Создаваемые вами обработчики сообщений должны возвращать TRUE, если сообщение успешно обработано, и FALSE, если произошла ошибка.

В качестве примера здесь приведен экземпляр класса cNetworkServer, который отображает текст входящего сообщения и

отсылает точно такое же сообщение назад отправителю (используя гарантированную доставку):

// Создаем класс-наследник

class cServer : public cNetworkServer

{

private:

BOOL Receive(DPNMSG_RECEIVE *Msg);

};

BOOL cServer::Receive(DPNMSG_RECEIVE *Msg)

{

// Отображаем сообщение

MessageBox(NULL, Msg->pReceivedData, "Incoming Message", MB_OK);

// Отправляем его обратно

Send(Msg->dpnidSender, Msg->pReceiveData, Msg->dwReceivedDataSize, DPNSEND_GUARANTEED);

return TRUE;

}

344

netlib.narod.ru

Соседние файлы в папке GameProg