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

📄 winmain.cpp

📁 [游戏开发参考书-用DirectX编写RPG游戏]这是一个系列的丛书如果你都看并且懂的话你就可以你工作啦!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**************************************************
WinMain.cpp
Chapter 19 Multiplayer Client 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 "Frustum.h"
#include "NodeTree.h"
#include "WinMain.h"
#include "resource.h"

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

BOOL             g_Connected = FALSE;  // Connection status

///////////////////////////////////////////////////////////
// cApp functions
///////////////////////////////////////////////////////////
cApp::cApp()
{ 
  // Setup main window information
  m_Width  = 640; 
  m_Height = 480;
  m_Style  = WS_BORDER | WS_CAPTION |                         \
             WS_MINIMIZEBOX | WS_SYSMENU;
  strcpy(m_Class, "ClientClass");
  strcpy(m_Caption, "Network Client Demo by Jim Adams");

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

  // Create a critical section for updating data
	InitializeCriticalSection(&m_UpdateCS);
}

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

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

  // Join networked game
  if(JoinGame() == FALSE) {
    Error(FALSE, "Unable to connect to server.");
    return FALSE;
  }

  return TRUE;
}

BOOL cApp::Shutdown()
{
  // Shutdown network
  m_Adapters.Shutdown();
  m_Client.Disconnect();
  m_Client.Shutdown();

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

  // Free meshes
  m_NodeTreeMesh.Free();
  m_TerrainMesh.Free();

  m_CharacterMesh.Free();
  m_WeaponMesh.Free();
  m_CharacterAnim.Free();

  // Shutdown input
  m_Keyboard.Free();
  m_Mouse.Free();
  m_Input.Shutdown();

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

  // Remove critical section
  DeleteCriticalSection(&m_UpdateCS);

  return TRUE;
}

BOOL cApp::Frame()
{
  static DWORD UpdateCounter  = timeGetTime();
  static long MoveAction = 0, LastMove = 0;
  static BOOL CamMoved = FALSE;
  BOOL AllowMovement;
  long Dir;
  float 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 };

  // Get local input every frame 
  m_Keyboard.Acquire(TRUE);  
  m_Mouse.Acquire(TRUE);     
  m_Keyboard.Read();
  m_Mouse.Read();

  // Pressing ESC quits program
  if(m_Keyboard.GetKeyState(KEY_ESC) == TRUE)
    return FALSE;

  // Handle connection and waiting for data screen
  if(g_Connected == FALSE || !m_Players[0].dpnidPlayer) {

    // Display message(s)
    m_Graphics.Clear();
    if(m_Graphics.BeginScene() == TRUE) {
      m_Font.Print("Connecting to server...", 0, 0);
      if(!m_Players[0].dpnidPlayer)
        m_Font.Print("Waiting for server data...", 0, 20);
      m_Graphics.EndScene();
    }
    m_Graphics.Display();

    // Request player ID from server every 2 seconds
    if(timeGetTime() > UpdateCounter + 2000) {
      UpdateCounter = timeGetTime();  // Update counter

      sAssignPlayerIDMessage apidm;
      apidm.Header.Type = MSG_ASSIGNID;
      apidm.Header.Size = sizeof(sAssignPlayerIDMessage);
      SendNetworkMessage(&apidm, DPNSEND_NOLOOPBACK |         \
                                 DPNSEND_GUARANTEED);
    }

    return TRUE;
  }

  // Store movements every frame
  if(m_Keyboard.GetKeyState(KEY_UP) == TRUE)
    MoveAction |= 1;
  if(m_Keyboard.GetKeyState(KEY_RIGHT) == TRUE)
    MoveAction |= 2;
  if(m_Keyboard.GetKeyState(KEY_DOWN) == TRUE)
    MoveAction |= 4;
  if(m_Keyboard.GetKeyState(KEY_LEFT) == TRUE)
    MoveAction |= 8;
  
  // Store attack action
  if(m_Keyboard.GetKeyState(KEY_SPACE) == TRUE)
    MoveAction |= 16;
  if(m_Mouse.GetButtonState(MOUSE_LBUTTON) == TRUE)
    MoveAction |= 16;

  // Rotate camera
  if(m_Mouse.GetXDelta() > 0) {
    m_CamAngle -= 0.1f;
    CamMoved = TRUE;
  }
  if(m_Mouse.GetXDelta() < 0) {
    m_CamAngle += 0.1f;
    CamMoved = TRUE;
  }

  // Only update players every 33ms (30 times a second)
  if(timeGetTime() < UpdateCounter + 33)
    return TRUE;

  // Set flag to allow player movement
  AllowMovement = TRUE;

  // Don't allow movement if still swinging weapon
  if(m_Players[0].State == STATE_SWING)
    AllowMovement = FALSE;

  // Don't allow movement if still being hurt
  if(m_Players[0].State == STATE_HURT)
    AllowMovement = FALSE;

  // Handle movements if allowed
  if(AllowMovement == TRUE) {

    // Process attack
    if(MoveAction & 16) {
      MoveAction = 0;  // Clear movement
      LastMove = 0;    // Clear last movement

      // Send attack message - let server signal swing
      sStateChangeMessage Msg;
      Msg.Header.Type     = MSG_STATE_CHANGE;
      Msg.Header.Size     = sizeof(sStateChangeMessage);
      Msg.Header.PlayerID = m_Players[0].dpnidPlayer;
      Msg.State           = STATE_SWING;
      Msg.Direction       = m_Players[0].Direction;

      // Send message to server
      SendNetworkMessage(&Msg, DPNSEND_NOLOOPBACK);
    }

    // Process local player movements
    if((Dir = MoveAction) > 0 && Dir < 13) {
      // Set new player state (w/time and direction)
      EnterCriticalSection(&m_UpdateCS);
      m_Players[0].State     = STATE_MOVE;
      m_Players[0].Direction = Angles[Dir] - m_CamAngle + 4.71f;
      LeaveCriticalSection(&m_UpdateCS);

      // Reset last move if camera moved since last update
      if(CamMoved == TRUE) {
        CamMoved = FALSE;
        LastMove = 0;
      }

      // Send actions to server if changed from last move
      if(MoveAction != LastMove) {
        LastMove = MoveAction;  // Store last action

        m_Players[0].Time = timeGetTime();

        // Construct message
        sStateChangeMessage Msg;
        Msg.Header.Type     = MSG_STATE_CHANGE;
        Msg.Header.Size     = sizeof(sStateChangeMessage);
        Msg.Header.PlayerID = m_Players[0].dpnidPlayer;
        Msg.State           = STATE_MOVE;
        Msg.Direction       = m_Players[0].Direction;

        // Send message to server
        SendNetworkMessage(&Msg, DPNSEND_NOLOOPBACK);
      }
    } else {
      // Change to idle state
      EnterCriticalSection(&m_UpdateCS);
      m_Players[0].State = STATE_IDLE;
      LeaveCriticalSection(&m_UpdateCS);

      // Send update only if player moved last update
      if(LastMove) {
        LastMove = 0;

        sStateChangeMessage Msg;
        Msg.Header.Type     = MSG_STATE_CHANGE;
        Msg.Header.Size     = sizeof(sStateChangeMessage);
        Msg.Header.PlayerID = m_Players[0].dpnidPlayer;
        Msg.State           = STATE_IDLE;
        Msg.Direction       = m_Players[0].Direction;

        // Send message to server
        SendNetworkMessage(&Msg, DPNSEND_NOLOOPBACK);
      }
    }
  }

  // Update all players
  UpdatePlayers();

  // Render the scene
  RenderScene();

  MoveAction = 0; // Clear action data for next frame

  UpdateCounter = timeGetTime(); // Reset update counter

  return TRUE;
}

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

///////////////////////////////////////////////////////////
// Select adapter dialog and other functions
///////////////////////////////////////////////////////////
BOOL CALLBACK ConnectDialogProc(HWND hWnd, UINT uMsg,         \
                                WPARAM wParam, LPARAM lParam)
{
  int Selection;
  long i;
  char Name[32], IP[16], Text[256];
  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);

      // Clear fields
      SetWindowText(GetDlgItem(hWnd, IDC_HOSTIP), "127.0.0.1");
      SetWindowText(GetDlgItem(hWnd, IDC_NAME), "");

      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;

          // Make sure there's an IP entered
          GetWindowText(GetDlgItem(hWnd, IDC_HOSTIP), IP, 16);
          if(!strlen(IP))
            break;

          // Make sure there's a name entered
          GetWindowText(GetDlgItem(hWnd, IDC_NAME), Name, 32);
          if(!strlen(Name))
            break;

          // Assign Adapter, IP, and Name
          if(g_Application != NULL)
            g_Application->SetInfo(                           \
                    g_Adapters->GetGUID(Selection), IP, Name);

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

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

  }
  return FALSE;
}

void cApp::SetInfo(GUID *Adapter, char *IP, char *Name)
{
  m_guidAdapter = Adapter;
  strcpy(m_HostIP, IP);
  strcpy(m_Name, Name);
}

///////////////////////////////////////////////////////////
// Misc. application functions
///////////////////////////////////////////////////////////
long cApp::GetPlayerNum(DPNID dpnidPlayer)
{
  long i;

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

  // Scan list looking for match
  for(i=0;i<MAX_PLAYERS;i++) {
    if(m_Players[i].dpnidPlayer == dpnidPlayer &&             \
       m_Players[i].Connected == TRUE)
      return i;
  }

  return -1;  // Not found in list
}

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

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

  // Send the mesage
  return m_Client.Send(Msg, Size, SendFlags);
}

BOOL cApp::Receive(DPNMSG_RECEIVE *Msg)
{
  sMessage *MsgPtr;

  // Get pointer to received data
  MsgPtr = (sMessage*)Msg->pReceiveData;

  // Handle packets by type
  switch(MsgPtr->Header.Type) {
    case MSG_ASSIGNID:       // Assign local player ID
      AssignID(MsgPtr);
      break;

    case MSG_PLAYER_INFO:    // Add a player to list
    case MSG_CREATE_PLAYER:
      CreatePlayer(MsgPtr);
      break;

    case MSG_DESTROY_PLAYER: // Remove a player from list
      DestroyPlayer(MsgPtr);
      break;

    case MSG_STATE_CHANGE:   // Change state of player
      ChangeState(MsgPtr);
      break;
  }

  return TRUE;
}

///////////////////////////////////////////////////////////
// Message parsing functions

⌨️ 快捷键说明

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