3D 伺服器端以向量計算為主的角色位置的演算法

快看一隻熊發表於2013-06-18

把我以前學習過的一個東西拿出來分享下~

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 }

 

相關文章