把我以前學習過的一個東西拿出來分享下~
3D伺服器端玩家行走處理是伺服器端根據客戶端行走路徑、玩家行走時間以及速度(包括變化速度)計算得出玩家的當前位置。
由於客戶端行走是一條路徑,不使用2D中的格子計算演算法,未能高效的獲取角色的當前位置,運用玩家行走路徑,行走速度,行走時間這些已量,進行計算玩家的當前精確位置。由於3D遊戲中的點為xyz的空間點,所以牽連的計算為3維向量計算。
空間兩點距離計算公式為:
玩家在某條線段上的座標x:
玩家在某條線段上的座標y:
玩家在某條線段上的座標z:
角色當前位置計算原理分析:
角色行走是一條路徑,這條路徑使用點序列表示,角色開始行走記錄當前時間TimeStart,獲取覺得當前位置的計算,首先獲取當前時間TimeNow,根據TimeNow-TimeStart的時間差與角色的行走速度,獲取角色已經行走過的距離distance,計算每兩點的距離,判定角色當前時間所處在哪一條路徑上,及角色在哪兩點之間。然後使用向量計算公式計算當前角色處於的座標點位置。
角色位置位置計算的類封裝實現程式碼:
1 #pragma once 2 3 class CCoordinatePath 4 { 5 public: 6 CCoordinatePath(void); 7 ~CCoordinatePath(void); 8 9 public: 10 // 更新行走路徑 11 void UpdatePath(COORDINATE_3D stopCoordinate3D); 12 void UpdatePath(vector<COORDINATE_3DPATH> vtPath, COORDINATE_3D stopCoordinate3D, float nCompletePath = 0); 13 // 開始行走(移動計算) 14 void StartMove(DWORD dwStartTime); 15 // 獲取當前空間位置 16 COORDINATE_3D GetCoordinate(DWORD dwNowTime); 17 // 獲取行走路徑 18 const vector<COORDINATE_3DPATH>* GetPath(); 19 // 獲取停止位置 20 COORDINATE_3D GetStopCoordinate(); 21 // 獲取移動總距離(從開始行走到現在的行走總距離) 22 float GetCompletePath(DWORD dwNowTime); 23 // 更新玩家速度 24 void UpdateSpeed(unsigned short wSpeed, DWORD dwNowTime); 25 // 獲取當前速度 26 unsigned short GetSpeed(); 27 // 玩家是否正在移動 28 bool IsMoving(DWORD dwNowTime); 29 30 private: 31 // 行走路徑 32 vector<COORDINATE_3DPATH> m_vtPath; 33 // 停止點 34 COORDINATE_3D m_stopCoordinate3D; 35 36 // 已完成路徑 37 float m_nCompletePath; 38 // 玩家當前速度 39 unsigned short m_wCurSpeed; 40 // 行走路徑開始時間 41 DWORD m_dwStartMoveTime; 42 43 }; 44 45 #include "StdAfx.h" 46 #include "CoordinatePath.h" 47 48 CCoordinatePath::CCoordinatePath(void) 49 { 50 m_wCurSpeed = 4; 51 } 52 53 CCoordinatePath::~CCoordinatePath(void) 54 { 55 } 56 57 void CCoordinatePath::UpdatePath( COORDINATE_3D stopCoordinate3D ) 58 { 59 m_vtPath.clear(); 60 m_stopCoordinate3D = stopCoordinate3D; 61 m_nCompletePath = 0; 62 } 63 64 void CCoordinatePath::UpdatePath( vector<COORDINATE_3DPATH> vtPath, COORDINATE_3D stopCoordinate3D, float nCompletePath /*= 0*/ ) 65 { 66 m_vtPath = vtPath; 67 m_stopCoordinate3D = stopCoordinate3D; 68 m_nCompletePath = nCompletePath; 69 } 70 71 void CCoordinatePath::StartMove( DWORD dwStartTime ) 72 { 73 m_dwStartMoveTime = dwStartTime; 74 } 75 76 COORDINATE_3D CCoordinatePath::GetCoordinate(DWORD dwNowTime) 77 { 78 if (m_vtPath.size() == 0) 79 { 80 return m_stopCoordinate3D; 81 } 82 83 float nTotalDistance = GetCompletePath(dwNowTime); 84 85 if (nTotalDistance < 0) 86 { 87 cout << "計算玩家移動距離錯誤" << endl; 88 return m_stopCoordinate3D; 89 } 90 91 // ceshi 92 //cout << "距離:" << nTotalDistance << "時間" << (dwNowTime-m_dwStartMoveTime) << endl; 93 94 COORDINATE_3D coordinate3D; 95 96 // 上面已經計算出玩家行走總距離,計算玩家位置 97 vector<COORDINATE_3DPATH>::iterator itPath = m_vtPath.begin(); 98 for (; itPath!=m_vtPath.end(); ++itPath) 99 { 100 if (itPath->allDistance > nTotalDistance) 101 { 102 // 角色當前位置在當前path中,計算當前位置 103 float nCurDistance = nTotalDistance - (itPath->allDistance - itPath->curDistance); 104 105 if (nCurDistance < 0) 106 { 107 cout << "[嚴重錯誤]獲取座標" << endl; 108 return m_stopCoordinate3D; 109 } 110 111 coordinate3D.x = itPath->x + itPath->dFormula*itPath->xDistance*nCurDistance; 112 coordinate3D.y = itPath->y + itPath->dFormula*itPath->yDistance*nCurDistance; 113 coordinate3D.z = itPath->z + itPath->dFormula*itPath->zDistance*nCurDistance; 114 coordinate3D.dir = itPath->dir; 115 116 if (coordinate3D.x ==1 && coordinate3D.y==1 && coordinate3D.z == 1) 117 { 118 int i = 0; 119 } 120 ///yang 121 //cout << "當前移動座標:x:" << coordinate3D.x << ",y:" << coordinate3D.y << ",z:" << coordinate3D.z << endl; 122 ///yang 123 return coordinate3D; 124 } 125 } 126 127 // 到達目標點做先前點路徑的清理工作 128 m_vtPath.clear(); 129 130 return m_stopCoordinate3D; 131 } 132 133 const vector<COORDINATE_3DPATH>* CCoordinatePath::GetPath() 134 { 135 return &m_vtPath; 136 } 137 138 COORDINATE_3D CCoordinatePath::GetStopCoordinate() 139 { 140 return m_stopCoordinate3D; 141 } 142 143 float CCoordinatePath::GetCompletePath( DWORD dwNowTime ) 144 { 145 // 無變速的移動距離計算 146 DWORD dwMoveTime = dwNowTime-m_dwStartMoveTime; 147 148 return (m_nCompletePath + m_wCurSpeed*dwMoveTime/1000.0f); 149 } 150 151 void CCoordinatePath::UpdateSpeed( unsigned short wSpeed, DWORD dwNowTime ) 152 { 153 // 計算已經完成路徑 154 m_nCompletePath += GetCompletePath(dwNowTime); 155 m_dwStartMoveTime = dwNowTime; 156 157 m_wCurSpeed = wSpeed; //當前速度 158 } 159 160 unsigned short CCoordinatePath::GetSpeed() 161 { 162 return m_wCurSpeed; 163 } 164 165 bool CCoordinatePath::IsMoving( DWORD dwNowTime ) 166 { 167 GetCoordinate(dwNowTime); 168 169 if (m_vtPath.size() > 0) 170 { 171 return true; 172 } 173 else 174 { 175 return false; 176 } 177 }