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 = );
// 开始行走(移动计算)
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 = ;
} CCoordinatePath::~CCoordinatePath(void)
{
} void CCoordinatePath::UpdatePath( COORDINATE_3D stopCoordinate3D )
{
m_vtPath.clear();
m_stopCoordinate3D = stopCoordinate3D;
m_nCompletePath = ;
} 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() == )
{
return m_stopCoordinate3D;
} float nTotalDistance = GetCompletePath(dwNowTime); if (nTotalDistance < )
{
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 < )
{
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 == && coordinate3D.y== && coordinate3D.z == )
{
int i = ;
}
///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() > )
{
return true;
}
else
{
return false;
}
}
3D 服务器端以向量计算为主的角色位置的算法的更多相关文章
- Python之find命令中的位置的算法
find("s",a,b) #s表示的是一个子序列,a表示的是检索的起始位置,b表示的是检索的终止位置,ab可有可无 test = "abcdefgh" ...
- 3D空间中射线与三角形的交叉检测算法【转】
引言 射线Ray,在3D图形学中有很多重要的应用.比如,pick操作就是使用射线Ray来实现的,还有诸如子弹射线的碰撞检测等等都可以使用射线Ray来完成.所以,在本次博客中,将会简单的像大家介绍下,如 ...
- js数组插入指定位置元素,删除指定位置元素,查找指定位置元素算法
将元素x插入到顺序表L(数组)的第i个数据元素之前 function InsertSeqlist(L, x, i) { // 将元素x插入到顺序表L的第i个数据元素之前 if(L.length == ...
- C++ 递归位置排列算法及其应用
废话不多说,我们先看一下位置排序的算法: #include <iostream> using namespace std; int n = 0; int m = 2; int l = 0; ...
- [转] MMO即时战斗:地图角色同步管理和防作弊实现
一.前言 无论是端游.页游.手游如果是采用了MMO即时战斗游戏模式,基本都会遇到同屏多角色实时移动.释放技能.战斗等场景,于是自然也需要实现如何管理同屏内各种角色的信息同步:例如角色的位置.以及角色身 ...
- 【转】MMO即时战斗:地图角色同步管理和防作弊实现
---转自CSDN 一.前言 无论是端游.页游.手游如果是采用了MMO即时战斗游戏模式,基本都会遇到同屏多角色实时移动.释放技能.战斗等场景,于是自然也需要实现如何管理同屏内各种角色的信息同步:例如角 ...
- 【Unity 3D 游戏开发】Unity3D 入门 - 工作区域介绍 与 入门示例
一. 工作区域详解 1. Scence视图 (场景设计面板) scence视图简介 : 展示创建的游戏对象, 可以对所有的游戏对象进行 移动, 操作 和 放置; -- 示例 : 创建一个球体, 控制摄 ...
- 关于Unity中3D声音的使用
3D声音 3D立体声和2D声不同的地方是它是会随着距离衰减的,距离越近声音越大,距离越远声音越小. 1: 声音: 背景音乐和音效; 2: 声音文件支持的格式: ogg, mp3, wave, AIFF ...
- 【Unity 3D 游戏开发】Unity3D 入门 - 工作区域介绍 与 入门演示样例
一. 工作区域具体解释 1. Scence视图 (场景设计面板) scence视图简单介绍 : 展示创建的游戏对象, 能够对全部的游戏对象进行 移动, 操作 和 放置; -- 演示样例 : 创建一个球 ...
随机推荐
- 在配置XML时报的The reference to entity "dataSource" must end with the ';' delimiter错误
<?xml version="1.0" encoding="UTF-8"?> <ECharts> <element>http ...
- gshop.data 编辑器通杀版本 支持146-151版本
EXE下载:http://files.cnblogs.com/xe2011/EXEgshop.dataeditorV1.42014-3-11-204242.7z C#:http://files.cnb ...
- Google高级技巧—google Hack★★★★
google hacking事实上并算不上什么新东西,当时并没有重视这样的技术,觉得webshell什么的,并无太大实际用途.google hacking事实上并非如此简单... 经常使用的googl ...
- Android Studio 完美修改应用包名
我们平时新建项目有些朋友可能当时就是随意写的一个包名,然后在项目过程中, 又感觉这个包名不太好,所以就要对包名进行修改,根据我们正常的修改方式,是这样的. 在种情况是只能修改最外层的那个名称, 如果我 ...
- Eclipse启动Tomcat访问不了首页
Eclipse开发web项目与myEclipse不同: 启动服务器后访问 http:localhost:8080 找不到服务器 想要访问Tomcat首页只需修改Tomcat配置 进入Eclipse双击 ...
- "只能在执行Render()的过程中调用RegisterForEventValidation" 解决方案
开发中遇到令人蛋疼的问题: 只能在执行Render()的过程中调用RegisterForEventValidation 当出现的异常的提示: 异常详细信息: System.InvalidOperati ...
- magento 数据结构
首先要知道是EAV模式,这种结构要比普通数据结构更容易扩展,但是带来的就是查询速度慢,好在magento的缓存机制不错 最重要的3张表eav_entity_type,eav_entity_attrib ...
- T-SQL基础 (子查询,连接查询,交叉查询,事务|| 笔记0807)
一: A.子查询: 1.select 字段名 from table where 字段名=(select 字段名 from table 条件) //只能做1个匹配 2.select 字段名 from ...
- DI(依赖注入)简单理解 NO1
依赖注入:目的削减程序的耦合度,达到高内聚/低耦合 常用形式:Interface Driven Design接口驱动,接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性等等.通过Io ...
- C#微信公众号开发 -- (七)自定义菜单事件之VIEW及网页(OAuth2.0)授权
通俗来讲VIEW其实就是我们在C#中常用的a标签,可以直接在自定义菜单URL的属性里面写上需要跳转的链接,也即为单纯的跳转. 但更多的情况下,我们是想通过VIEW来进入指定的页面并进行操作. 举一个简 ...