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

📄 winmain.cpp

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

      // List all players
      ListPlayers();

      return TRUE;
    }
  }

  return FALSE;  // Return failure
}

BOOL cApp::PlayerStateChange(sMessage *Msg)
{
  sStateChangeMessage *scm, uscm;
  long i, PlayerNum;
  BOOL AllowChange;
  float XDiff, ZDiff, Dist, Angle;

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

  // Get pointer to state change message
  scm = (sStateChangeMessage*)Msg;

  // Get player number in list
  PlayerNum = -1;
  for(i=0;i<MAX_PLAYERS;i++) {
    if(m_Players[i].dpnidPlayer == Msg->Header.PlayerID &&    \
       m_Players[i].Connected == TRUE) {
      PlayerNum = i;
      break;
    }
  }
  if(PlayerNum == -1)
    return FALSE;

  AllowChange = TRUE;  // Flag to allow changes in state

  // Refuse to update player if swinging sword
  if(m_Players[PlayerNum].State == STATE_SWING)
    AllowChange = FALSE;

  // Refuse to update player if hurt
  if(m_Players[PlayerNum].State == STATE_HURT)
    AllowChange = FALSE;

  // Only change state if allowed
  if(AllowChange == TRUE) {

    // Update selected player
    m_Players[PlayerNum].Time      = timeGetTime();
    m_Players[PlayerNum].State     = scm->State;
    m_Players[PlayerNum].Direction = scm->Direction;

    // Adjust action time based on latency
    m_Players[PlayerNum].Time -= m_Players[PlayerNum].Latency;

    // Send player data to all clients
    uscm.Header.Type     = MSG_STATE_CHANGE;
    uscm.Header.Size     = sizeof(sStateChangeMessage);
    uscm.Header.PlayerID = scm->Header.PlayerID;
    uscm.State           = m_Players[PlayerNum].State;
    uscm.XPos            = m_Players[PlayerNum].XPos;
    uscm.YPos            = m_Players[PlayerNum].YPos;
    uscm.ZPos            = m_Players[PlayerNum].ZPos;
    uscm.Direction       = m_Players[PlayerNum].Direction;
    uscm.Speed           = m_Players[PlayerNum].Speed;
    SendNetworkMessage(&uscm, DPNSEND_NOLOOPBACK);

    // If swinging sword, determine who's hurt
    if(scm->State == STATE_SWING) {

      // Check all players
      for(i=0;i<MAX_PLAYERS;i++) {
        
        // Only check against other players that are connected
        if(i != PlayerNum && m_Players[i].Connected == TRUE) {

          // Get distance to player
          XDiff = (float)fabs(m_Players[PlayerNum].XPos -     \
                              m_Players[i].XPos);
          ZDiff = (float)fabs(m_Players[PlayerNum].ZPos -     \
                              m_Players[i].ZPos);
          Dist = XDiff*XDiff + ZDiff*ZDiff;

          // Continue if distance between players acceptable
          if(Dist < 10000.0f) {
            
            // Get angle between players
            Angle = -(float)atan2(                            \
                           (m_Players[i].ZPos -               \
                            m_Players[PlayerNum].ZPos),       \
                           (m_Players[i].XPos -               \
                            m_Players[PlayerNum].XPos)) +     \
                            1.570796f;

             // Adjust for attacker's direction
            Angle -= m_Players[PlayerNum].Direction;

            Angle += 0.785f; // Adjust for FOV

            // Bounds angle value
            if(Angle < 0.0f)
              Angle += 6.28f;
            if(Angle >= 6.28f)
              Angle -= 6.28f;
                       
            // Player hit if in front of attacker (90 FOV)
            if(Angle >= 0.0f && Angle <= 1.570796f) {

              // Set victim's state to hurt (if not already)
              if(m_Players[i].State != STATE_HURT) {
                m_Players[i].State = STATE_HURT;
                m_Players[i].Time = timeGetTime();

                // Send network message
                uscm.Header.Type = MSG_STATE_CHANGE;
                uscm.Header.Size = sizeof(sStateChangeMessage);
                uscm.Header.PlayerID = m_Players[i].dpnidPlayer;
                uscm.State = m_Players[i].State;
                uscm.XPos = m_Players[i].XPos;
                uscm.YPos = m_Players[i].YPos;
                uscm.ZPos = m_Players[i].ZPos;
                uscm.Direction = m_Players[i].Direction;
                uscm.Speed = m_Players[i].Speed;
                SendNetworkMessage(&uscm, DPNSEND_NOLOOPBACK);
              }
            }
          }
        }
      }
    }
  }

  return TRUE;
}

///////////////////////////////////////////////////////////
// App initialization functions
///////////////////////////////////////////////////////////
BOOL cApp::SelectAdapter()
{
  int Result;

  // Hide main window
  ShowWindow(GethWnd(), SW_HIDE);

  // Build a list of network adapters
  m_Adapters.Init();

  // Open configure dialog
  Result = DialogBox(GethInst(), MAKEINTRESOURCE(IDD_CONFIG), \
                     GethWnd(), ConfigDialogProc);

  // Don't continue if quit selected
  if(Result == FALSE)
    return FALSE;

  // Continue if user selected OK
  return TRUE;
}

void cApp::SetupApplicationWindow()
{
  // Create the windows controls

  // Window to hold host IP address
  m_Controls[0] = CreateWindow("STATIC", "",                  \
          WS_CHILD | WS_VISIBLE,                              \
          4, 4, 312, 18,                                      \
          GethWnd(), NULL, GethInst(), NULL);

  // Window to hold # of connected players
  m_Controls[1] = CreateWindow("STATIC",                      \
          "No Connected Players",                             \
          WS_CHILD | WS_VISIBLE,                              \
          4, 26, 312, 18,                                     \
          GethWnd(), NULL, GethInst(), NULL);

  // List box to display connect player's names
  m_Controls[2] = CreateWindow("LISTBOX", "",                 \
          WS_CHILD | WS_BORDER | WS_VSCROLL | WS_VISIBLE,     \
          4, 48, 312, 154,                                    \
          GethWnd(), NULL, GethInst(), NULL);   

  // Show main window
  ShowWindow(GethWnd(), SW_SHOW);
}

BOOL cApp::InitializeGame()
{
  // Initialize the graphics device and set display mode
  m_Graphics.Init();
  m_Graphics.SetMode(GethWnd());

  // Load the level mesh for collision checking
  m_LevelMesh.Load(&m_Graphics, "..\\Data\\ArenaCM.x");

  // Allocate message queue and reset message pointers
  m_Messages = new sMessage[NUM_MESSAGES]();
  m_MsgHead = m_MsgTail = 0;

  // Create player structures
  m_Players = new sPlayer[MAX_PLAYERS]();

  // Reset # of players
  m_NumPlayers = 0;

  return TRUE;
}

BOOL cApp::HostGame()
{
  char Text[33], IP[16];

  // Configure server and begin hosting
  m_Server.Init();
  if(m_Server.Host(m_guidAdapter, 9123,                       \
                  "RPGGAME", NULL, MAX_PLAYERS) == FALSE)
    return FALSE;

  // Get Server IP address and display in application window
  m_Server.GetIP(IP);
  sprintf(Text, "Host IP Address: %s", IP);
  SetWindowText(m_Controls[0], Text);

  return TRUE;  // Return success
}

///////////////////////////////////////////////////////////
// Game message queue processing and update functions
///////////////////////////////////////////////////////////
void cApp::ProcessQueuedMessages()
{
  sMessage *Msg;
  long Count = 0;

  // Pull out messages to process
  while(Count != MESSAGES_PER_FRAME && m_MsgHead != m_MsgTail) {

    // Get pointer to 'tail' message
    EnterCriticalSection(&m_MessageCS);
    Msg = &m_Messages[m_MsgTail];
    LeaveCriticalSection(&m_MessageCS);

    // Process a single message based on type
    switch(Msg->Header.Type) {
      case MSG_ASSIGNID: // Send users their player ID
        PlayerID(Msg, Msg->Header.PlayerID);
        break;

      case MSG_PLAYER_INFO:    // Request player info
        PlayerInfo(Msg, Msg->Header.PlayerID);
        break;

      case MSG_CREATE_PLAYER:  // Add a player
        AddPlayer(Msg);
        break;

      case MSG_DESTROY_PLAYER: // Remove a player
        RemovePlayer(Msg);
        break;

      case MSG_STATE_CHANGE:   // Change state of player
        PlayerStateChange(Msg);
        break;
    }

    Count++; // Increase processed message count

    // Goto next message in list
    EnterCriticalSection(&m_MessageCS);
    m_MsgTail = (m_MsgTail + 1) % NUM_MESSAGES;
    LeaveCriticalSection(&m_MessageCS);
  }
}

void cApp::UpdatePlayers()
{
  long i;
  float XMove, ZMove, Speed;
  sStateChangeMessage scm;
  long Elapsed;

  // Loop through all players
  for(i=0;i<MAX_PLAYERS;i++) {

    // Only update connected players
    if(m_Players[i].Connected == TRUE) {

      // Get elapsed time from now and state time
      Elapsed = timeGetTime() - m_Players[i].Time;

      // Process player movement state
      if(m_Players[i].State == STATE_MOVE) {
        // Calculate amount of movement by time passed
        Speed = (float)Elapsed / 1000.0f * m_Players[i].Speed;
        XMove = (float)sin(m_Players[i].Direction) * Speed;
        ZMove = (float)cos(m_Players[i].Direction) * Speed;

        // Check for movement collisions -
        // can't walk past anything blocking path.
        if(CheckIntersect(&m_LevelMesh,                       \
                          m_Players[i].XPos,                  \
                          m_Players[i].YPos + 16.0f,          \
                          m_Players[i].ZPos,                  \
                          m_Players[i].XPos + XMove,          \
                          m_Players[i].YPos + 16.0f,          \
                          m_Players[i].ZPos + ZMove) == TRUE)
          XMove = ZMove = 0.0f;

        // Update player coordinates
        m_Players[i].XPos += XMove;
        m_Players[i].YPos = 0.0f;    // Stay on ground
        m_Players[i].ZPos += ZMove;

        m_Players[i].Time = timeGetTime();  // Reset time
      }

      // Clear swing status after 1 second
      if(m_Players[i].State == STATE_SWING) {
        if(Elapsed > 1000) {
          m_Players[i].State = STATE_IDLE;

          // Send network message to player to clear
          scm.Header.Type     = MSG_STATE_CHANGE;
          scm.Header.Size     = sizeof(sStateChangeMessage);
          scm.Header.PlayerID = m_Players[i].dpnidPlayer;
          scm.XPos            = m_Players[i].XPos;
          scm.YPos            = m_Players[i].YPos;
          scm.ZPos            = m_Players[i].ZPos;
          scm.Direction       = m_Players[i].Direction;
          scm.Speed           = m_Players[i].Speed;
          scm.State           = m_Players[i].State;

          // Send the message over network
          SendNetworkMessage(&scm, DPNSEND_NOLOOPBACK, -1);
        }
      }

      // Clear hurt status after 1 second
      if(m_Players[i].State == STATE_HURT) {
        if(Elapsed > 1000) {
          m_Players[i].State = STATE_IDLE;

          // Send network message to player to clear
          scm.Header.Type     = MSG_STATE_CHANGE;
          scm.Header.Size     = sizeof(sStateChangeMessage);
          scm.Header.PlayerID = m_Players[i].dpnidPlayer;
          scm.XPos            = m_Players[i].XPos;
          scm.YPos            = m_Players[i].YPos;
          scm.ZPos            = m_Players[i].ZPos;
          scm.Direction       = m_Players[i].Direction;
          scm.Speed           = m_Players[i].Speed;
          scm.State           = m_Players[i].State;

          // Send the message over network
          SendNetworkMessage(&scm, DPNSEND_NOLOOPBACK, -1);
        }
      }
    }
  }
}

void cApp::UpdateNetwork()
{
  long i;
  sStateChangeMessage scm;

  // Send all player updates
  for(i=0;i<MAX_PLAYERS;i++) {

    // Only send data about connected players
    if(m_Players[i].Connected == TRUE) {
      scm.Header.Type     = MSG_STATE_CHANGE;
      scm.Header.Size     = sizeof(sStateChangeMessage);
      scm.Header.PlayerID = m_Players[i].dpnidPlayer;
      scm.XPos            = m_Players[i].XPos;
      scm.YPos            = m_Players[i].YPos;
      scm.ZPos            = m_Players[i].ZPos;
      scm.Direction       = m_Players[i].Direction;
      scm.Speed           = m_Players[i].Speed;
      scm.State           = m_Players[i].State;
      scm.Latency         = m_Players[i].Latency;

      // Send the message over network
      SendNetworkMessage(&scm, DPNSEND_NOLOOPBACK);
    }
  }
}

void cApp::UpdateLatency()
{
  long i;
  DPN_CONNECTION_INFO dpci;
  HRESULT hr;

  // Go through all players
  for(i=0;i<MAX_PLAYERS;i++) {
    
    // Only process connected players
    if(m_Players[i].Connected == TRUE) {

      // Request player connection settings
      hr = m_Server.GetServerCOM()->GetConnectionInfo(        \
                   m_Players[i].dpnidPlayer, &dpci, 0);

      if(SUCCEEDED(hr)) {
        m_Players[i].Latency = dpci.dwRoundTripLatencyMS / 2;

        // Bounds latency to 1 second
        if(m_Players[i].Latency > 1000)
          m_Players[i].Latency = 1000;

      } else {
        m_Players[i].Latency = 0;
      }
    }
  }
}

///////////////////////////////////////////////////////////
// Game logic functions
///////////////////////////////////////////////////////////
BOOL cApp::CheckIntersect(cMesh *Mesh,                        \
                 float XStart, float YStart, float ZStart,    \
                 float XEnd,   float YEnd,   float ZEnd)
{
  sMesh *MeshPtr;
  BOOL  Hit;
  float u, v, Dist;
  float XDiff, YDiff, ZDiff, Size;
  DWORD FaceIndex;
  D3DXVECTOR3 vecDir;

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

  // Start with parent mesh
  if((MeshPtr = Mesh->GetParentMesh()) == NULL)
    return FALSE;

  // Calculate ray
  XDiff = XEnd - XStart;
  YDiff = YEnd - YStart;
  ZDiff = ZEnd - ZStart;
  D3DXVec3Normalize(&vecDir, &D3DXVECTOR3(XDiff, YDiff, ZDiff));

  // Go through each mesh looking for intersection
  while(MeshPtr != NULL) {
    D3DXIntersect(MeshPtr->m_Mesh,                            \
                &D3DXVECTOR3(XStart,YStart,ZStart), &vecDir,  \
                &Hit, &FaceIndex, &u, &v, &Dist);

    if(Hit == TRUE) {
      Size = (float)sqrt(XDiff*XDiff+YDiff*YDiff+ZDiff*ZDiff);
      if(Dist <= Size)
        return TRUE;
    }

    MeshPtr = MeshPtr->m_Next;
  }

  return FALSE;
}

///////////////////////////////////////////////////////////
// Server class code
///////////////////////////////////////////////////////////
BOOL cServer::CreatePlayer(DPNMSG_CREATE_PLAYER *Msg)
{
  // Send message to application class instance (if any)
  if(g_Application != NULL)
    g_Application->CreatePlayer(Msg);
 
  return TRUE;
}

BOOL cServer::DestroyPlayer(DPNMSG_DESTROY_PLAYER *Msg)
{
  // Send message to application class instance (if any)
  if(g_Application != NULL)
    g_Application->DestroyPlayer(Msg);
  return TRUE;
}

BOOL cServer::Receive(DPNMSG_RECEIVE *Msg)
{
  // Send message to application class instance (if any)
  if(g_Application != NULL)
    g_Application->Receive(Msg);
  return TRUE;
}

⌨️ 快捷键说明

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