3D服務器端玩家行走處理是服務器端根據客戶端行走路徑、玩家行走時間以及速度(包括變化速度)計算得出玩家的當前位置。 由於客戶端行走是一條路徑,不使用2D中的格子計算算法,未能高效的獲取角色的當前位置,運用玩家行走路徑,行走速度,行走時間這些已量,進行計算玩家的當前精確位置。由於3D游戲中的點為xyz的空間點,所以牽連的計算為3維向量計算。 空間兩點距離計算公式為: 玩家在某條線段上的坐標x: 玩家在某條線段上的坐標y: 玩家在某條線段上的坐標z: 備注:公式文件公式.rar 代碼實現: // 空間坐標 typedef struct tagCoordinate3D { tagCoordinate3D() { this->x = 0; this->y = 0; this->z = 0; this->dir = 0; } tagCoordinate3D(int x, int y, int z, short dir = 0) { www.2cto.com this->x = x; this->y = y; this->z = z; this->dir = dir; } ~tagCoordinate3D(){} int operator - (tagCoordinate3D coordinate3D) { double nTemp = (this->x - coordinate3D.x)*(this->x - coordinate3D.x) + (this->y - coordinate3D.y)*(this->y - coordinate3D.y) + (this->z - coordinate3D.z)*(this->z - coordinate3D.z); if (0 == nTemp) { return (int)-1; } return (int)sqrt(nTemp); } int x;//X坐標 int z;//Z坐標 int y;//Y坐標(高度) short dir;//方向(范圍:0-359) }COORDINATE_3D, *PCOORDINATE_3D; typedef struct tagCoordinate3DPath : public tagCoordinate3D { tagCoordinate3DPath() { } tagCoordinate3DPath(int x, int y, int z, short dir = 0) : tagCoordinate3D(x, y, z, dir) { } tagCoordinate3DPath(tagCoordinate3D coordinate3D) : tagCoordinate3D(coordinate3D.x, coordinate3D.y, coordinate3D.z, coordinate3D.dir) { } ~tagCoordinate3DPath() {} int curDistance;//當前距離(和上個點的距離) int allDistance;//總距離(和第一個點的距離,所有點距離之和) int xDistance; int yDistance; int zDistance; double dFormula;//位置計算公式 }COORDINATE_3DPATH, *PCOORDINATE_3DPATH; 獲取角色當前坐標: COORDINATE_3D CFightRole::GetPosition() { if (m_vtWalkPath.size() == 0) { return m_3DWalkPathEnd; } COORDINATE_3D coordinate3D; DWORD dwNowTime = GetFrameTime(); int nWalkTime = dwNowTime - m_dwWalkPathBeginTime; if (nWalkTime < 0) { cout << "[嚴重錯誤]不應該發生錯誤的地方,發生了錯誤" << endl; return m_3DWalkPathEnd; } double nTotalDistance = m_wSpeed*nWalkTime/(1000.0f); // 上面已經計算出玩家行走總距離,計算玩家位置 vector<COORDINATE_3DPATH>::iterator itPath = m_vtWalkPath.begin(); for (; itPath!=m_vtWalkPath.end(); ++itPath) { if (itPath->allDistance > (int)nTotalDistance) { // 角色當前位置在當前path中,計算當前位置 bFind = true; double nCurDistance = nTotalDistance - (itPath->allDistance - itPath->curDistance); if (nCurDistance < 0) { cout << "[嚴重錯誤]獲取坐標" << endl; return coordinate3D; } coordinate3D.x = (int)(itPath->x + itPath->dFormula*itPath->xDistance*nCurDistance); coordinate3D.y = (int)(itPath->y + itPath->dFormula*itPath->yDistance*nCurDistance); coordinate3D.z = (int)(itPath->z + itPath->dFormula*itPath->zDistance*nCurDistance); coordinate3D.dir = itPath->dir; if (coordinate3D.x ==1 && coordinate3D.y==1 && coordinate3D.z == 1) { int i = 0; } return coordinate3D; } } // 到達目標點做先前點路徑的清理工作 m_vtWalkPath.clear(); return m_3DWalkPathEnd; } 部分計算公式初始化: COORDINATE_3D curCoordinate3D(tempCoordinate3d.x(), tempCoordinate3d.y(), tempCoordinate3d.z(), tempCoordinate3d.dir()); // 第n段行走路徑 COORDINATE_3DPATH coordinate3DPath(prevCoordinate3D); // 當前路徑距離 coordinate3DPath.curDistance = curCoordinate3D - prevCoordinate3D; // 總路徑距離 nAllPathDistance += coordinate3DPath.curDistance; coordinate3DPath.allDistance = nAllPathDistance; // 位置計算公式 double nValue = (curCoordinate3D.x-prevCoordinate3D.x)*(curCoordinate3D.x-prevCoordinate3D.x) + (curCoordinate3D.y-prevCoordinate3D.y)*(curCoordinate3D.y-prevCoordinate3D.y) + (curCoordinate3D.z-prevCoordinate3D.z)*(curCoordinate3D.z-prevCoordinate3D.z); if (nValue <= 0) { cout << "開根號為0" << endl; return ; } double dValue = sqrt(nValue); if (0 == dValue) { cout << "錯誤" << endl; return; } coordinate3DPath.xDistance = curCoordinate3D.x-prevCoordinate3D.x; coordinate3DPath.yDistance = curCoordinate3D.y-prevCoordinate3D.y; coordinate3DPath.zDistance = curCoordinate3D.z-prevCoordinate3D.z; coordinate3DPath.dFormula = 1/dValue; // 間斷取path線段中的點,進行格子可行走點的判定。 vtWalkPath.push_back(coordinate3DPath)