角色行走频繁点击地面进行行走,会频繁出现客户端被拉回。
拉回的原因是客户端的位置和服务器的位置出现偏差。服务器强制拉回客户端。经过持续半个月间断性的查找,终于找到原因是,因为
int CCoordinatePath::GetCompletePath( DWORD dwNowTime )
{
// 无变速的移动距离计算
DWORD dwMoveTime = dwNowTime-m_dwStartMoveTime;
return (m_nCompletePath + m_wCurSpeed*dwMoveTime/1000);
}
之前行走距离进行了取整,不停的发送角色行走,不停的计算路径长度的过程,把角色行走距离给取整时过滤掉了,最终导致客户端比服务器位置提前,进行拉回。服务器也应该使用浮点数进行处理行走,这样才能保持客户端与服务器同步。解决客户端频繁拉回的问题。下面是修改后的代码。
获取角色当前位置的源代码(修正后)CoordinatePath.zip:
#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()
{ www.zzzyk.com
return m_wCurSpeed;
}
bool CCoordinatePath::IsMoving( DWORD dwNowTime )
{
GetCoordinate(dwNowTime);
if (m_vtPath.size() > 0)
{
return true;
}
else
{
return false;
}
}