3D 服务器端以向量计算为主的角色位置的算法

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;
	}
}



AdjuntoTamaño
Icono de Imagen 1363866855-5554.png9.64 KB
Icono de Imagen 2.png14.35 KB
Icono de Imagen 3.png2.72 KB
Icono de Imagen 4.png2.76 KB
Icono de Imagen 5.png2.68 KB
Para obtener información más completa sobre las optimizaciones del compilador, consulte nuestro Aviso de optimización.