3D服务器端玩家行走处理是服务器端根据客户端行走路径、玩家行走时间以及速度(包括变化速度)计算得出玩家的当前位置。
由于客户端行走是一条路径,不使用2D中的格子计算算法,未能高效的获取角色的当前位置,运用玩家行走路径,行走速度,行走时间这些已量,进行计算玩家的当前精确位置。由于3D游戏中的点为xyz的空间点,所以牵连的计算为3维向量计算。
空间两点距离计算公式为:
玩家在某条线段上的坐标x:
玩家在某条线段上的坐标y:
玩家在某条线段上的坐标z:
角色当前位置计算原理分析:
角色行走是一条路径,这条路径使用点序列表示,角色开始行走记录当前时间TimeStart,获取觉得当前位置的计算,首先获取当前时间TimeNow,根据TimeNow-TimeStart的时间差与角色的行走速度,获取角色已经行走过的距离distance,计算每两点的距离,判定角色当前时间所处在哪一条路径上,及角色在哪两点之间。然后使用向量计算公式计算当前角色处于的坐标点位置。
角色位置位置计算的类封装实现代码:
#pragma once class CCoordinatePath { public: CCoordinatePath(void); ~CCoordinatePath(void); public: // 更新行走路径 void UpdatePath(COORDINATE_3D stopCoordinate3D); void UpdatePath(vector<COORDINATE_3DPATH> vtPath, COORDINATE_3D stopCoordinate3D, float nCompletePath = 0); // 开始行走(移动计算) void StartMove(DWORD dwStartTime); // 获取当前空间位置 COORDINATE_3D GetCoordinate(DWORD dwNowTime); // 获取行走路径 const vector<COORDINATE_3DPATH>* GetPath(); // 获取停止位置 COORDINATE_3D GetStopCoordinate(); // 获取移动总距离(从开始行走到现在的行走总距离) float GetCompletePath(DWORD dwNowTime); // 更新玩家速度 void UpdateSpeed(unsigned short wSpeed, DWORD dwNowTime); // 获取当前速度 unsigned short GetSpeed(); // 玩家是否正在移动 bool IsMoving(DWORD dwNowTime); private: // 行走路径 vector<COORDINATE_3DPATH> m_vtPath; // 停止点 COORDINATE_3D m_stopCoordinate3D; // 已完成路径 float m_nCompletePath; // 玩家当前速度 unsigned short m_wCurSpeed; // 行走路径开始时间 DWORD m_dwStartMoveTime; };
#include "StdAfx.h" #include "CoordinatePath.h" CCoordinatePath::CCoordinatePath(void) { m_wCurSpeed = 4; } CCoordinatePath::~CCoordinatePath(void) { } void CCoordinatePath::UpdatePath( COORDINATE_3D stopCoordinate3D ) { m_vtPath.clear(); m_stopCoordinate3D = stopCoordinate3D; m_nCompletePath = 0; } void CCoordinatePath::UpdatePath( vector<COORDINATE_3DPATH> vtPath, COORDINATE_3D stopCoordinate3D, float nCompletePath /*= 0*/ ) { m_vtPath = vtPath; m_stopCoordinate3D = stopCoordinate3D; m_nCompletePath = nCompletePath; } void CCoordinatePath::StartMove( DWORD dwStartTime ) { m_dwStartMoveTime = dwStartTime; } COORDINATE_3D CCoordinatePath::GetCoordinate(DWORD dwNowTime) { if (m_vtPath.size() == 0) { return m_stopCoordinate3D; } float nTotalDistance = GetCompletePath(dwNowTime); if (nTotalDistance < 0) { cout << "计算玩家移动距离错误" << endl; return m_stopCoordinate3D; } // ceshi //cout << "距离:" << nTotalDistance << "时间" << (dwNowTime-m_dwStartMoveTime) << endl; COORDINATE_3D coordinate3D; // 上面已经计算出玩家行走总距离,计算玩家位置 vector<COORDINATE_3DPATH>::iterator itPath = m_vtPath.begin(); for (; itPath!=m_vtPath.end(); ++itPath) { if (itPath->allDistance > nTotalDistance) { // 角色当前位置在当前path中,计算当前位置 float nCurDistance = nTotalDistance - (itPath->allDistance - itPath->curDistance); if (nCurDistance < 0) { cout << "[严重错误]获取坐标" << endl; return m_stopCoordinate3D; } coordinate3D.x = itPath->x + itPath->dFormula*itPath->xDistance*nCurDistance; coordinate3D.y = itPath->y + itPath->dFormula*itPath->yDistance*nCurDistance; coordinate3D.z = itPath->z + itPath->dFormula*itPath->zDistance*nCurDistance; coordinate3D.dir = itPath->dir; if (coordinate3D.x ==1 && coordinate3D.y==1 && coordinate3D.z == 1) { int i = 0; } ///yang //cout << "当前移动坐标:x:" << coordinate3D.x << ",y:" << coordinate3D.y << ",z:" << coordinate3D.z << endl; ///yang return coordinate3D; } } // 到达目标点做先前点路径的清理工作 m_vtPath.clear(); return m_stopCoordinate3D; } const vector<COORDINATE_3DPATH>* CCoordinatePath::GetPath() { return &m_vtPath; } COORDINATE_3D CCoordinatePath::GetStopCoordinate() { return m_stopCoordinate3D; } float CCoordinatePath::GetCompletePath( DWORD dwNowTime ) { // 无变速的移动距离计算 DWORD dwMoveTime = dwNowTime-m_dwStartMoveTime; return (m_nCompletePath + m_wCurSpeed*dwMoveTime/1000.0f); } void CCoordinatePath::UpdateSpeed( unsigned short wSpeed, DWORD dwNowTime ) { // 计算已经完成路径 m_nCompletePath += GetCompletePath(dwNowTime); m_dwStartMoveTime = dwNowTime; m_wCurSpeed = wSpeed; //当前速度 } unsigned short CCoordinatePath::GetSpeed() { return m_wCurSpeed; } bool CCoordinatePath::IsMoving( DWORD dwNowTime ) { GetCoordinate(dwNowTime); if (m_vtPath.size() > 0) { return true; } else { return false; } }