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)