3D 服务器端以向量计算为主的角色位置的算法
把我以前学习过的一个东西拿出来分享下~
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 }