⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winmain.cpp

📁 [游戏开发参考书-用DirectX编写RPG游戏]这是一个系列的丛书如果你都看并且懂的话你就可以你工作啦!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**************************************************
WinMain.cpp
Chapter 19 Multiplayer Server Demo

Programming Role-Playing Games with DirectX
by Jim Adams (01 Jan 2002)

Required libraries:
  D3D8.LIB, D3DX8.LIB, DINPUT8.LIB, D3DXOF.LIB,
  DXGUID.LIB, DPNET.LIB, DPLAY.LIB, and DPNADDR.LIB
**************************************************/

#include "Core_Global.h"
#include "Server.h"
#include "WinMain.h"
#include "resource.h"

cApp            *g_Application; // Global application pointer
cNetworkAdapter *g_Adapters;    // Global adapter list pointer

///////////////////////////////////////////////////////////
// cApp overidden virtual functions
///////////////////////////////////////////////////////////
cApp::cApp()
{ 
  // Setup main window information
  m_Width  = 320;
  m_Height = 212;
  m_Style  = WS_BORDER | WS_CAPTION |                         \
             WS_MINIMIZEBOX | WS_SYSMENU;
  m_wcex.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
  strcpy(m_Class, "ServerClass");
  strcpy(m_Caption, "Network Server Demo by Jim Adams");

  // Clear class data
  m_Messages    = NULL;
  m_Players     = NULL;
  m_guidAdapter = NULL;
  g_Application = this;
  g_Adapters    = &m_Adapters;

  // Initialize a critical section for messaging
  InitializeCriticalSection(&m_MessageCS);
}

BOOL cApp::Init()
{
  // Select a network adapter to use (or quit if selected)
  if(SelectAdapter() == FALSE)
    return FALSE;

  // Setup the main interface window
  SetupApplicationWindow();

  // Initialize the game, set video mode, load data, etc
  if(InitializeGame() == FALSE) {
    Error(FALSE, "Unable to initialize game.");
    return FALSE;
  }

  // Begin hosting the game session
  if(HostGame() == FALSE) {
    Error(FALSE, "Unable to host network server.");
    return FALSE;
  }

  return TRUE;
}

BOOL cApp::Shutdown()
{
  // Disconnect network and free interfaces
  m_Adapters.Shutdown();
  m_Server.Disconnect();
  m_Server.Shutdown();

  // Shutdown graphics
  m_LevelMesh.Free();
  m_Graphics.Shutdown();

  // Delete message array
  delete [] m_Messages;
  m_Messages = NULL;

  // Delete players
  delete [] m_Players;
  m_Players = NULL;

  // Free the critical section
  DeleteCriticalSection(&m_MessageCS);

  return TRUE;
}

BOOL cApp::Frame()
{
  static DWORD PlayerCounter = timeGetTime();
  static DWORD NetworkCounter = timeGetTime();
  static DWORD LatencyCounter = timeGetTime();

  // Process some queued network messages
  ProcessQueuedMessages();

  // Update players every 33ms (30 times a second)
  if(timeGetTime() > PlayerCounter + 33) {
    UpdatePlayers();
    PlayerCounter = timeGetTime(); // Reset counter
  }

  // Send out network updates every 100ms (10 times a second)
  if(timeGetTime() > NetworkCounter + 100) {
    UpdateNetwork();
    NetworkCounter = timeGetTime(); // Reset counter
  }

  // Update player latency values every 10 seconds
  if(timeGetTime() > LatencyCounter + 10000) {
    UpdateLatency();
    LatencyCounter = timeGetTime(); // Reset counter
  }

  return TRUE;
}

FAR PASCAL cApp::MsgProc(HWND hWnd, UINT uMsg,                \
                         WPARAM wParam, LPARAM lParam)
{
  switch(uMsg) {
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default: return DefWindowProc(hWnd, uMsg, wParam, lParam);
  }

  return 0;
}    

int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev,          \
                   LPSTR szCmdLine, int nCmdShow)
{
  cApp App;
  return App.Run();  // Run the application instance
}

///////////////////////////////////////////////////////////
// Select adapter dialog and other functions
///////////////////////////////////////////////////////////
BOOL CALLBACK ConfigDialogProc(HWND hWnd, UINT uMsg,          \
                               WPARAM wParam, LPARAM lParam)
{
  long i;
  char Text[256];
  int Selection;
  static HWND hAdapters;

  switch(uMsg) {
    case WM_INITDIALOG:
      // Get adapter list window handle
      hAdapters = GetDlgItem(hWnd, IDC_ADAPTERS);

      // Add adapter names to list
      for(i=0;i<g_Adapters->GetNumAdapters();i++) {
        g_Adapters->GetName(i, Text);
        SendMessage(hAdapters, CB_INSERTSTRING,i,(LPARAM)Text);
      }

      // Select first adapter in list
      SendMessage(hAdapters, CB_SETCURSEL, 0, 0);

      return TRUE;

    case WM_COMMAND:
      switch(LOWORD(wParam)) {

        case IDC_OK:
          // Make sure an adapter was selected
          if((Selection = SendMessage(hAdapters,              \
                                      CB_GETCURSEL,           \
                                      0, 0)) == LB_ERR)
            break;

          // Assign adapter
          if(g_Application != NULL)
            g_Application->SetAdapter(                        \
                           g_Adapters->GetGUID(Selection));

          // Quit dialog
          EndDialog(hWnd, TRUE);
          return TRUE;

        case IDC_CANCEL:
          EndDialog(hWnd, FALSE);
          return TRUE;
      }

  }
  return FALSE;
}

void cApp::SetAdapter(GUID *Adapter)
{
  m_guidAdapter = Adapter;
}

///////////////////////////////////////////////////////////
// Misc. application functions
///////////////////////////////////////////////////////////
void cApp::ListPlayers()
{
  long i;
  char Text[256];

  // Error checking
  if(m_Players == NULL)
    return;

  // Clear player list
  SendMessage(m_Controls[2], LB_RESETCONTENT, 0, 0);

  // Count all players and add names to list
  for(i=0;i<MAX_PLAYERS;i++) {
    if(m_Players[i].Connected == TRUE)
      SendMessage(m_Controls[2], LB_ADDSTRING, 0,             \
                 (LPARAM)m_Players[i].Name);
  }

  // Display player count
  if(!m_NumPlayers)
    SetWindowText(m_Controls[1], "No Connected Players");
  else {
    sprintf(Text, "%lu Players Connected", m_NumPlayers);
    SetWindowText(m_Controls[1], Text);
  }
}

///////////////////////////////////////////////////////////
// Network send and receive functions
///////////////////////////////////////////////////////////
BOOL cApp::SendNetworkMessage(void *Msg, long SendFlags, int To)
{
  sMessageHeader *mh = (sMessageHeader*)Msg;
  unsigned long Size;

  // Get size of message to send
  if((Size = mh->Size) == 0)
    return FALSE;

  // Set destination to all players if To == -1
  if(To == -1)
    To = DPNID_ALL_PLAYERS_GROUP;

  // Send the message
  return m_Server.Send(To, Msg, Size, SendFlags);
}

BOOL cApp::CreatePlayer(DPNMSG_CREATE_PLAYER *Msg)
{
  sCreatePlayerMessage cpm;

  // Setup message data
  cpm.Header.Type     = MSG_CREATE_PLAYER;
  cpm.Header.Size     = sizeof(sCreatePlayerMessage);
  cpm.Header.PlayerID = Msg->dpnidPlayer;

  QueueMessage(&cpm); // Queue the message
  
  return TRUE;
}

BOOL cApp::DestroyPlayer(DPNMSG_DESTROY_PLAYER *Msg)
{
  sDestroyPlayerMessage dpm;

  // Setup message data
  dpm.Header.Type     = MSG_DESTROY_PLAYER;
  dpm.Header.Size     = sizeof(sDestroyPlayerMessage);
  dpm.Header.PlayerID = Msg->dpnidPlayer;
  
  QueueMessage(&dpm); // Queue the message

  return TRUE;
}

BOOL cApp::Receive(DPNMSG_RECEIVE *Msg)
{
  sMessageHeader *mh = (sMessageHeader*)Msg->pReceiveData;

  // Make sure it's a valid message type and queue it
  switch(mh->Type) {
    case MSG_ASSIGNID: 
      // Store player ID before continuing
      mh->PlayerID = Msg->dpnidSender;
    case MSG_PLAYER_INFO:
    case MSG_STATE_CHANGE:
      // Add message to queue
      QueueMessage((void*)Msg->pReceiveData);
      break;
  }

  return TRUE;
}

///////////////////////////////////////////////////////////
// Message queue functions
///////////////////////////////////////////////////////////
BOOL cApp::QueueMessage(void *Msg)
{
  sMessageHeader *mh = (sMessageHeader*)Msg;

  // Error checking - make sure there's a message array
  if(m_Messages == NULL)
    return FALSE;

  // Return if no room left in queue
  if(((m_MsgHead+1) % NUM_MESSAGES) == m_MsgTail)
    return FALSE;

  // Stuff message into queue
  if(mh->Size <= sizeof(sMessage)) {
    // Start the critical section
    EnterCriticalSection(&m_MessageCS);

    memcpy(&m_Messages[m_MsgHead], Msg, mh->Size);

    // Go to next empty message (flip around if at end)
    m_MsgHead++;
    if(m_MsgHead >= NUM_MESSAGES)
      m_MsgHead = 0;

    // Leave the critical section
    LeaveCriticalSection(&m_MessageCS);
  }

  return TRUE;
}

BOOL cApp::PlayerID(sMessage *Msg, DPNID To)
{
  sAssignPlayerIDMessage apidm;

  apidm.Header.Type     = MSG_ASSIGNID;
  apidm.Header.Size     = sizeof(sAssignPlayerIDMessage);
  apidm.Header.PlayerID = To;
  SendNetworkMessage(&apidm, DPNSEND_NOLOOPBACK, To);

  return TRUE;
}

BOOL cApp::PlayerInfo(sMessage *Msg, DPNID To)
{
  sRequestPlayerInfoMessage *rpim;
  sCreatePlayerMessage cpm;
  long i;

  // Error checking
  if(m_Players == NULL)
    return FALSE;

  // Get pointer to request info
  rpim = (sRequestPlayerInfoMessage*)Msg;

  for(i=0;i<MAX_PLAYERS;i++) {
    // Only send if found in list
    if(m_Players[i].dpnidPlayer == rpim->PlayerID &&          \
       m_Players[i].Connected == TRUE) {
 
      // Send player info to requesting player
      cpm.Header.Type     = MSG_PLAYER_INFO;
      cpm.Header.Size     = sizeof(sCreatePlayerMessage);
      cpm.Header.PlayerID = rpim->PlayerID;

      cpm.XPos            = m_Players[i].XPos;
      cpm.YPos            = m_Players[i].YPos;
      cpm.ZPos            = m_Players[i].ZPos;
      cpm.Direction       = m_Players[i].Direction;

      SendNetworkMessage(&cpm, DPNSEND_NOLOOPBACK, To);

      break;
    }
  }

  return TRUE;
}

BOOL cApp::AddPlayer(sMessage *Msg)
{
  long i;
  DWORD Size = 0;
  DPN_PLAYER_INFO *dpi = NULL;
  HRESULT hr;
  DPNID PlayerID;

  // Error checking
  if(m_Players == NULL)
    return FALSE;

  // Get the player ID #
  PlayerID = Msg->Header.PlayerID;

  // Get the player information 
  hr = m_Server.GetServerCOM()->GetClientInfo(PlayerID, dpi,  \
                                              &Size, 0);

  // Return on error or if adding server
  if(FAILED(hr) && hr != DPNERR_BUFFERTOOSMALL)
    return FALSE;

  // Allocate player data buffer and try again
  if((dpi = (DPN_PLAYER_INFO*)new BYTE[Size]) == NULL)
    return FALSE;
  ZeroMemory(dpi, Size);
  dpi->dwSize = sizeof(DPN_PLAYER_INFO);
  if(FAILED(m_Server.GetServerCOM()->GetClientInfo(           \
                                PlayerID, dpi, &Size, 0))) {
    delete [] dpi;
    return FALSE;
  }

  // Make sure not already in list
  for(i=0;i<MAX_PLAYERS;i++) {
    if(m_Players[i].dpnidPlayer == PlayerID &&                \
       m_Players[i].Connected == TRUE) {
      delete [] dpi;
      m_Server.DisconnectPlayer(PlayerID);
      return FALSE;
    }
  }

  // Search for an empty slot to put player
  for(i=0;i<MAX_PLAYERS;i++) {
    if(m_Players[i].Connected == FALSE) {

      m_Players[i].Connected = TRUE; // Flag as connected

      // Save DirectPlay DPNID # and name of player
      m_Players[i].dpnidPlayer = PlayerID;
      wcstombs(m_Players[i].Name, dpi->pwszName, 256);

      // Setup player data
      m_Players[i].XPos      = 0.0f;
      m_Players[i].YPos      = 0.0f;
      m_Players[i].ZPos      = 0.0f;
      m_Players[i].Direction = 0.0f;
      m_Players[i].Speed     = 512.0f;
      m_Players[i].State     = STATE_IDLE;
      m_Players[i].Latency   = 0;

      // Send add player info to all players in area
      sCreatePlayerMessage cpm;
      cpm.Header.Type     = MSG_CREATE_PLAYER;
      cpm.Header.Size     = sizeof(sCreatePlayerMessage);
      cpm.Header.PlayerID = PlayerID;
      cpm.XPos            = m_Players[i].XPos;
      cpm.YPos            = m_Players[i].YPos;
      cpm.ZPos            = m_Players[i].ZPos;
      cpm.Direction       = m_Players[i].Direction;
      SendNetworkMessage(&cpm, DPNSEND_NOLOOPBACK, -1);

      ListPlayers();        // List all players

      delete [] dpi;        // Free player data

      return TRUE;          // Return success
    }
  }

  delete[] dpi;  // Free player data

  // Disconnect player - not allowed to connect
  m_Server.DisconnectPlayer(PlayerID);

  return FALSE;  // Return failure
}

BOOL cApp::RemovePlayer(sMessage *Msg)
{
  long i;

  // Error checking
  if(m_Players == NULL)
    return FALSE;

  // Search for player in list
  for(i=0;i<MAX_PLAYERS;i++) {
    if(m_Players[i].dpnidPlayer == Msg->Header.PlayerID &&    \
       m_Players[i].Connected == TRUE) {

      m_Players[i].Connected = FALSE;  // Disconnect player

      // Send remove player message to all players in area
      sDestroyPlayerMessage dpm;
      dpm.Header.Type     = MSG_DESTROY_PLAYER;
      dpm.Header.Size     = sizeof(sDestroyPlayerMessage);
      dpm.Header.PlayerID = Msg->Header.PlayerID;
      SendNetworkMessage(&dpm, DPNSEND_NOLOOPBACK, -1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -