游戏中的帧同步要求的计算一致性——定点数(Fixed Point)

2023-05-16

最近做了一款帧同步游戏,其寻路算法采用了RVO算法。但是由于是移动端的游戏。需要在不同的设备上运行,其所有运算必须符合一致性——即所有客户端运算出来的结果必须一致。但是由于浮点数的特性,具有误差,且在不同设备上误差更为明显。因此所有的算法都不能采用浮点数来运算。一般来说,这些游戏内大多采用*1000 再/1000的方式来实现帧同步的计算一致性。

        但是由于RVO算法,是用来寻路的,其中大量的向量运算,其算法复杂度非常高。而向量运算是一个特例。其中比如normalize,是不能放大的——因为放大多少倍最后的结果也只能是(1,0)(0,1)(0,0).还有一些 sin函数 cos函数是没有办法先乘后除的。在这种情况下,采用老式的方式已经非常不便了(大量的临时变量和成员变量你已经记不清哪些放大过哪些是标准值了)。因此,我打算采用定点库。网上的定点数库大多重载不全,而且没有找到跨语言的。。。所以就自己实现了一个。直接上代码(代码是c#的)。
       (其中的sin cos 的实现请参考上一篇文章)
 
 

using System.Collections;
using System;
using System.Globalization;
 
namespace FP
{
public struct FPoint 
{
public static int Fix_Fracbits = 16;
public static FPoint Zero = new FPoint(0);
        internal Int64 m_Bits;
public FPoint(int x)
{
m_Bits = (x<<Fix_Fracbits);
}
public FPoint(float x)
{
m_Bits =(Int64)((x) * (1 << Fix_Fracbits));
//x*(((Int64)(1)<<Fix_Fracbits))
}
public FPoint(Int64 x)
{
m_Bits = ((x) * (1 << Fix_Fracbits));
}
public Int64 GetValue()
{
return m_Bits;
}
//******************* +  **************************
public static FPoint operator +( FPoint p1,  FPoint p2)
{
FPoint tmp ;
tmp.m_Bits = p1.m_Bits + p2.m_Bits;
return tmp;
}
public static FPoint operator +(FPoint p1, int p2)
{
FPoint tmp ;
tmp.m_Bits = p1.m_Bits + (Int64)(p2<<Fix_Fracbits);
return tmp;
}
public static FPoint operator +(int p1, FPoint p2)
{
return p2+p1;
}
public static FPoint operator +(FPoint p1, Int64 p2)
{
FPoint tmp ;
tmp.m_Bits = p1.m_Bits + p2<<Fix_Fracbits;
return tmp;
}
public static FPoint operator +(Int64 p1, FPoint p2)
{
return p2+p1;
}
 
public static FPoint operator +(FPoint p1, float p2)
{
FPoint tmp ;
tmp.m_Bits = p1.m_Bits + (Int64)(p2*(1<<Fix_Fracbits));
return tmp;
}
public static FPoint operator +(float p1, FPoint p2)
{
FPoint tmp = p2 + p1;
return tmp;
}
//*******************  -  **************************
public static FPoint operator -(FPoint p1, FPoint p2)
{
FPoint tmp ;
tmp.m_Bits = p1.m_Bits - p2.m_Bits;
return tmp;
}
 
public static FPoint operator -(FPoint p1, int p2)
{
FPoint tmp ;
tmp.m_Bits = p1.m_Bits - (Int64)(p2<<Fix_Fracbits);
return tmp;
}
 
public static FPoint operator -(int p1, FPoint p2)
{
FPoint tmp ;
tmp.m_Bits = (p1<<Fix_Fracbits) - p2.m_Bits;
return tmp; 
}
public static FPoint operator -(FPoint p1, Int64 p2)
{
FPoint tmp ;
tmp.m_Bits = p1.m_Bits - (p2<<Fix_Fracbits);
return tmp;
}
public static FPoint operator -(Int64 p1, FPoint p2)
{
FPoint tmp;
tmp.m_Bits = (p1<<Fix_Fracbits) - p2.m_Bits;
return tmp; 
}
 
public static FPoint operator -(float p1, FPoint p2)
{
FPoint tmp;
tmp.m_Bits = (Int64)(p1*(1<<Fix_Fracbits)) - p2.m_Bits;
return tmp; 
}
public static FPoint operator -(FPoint p1, float p2)
{
FPoint tmp;
tmp.m_Bits = p1.m_Bits - (Int64)(p2*(1<<Fix_Fracbits));
return tmp; 
}
 
//******************* * **************************
public static FPoint operator *(FPoint p1, FPoint p2)
{
FPoint tmp ;
tmp.m_Bits = ((p1.m_Bits) * (p2.m_Bits)) >> (Fix_Fracbits);
return tmp;
}
 
public static FPoint operator *(int p1, FPoint p2)
{
FPoint tmp ;
tmp.m_Bits = p1 * p2.m_Bits;
return tmp;
}
public static FPoint operator *(FPoint p1, int p2)
{
return p2 * p1;
}
public static FPoint operator *(FPoint p1, float p2)
{
FPoint tmp;
tmp.m_Bits =  (Int64)(p1.m_Bits*p2);
return tmp;
}
public static FPoint operator *(float p1, FPoint p2)
{
FPoint tmp ;
tmp.m_Bits =  (Int64)(p1  * p2.m_Bits);
return tmp;
}
//******************* / **************************
public static FPoint operator / (FPoint p1, FPoint p2)
{
FPoint tmp ;
if(p2 == FPoint.Zero)
{
UnityEngine.Debug.LogError("/0");
tmp.m_Bits = Zero.m_Bits;
}
else
{
tmp.m_Bits = (p1.m_Bits) * (1<<Fix_Fracbits) / (p2.m_Bits); 
}
return tmp;
}
public static FPoint operator / (FPoint p1, int p2)
{
FPoint tmp ;
if(p2 == 0)
{
UnityEngine.Debug.LogError("/0");
tmp.m_Bits = Zero.m_Bits;
}
else
{
tmp.m_Bits = p1.m_Bits/(p2);
}
return tmp;
}
public static FPoint operator /(int p1, FPoint p2)
{
FPoint tmp ;
if(p2 == Zero)
{
UnityEngine.Debug.LogError("/0");
tmp.m_Bits = Zero.m_Bits;
}
else
{
Int64 tmp2 = ((Int64)p1 << Fix_Fracbits << Fix_Fracbits);
tmp.m_Bits = tmp2/(p2.m_Bits);
}
return tmp;
}
public static FPoint operator / (FPoint p1, Int64 p2)
{
FPoint tmp;
if(p2 == 0)
{
UnityEngine.Debug.LogError("/0");
tmp.m_Bits = Zero.m_Bits;
}
else
{
tmp.m_Bits = p1.m_Bits/(p2);
}
return tmp;
}
public static FPoint operator /(Int64 p1, FPoint p2)
{
FPoint tmp;
if(p2 == Zero)
{
UnityEngine.Debug.LogError("/0");
tmp.m_Bits = Zero.m_Bits;
}
else
{
if(p1>Int32.MaxValue ||p1
{
tmp.m_Bits = 0;
return tmp;
}
tmp.m_Bits = (p1<<Fix_Fracbits)/(p2.m_Bits);
}
return tmp;
}
public static FPoint operator /(float p1, FPoint p2)
{
FPoint tmp ;
if(p2 == Zero)
{
UnityEngine.Debug.LogError("/0");
tmp.m_Bits = Zero.m_Bits;
}
else
{
Int64 tmp1 = (Int64)p1 * ((Int64)1 << Fix_Fracbits << Fix_Fracbits);
tmp.m_Bits = (tmp1)/(p2.m_Bits);
}
return tmp;
} 
public static FPoint operator /(FPoint p1, float p2)
{
FPoint tmp;
if(p2>-0.000001f && p2<0.000001f)
{
UnityEngine.Debug.LogError("/0");
tmp.m_Bits = Zero.m_Bits;
}
else
{
tmp.m_Bits = (p1.m_Bits<<Fix_Fracbits)/((Int64)(p2*(1<<Fix_Fracbits)));
}
return tmp;
} 
public static FPoint Sqrt(FPoint p1)
{
FPoint tmp;
Int64 ltmp = p1.m_Bits * (1 << Fix_Fracbits);
tmp.m_Bits = (Int64)Math.Sqrt(ltmp); 
return tmp;
}
public static bool operator >(FPoint p1, FPoint p2)
{
return (p1.m_Bits>p2.m_Bits)?true:false;
}
public static bool operator <(FPoint p1, FPoint p2)
{
return (p1.m_Bits
}
public static bool operator <=(FPoint p1, FPoint p2)
{
return (p1.m_Bits<=p2.m_Bits)?true:false;
}
public static bool operator >=(FPoint p1, FPoint p2)
{
return (p1.m_Bits>=p2.m_Bits)?true:false;
}
public static bool operator !=(FPoint p1, FPoint p2)
{
return (p1.m_Bits!=p2.m_Bits)?true:false;
}
public static bool operator ==(FPoint p1, FPoint p2)
{
return (p1.m_Bits==p2.m_Bits)?true:false;
}
 
public static bool Equals(FPoint p1, FPoint p2)
{
return (p1.m_Bits==p2.m_Bits)?true:false;
}
 
public bool Equals(FPoint right)
{
if(m_Bits == right.m_Bits)
{
return true;
}
return false;
}
 
public static bool operator >(FPoint p1, float p2)
{
return (p1.m_Bits>(p2*(1<<Fix_Fracbits)))?true:false;
}
public static bool operator <(FPoint p1, float p2)
{
return (p1.m_Bits<<Fix_Fracbits))?true:false;
}
public static bool operator <=(FPoint p1, float p2)
{
return (p1.m_Bits<=p2*(1<<Fix_Fracbits))?true:false;
}
public static bool operator >=(FPoint p1, float p2)
{
return (p1.m_Bits>=p2*(1<<Fix_Fracbits))?true:false;
}
public static bool operator !=(FPoint p1, float p2)
{
return (p1.m_Bits!=p2*(1<<Fix_Fracbits))?true:false;
}
public static bool operator ==(FPoint p1, float p2)
{
return (p1.m_Bits==p2*(1<<Fix_Fracbits))?true:false;
}
 
public static FPoint Cos (FPoint p1)
{
            return FP.TrigonometricFunction.Cos(p1);
}
public static FPoint Sin (FPoint p1)
{
            return FP.TrigonometricFunction.Sin(p1);
}
 
public static FPoint Max()
{
FPoint tmp ;
tmp.m_Bits = Int64.MaxValue;
return tmp;
}
 
public static FPoint Max(FPoint p1 ,FPoint p2)
{
return p1.m_Bits>p2.m_Bits?p1:p2;
}
public static FPoint Min(FPoint p1 ,FPoint p2)
{
return p1.m_Bits
}
 
public static FPoint Precision()
{
FPoint tmp ;
tmp.m_Bits = 1;
return tmp;
}
 
public static FPoint MaxValue()
{
FPoint tmp ;
tmp.m_Bits = Int64.MaxValue;
return tmp;
}
public static FPoint Abs(FPoint P1)
{
FPoint tmp ;
tmp.m_Bits = Math.Abs (P1.m_Bits);
return tmp;
}
public static FPoint operator -(FPoint p1)
{
FPoint tmp ;
tmp.m_Bits = -p1.m_Bits;
return tmp;
}
 
public float ToFloat()
{
return m_Bits/(float)(1<<Fix_Fracbits);
}
 
        public int ToInt()
        {
            return (int)(m_Bits >> (Fix_Fracbits));
        }
public string ToString()
{
double tmp = (double)m_Bits/(double)(1<<Fix_Fracbits);
return tmp.ToString();
}
}
}  

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

游戏中的帧同步要求的计算一致性——定点数(Fixed Point) 的相关文章

  • tcpdump抓包命令

    该命令是抓包分析工具 xff0c 可以将数据包的头或者是整个包抓取下来进行分析 xff0c 支持针对特定协议 主机进行过滤 xff0c 同时支持逻辑操作 抓取本机第一个网络接口通常是eth0上所有的包 tcpdump 抓取指定指定网卡上的的
  • rundll32.exe命令使用大法

    lt DOCTYPE html PUBLIC WCDTD XHTML StrictEN httpwwwworgTRxhtmlDTDxhtml strictdtd gt Rundll32 exe是什么 xff1f 顾名思意 xff0c 执行3
  • sftp

    引述自 xff1a http cs ecust edu cn snwei studypc oftencommand ftp htm sftp的命令格式为 xff1a sftp v d i n g hostname v 显示远程服务器的所有响
  • L298N接线图

    转载于 https my oschina net surenpi blog 481745
  • 大数据:Hive - ORC 文件存储格式

    一 ORC File文件结构 ORC的全称是 Optimized Row Columnar xff0c ORC文件格式是一种Hadoop生态圈中的列式存储格式 xff0c 它的产生早在2013年初 xff0c 最初产生自Apache Hiv
  • WPF RichTextBox 禁止换行

    原文 WPF RichTextBox 禁止换行 这个问题困扰了好久 xff0c 进过不断的努力 xff0c 终于解决了 lt RichTextBox Margin 61 34 0 44 10 0 34 Name 61 34 codeText
  • 浅谈微信小程序用setStorage和getStorage缓存和获取数据

    缓存数据 每个微信小程序都可以有自己的本地缓存 xff0c 可以通过 wx setStorage xff08 wx setStorageSync xff09 wx getStorage xff08 wx getStorageSync xff
  • 微信扫码登录是如何实现的?

    网页版微信刚推出时 xff0c 无数人被它的登录方式惊艳了一下 xff0c 不需要输入用户名密码 xff0c 打开手机微信扫一扫 xff0c 便自动登录 从原理上讲 xff0c 二维码只能是一段文本的编码 xff0c 如何用它实现快捷登录的
  • python - http请求带Authorization

    背景 接入公司的一个数据统计平台 xff0c 该平台的接口是带上了Authorization验证方式来保证验签计算安全 方法 其实很简单 xff0c 就是在header中加入key 61 Authorization xff0c value是
  • element设置设置日期0点到23:59:59

    2019独角兽企业重金招聘Python工程师标准 gt gt gt js方式 var start 61 new Date new Date new Date toLocaleDateString getTime 当前日期0点到23 xff1
  • 一张图看懂亮度、明度、光度、光亮度、明亮度

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 亮度 明度 光亮度 xff0c Luminance和Brightness lightness其实都是一个意思 xff0c 只是起名字太难了 提出一个颜色模型后 xff0c
  • prfpset文件怎么导入pr?pr预设如何导入?

    prfpset文件是一种可以导入到Adobe Premiere Pro中使用的预设文件 xff0c 导入后即可为你的画面进行调色 xff0c 不同的pr预设拥有不同的调色效果 xff0c 那么prfpset格式预设怎么打开 xff1f pr
  • How does java technology relate to cloud computing?

    Java Paas shootout 64 IBM developer Cloud computing is always a hot topic around IT field today How can it bring to us H
  • LCD1602A接线图

    转载于 https my oschina net surenpi blog 481697
  • 3dmax2020卸载/安装失败/如何彻底卸载清除干净3dmax2020注册表和文件的方法

    3dmax2020提示安装未完成 xff0c 某些产品无法安装该怎样解决呢 xff1f 一些朋友在win7或者win10系统下安装3dmax2020失败提示3dmax2020安装未完成 xff0c 某些产品无法安装 xff0c 也有时候想重
  • matlab练习程序(生成黑白网格)

    提供了两种生成方法 xff0c 一个是自己编程实现 xff0c 比较灵活 xff1b 另一个是调用系统的checkerboard函数 xff0c 似乎只能生成8 8网格 至于用途 xff0c 也许可以用来下国际象棋 自己函数生成 xff1a
  • git 基本操作

    配置 user name user email git config global user name 34 fatdai 34 git config global user email 34 1012607376 64 qq com 34
  • 第五篇:明确拒绝不想编译器自动生成的拷贝构造函数和赋值运算符重载函数...

    前言 如果你不想要编译器帮你自动生成的拷贝机制 参考前文 xff0c 那么你应当明确的拒绝 如何拒绝 xff1f 这便是本文要解决的主要问题 问题描述 当你定义了一个类 xff0c 而这个类中各对象之间也是封装的 禁止同类对象之间的相互赋值
  • springboot开启access_log日志输出

    由于在调试时需要查看access log日志 xff0c 但是springboot默认并没有开启 xff0c 因此查看了一下文档 xff0c 在springboot的配置文件中添加如下设置 xff0c 即可将日志输出当磁盘文件中以供查看 日
  • 向论文作者要代码的邮件怎么写

    Reference 找人要代码的邮件怎么写

随机推荐

  • 当 better-scroll 遇见 Vue

    作者 xff1a 滴滴公共前端 黄轶 在我们日常的移动端项目开发中 xff0c 处理滚动列表是再常见不过的需求了 以滴滴为例 xff0c 可以是这样竖向滚动的列表 xff0c 如图所示 xff1a 竖向列表 也可以是横向滚动的导航栏 xff
  • elementUI中form表单的upload上传图片及校验总结

    自定义校验方法 因为我的项目是 分情况 可以选择是否有图 所以我定义了一个变量hasFmt 当他为false的时候 才会要求上传 走这个校验方法 rules里声明这个方法 var valiIcon 61 rule value callbac
  • iview Table表格组件无法拆分单元格的解决思路

    最近在开发的Vue项目中 xff0c 使用了iview第三方UI库 对于表格组件的需求是最多的 xff0c 但是在一些特定场景下 xff0c 发现iview的表格组件没有单元格合并与拆分的API xff0c 搜了一下发现很多同学提问关于iv
  • Django+Semantic-ui建立Blog网站(一、基本框架)

    Django应该算是最流行的web应用框架了吧 xff0c 而语义化的CSS框架semantic ui我觉得非常好用 xff0c 使用这个组合做一个blog站点 关于Django的详细介绍以及MTV模式的相关有优点 xff0c 请翻阅官方文
  • Eclipse插件开发首选项篇

    介绍 如果你的插件需要保存一些数据 xff08 参数 xff09 xff0c 比如要设置一些ip地址等等 这时候 xff0c 就要用到Eclipse提供的首选项这个扩展点 我们这里的首选项的数据类型只包括Java中的基本数据类型 扩展点 o
  • java 判断字符串是否是json格式

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 两种实现方式 xff1a 1 通过fastjson解析来判断 xff0c 解析成功 xff0c 是json格式 xff1b 否则 xff0c 不是json格式 xff1a
  • Error response from daemon: Error processing tar file(exit status 1): remove /hosts: device or resou

    2019独角兽企业重金招聘Python工程师标准 gt gt gt You cannot copy over etc hosts Docker provides the container with a custom etc hosts f
  • Jquery动态添加标签元素,在指定标签前或者标签后(append/prepend用法)

    Jquery动态添加标签元素 在指定标签前或者标签后 xff08 append prepend用法 xff09 1 append 方法在被选元素的结尾插入指定内容 2 appendTo 方法在被选元素的结尾插入 HTML 元素 3 prep
  • ASP.NET中常用正则表达式

    34 d 43 34 非负整数 xff08 正整数 43 0 xff09 34 0 9 1 9 0 9 34 正整数 34 d 43 0 43 34 非正整数 xff08 负整数 43 0 xff09 34 0 9 1 9 0 9 34 负
  • 总结 IOS 7 内存管理

    iOS7的一些总结 5 iOS中的内存管理 我们知道 xff0c 为了更加方便地处理内存管理问题 xff0c 将开发人员从繁琐的内存的分配和释放工作中解放出来而专注于产品和逻辑 xff0c iOS提供了一种有效的方法 xff0c 即自动引用
  • 《STL源码剖析》---list容器insert操作的个人理解

    最近在看STL源码剖析 xff0c 感觉还是挺深奥的 xff0c 感觉看不太懂 今天在看list容器这块 xff0c 讲到了insert操作 xff0c 便记录一番自己的理解吧 摘抄书上的 xff1a iterator insert ite
  • PROCESS_YIELD()宏和C语言的switch语句< contiki学习笔记之七>

    写在前面 xff1a 按照main 函数的代码一行一行的分析 xff0c 该是看到了 etimer process 这个位置 但是etimer process实现里的一个宏 PROCESS YIELD 引出了很多故事 xff0c 于是单独把
  • 用c语言指针实现vector,C使用指针将对象添加到Vector中

    我有一个向量添加包含 SDL Surface 指针作为数据成员的对象 xff0c 这意味着我必须使用复制构造函数来实现指针的深层复制 该对象释放析构函数中的表面 指针 xff0c 这就是问题发生的地方 当对象被添加到向量中时 通过按下按钮
  • 【Http认证方式】——Basic认证

    访问请求 xff1a http 192 168 2 113 8080 geoserver rest workspaces时 xff0c 浏览器弹出窗口需要输入用户名和密码 xff0c 并且 xff0c 如果不输入或者输入错误 xff0c 浏
  • c++ http请求

    平常我们要访问某个URL一般都是通过浏览器进行 xff1a 提交一个URL请求后 xff0c 浏览器将请求发向目标服务器或者代理服务器 xff0c 目标服务器或者代理服务器返回我们所需要的数据 xff0c 浏览器接收到这些数据后保存成文件并
  • libcurl实现http登录功能

    用Fiddler Web Debugger捕捉http数据包 xff1a 观察看看 xff0c POST请求的地址为http passport cnblogs com login aspx ReturnUrl 61 http 3a 2f 2
  • 服务器机柜和网络机柜的区别

    原文转载自 http www fwqtg net 服务器机柜 xff0c 用来组合安装面板 插件 插箱 电子元件 器件和机械零件与部件 xff0c 使其构成一个整体的安装箱 服务器机柜由框架和盖板 xff08 门 xff09 组成 xff0
  • Eclipse+Maven创建webapp项目<一>

    Eclipse 43 Maven创建webapp项目 lt 一 gt 1 开启eclipse xff0c 右键new other xff0c 如下图找到maven project 2 选择maven project xff0c 显示创建ma
  • java日期格式(年月日时分秒毫秒)

    package test remote tools combine import java text SimpleDateFormat import java util Calendar import java util Date impo
  • 游戏中的帧同步要求的计算一致性——定点数(Fixed Point)

    最近做了一款帧同步游戏 xff0c 其寻路算法采用了RVO算法 但是由于是移动端的游戏 需要在不同的设备上运行 xff0c 其所有运算必须符合一致性 即所有客户端运算出来的结果必须一致 但是由于浮点数的特性 xff0c 具有误差 xff0c