帧同步原理

news2024/10/1 17:36:56

帧同步和状态同步区别

在这里插入图片描述

在这里插入图片描述

状态同步:发操作,收状态
帧同步:发操作,收操作

逻辑严格排序

经常会有需要排序的列表或者数组,比如攻击距离自己最近的敌人,这时候就需要将身边的敌人进行距离排序,一般来说只要排序距离就行了,但是如果出现两个敌人距离一样的时候,就会导致在不同的机器上选择的敌人是不同的。所以排序一定要排到id为止,才能避免出现条件相同顺序不同的问题。

浮点数与定点数

浮点数:精度为7位到8位小数,有一定的误差,不同的硬件软件平台也会有些许差异,随着游戏进行,这一点点误差会逐渐放大,导致不同客户端的计算结果不一致
定点数:把整数部分和小数部分拆分开来,都用整数的形式表示,小数点位置固定,缺点是占用空间更大

实现自定义定点数

using System;

/// <summary>
/// 自定义64位定点数
/// </summary>
[Serializable]
public struct Fixed64 : IEquatable<Fixed64>, IComparable, IComparable<Fixed64>
{
    public long value;
    //小数部分位数
    private const int FRACTIONALBITS = 12;
    private const long ONE = 1L << FRACTIONALBITS;
    public static Fixed64 Zero = new Fixed64(0);
    
    /// <summary>
    /// ֱ直接对value赋值
    /// </summary>
    Fixed64(long value)
    {
        this.value = value;
    }
    
    /// <summary>
    /// 传入具体数字的构造函数
    /// </summary>
    public Fixed64(int value)
    {
        this.value = value * ONE;
    }

    /// <summary>
    /// 重载运算符
    /// </summary>
    public static Fixed64 operator +(Fixed64 a, Fixed64 b)
    {
        return new Fixed64(a.value + b.value);
    }
    
    public static Fixed64 operator -(Fixed64 a,Fixed64 b)
    {
        return new Fixed64(a.value - b.value);
    }
    
    public static Fixed64 operator*(Fixed64 a,Fixed64 b)
    {
        //直接相乘后面会多出0,所以这里要右移
        return new Fixed64((a.value >> FRACTIONALBITS) * b.value);
    }
    
    public static Fixed64 operator/(Fixed64 a,Fixed64 b)
    {
        return new Fixed64((a.value << FRACTIONALBITS) / b.value);
    }
    
    public static bool operator ==(Fixed64 a,Fixed64 b)
    {
        return a.value == b.value;
    }
    
    public static bool operator !=(Fixed64 a,Fixed64 b)
    {
        return !(a == b);
    }
    
    public static bool operator>(Fixed64 a,Fixed64 b)
    {
        return a.value > b.value;
    }
    
    public static bool operator <(Fixed64 a, Fixed64 b)
    {
        return a.value < b.value;
    }
    
    public static bool operator >=(Fixed64 a, Fixed64 b)
    {
        return a.value >= b.value;
    }
    
    public static bool operator <=(Fixed64 a, Fixed64 b)
    {
        return a.value <= b.value;
    }
    
    /// <summary>
    /// 显式强制类型转换,Fixed64转换为long类型
    /// </summary>
    public static explicit operator long(Fixed64 value)
    {
        return value.value >> FRACTIONALBITS;
    }
    
    public static explicit operator Fixed64(long value)
    {
        return new Fixed64(value);
    }
    
    public static explicit operator float(Fixed64 value)
    {
        return (float)value.value / ONE;
    }
    
    public static explicit operator Fixed64(float value)
    {
        return new Fixed64((long)(value * ONE));
    }
    
    public int CompareTo(object obj)
    {
        return value.CompareTo(obj);
    }

    public int CompareTo(Fixed64 other)
    {
        return value.CompareTo(other.value);
    }

    public bool Equals(Fixed64 other)
    {
        return value == other.value;
    }
    
    public override int GetHashCode()
    {
        return value.GetHashCode();
    }
    
    public override bool Equals(object obj)
    {
        return obj is Fixed64 && ((Fixed64)obj).value == value;
    }
    
    public override string ToString()
    {
        return ((float)this).ToString();
    }
}

实现自定义定点数向量

using System;

/// <summary>
/// 自定义定点数三维向量
/// </summary>
public struct Fixed64Vector3 : IEquatable<Fixed64Vector3>
{
    public Fixed64 x;
    public Fixed64 y;
    public Fixed64 z;
    
    public Fixed64Vector3(Fixed64 x, Fixed64 y, Fixed64 z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    
    public Fixed64 this[int index]
    {
        get
        {
            if (index == 0)
                return x;
            else if (index == 1)
                return y;
            else
                return z;
        }
        set
        {
            if (index == 0)
                x = value;
            else if (index == 1)
                y = value;
            else
                y = value;
        }
    }
    
    public static Fixed64Vector3 Zero
    {
        get { return new Fixed64Vector3(Fixed64.Zero, Fixed64.Zero, Fixed64.Zero); }
    }

    public static Fixed64Vector3 operator +(Fixed64Vector3 a, Fixed64Vector3 b)
    {
        Fixed64 x = a.x + b.x;
        Fixed64 y = a.y + b.y;
        Fixed64 z = a.z + b.z;
        return new Fixed64Vector3(x, y, z);
    }

    public static Fixed64Vector3 operator -(Fixed64Vector3 a, Fixed64Vector3 b)
    {
        Fixed64 x = a.x - b.x;
        Fixed64 y = a.y - b.y;
        Fixed64 z = a.z - b.z;
        return new Fixed64Vector3(x, y, z);
    }

    public static Fixed64Vector3 operator *(Fixed64 d, Fixed64Vector3 a)
    {
        Fixed64 x = a.x * d;
        Fixed64 y = a.y * d;
        Fixed64 z = a.z * d;
        return new Fixed64Vector3(x, y, z);
    }

    public static Fixed64Vector3 operator *(Fixed64Vector3 a, Fixed64 d)
    {
        Fixed64 x = a.x * d;
        Fixed64 y = a.y * d;
        Fixed64 z = a.z * d;
        return new Fixed64Vector3(x, y, z);
    }

    public static Fixed64Vector3 operator /(Fixed64Vector3 a, Fixed64 d)
    {
        Fixed64 x = a.x / d;
        Fixed64 y = a.y / d;
        Fixed64 z = a.z / d;
        return new Fixed64Vector3(x, y, z);
    }
    
    public static bool operator ==(Fixed64Vector3 lhs, Fixed64Vector3 rhs)
    {
        return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z;
    }

    public static bool operator !=(Fixed64Vector3 lhs, Fixed64Vector3 rhs)
    {
        return lhs.x != rhs.x || lhs.y != rhs.y || lhs.z != rhs.z;
    }

    /// <summary>
    /// 进行左移和右移是为了增加哈希值的混淆性和分布性,参考Vector3中的写法
    /// </summary>
    public override int GetHashCode()
    {
        return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2);
    }
    
    public override bool Equals(object obj)
    {
        return ((Fixed64Vector3)obj) == this;
    }
    
    public override string ToString()
    {
        return string.Format("x:{0} y:{1} z:{2}", x, y, z);
    }
    
    public bool Equals(Fixed64Vector3 other)
    {
        return this == other;
    }
}

帧同步流程

逻辑帧:游戏被划分为连续的游戏帧,每一帧就是一个时间片段,帧同步的目标是把每一帧中所有客户端的操作同步起来

在这里插入图片描述

客户端-服务端架构:每个客户端把自己的一个或多个操作发给服务端,服务端把这些操作应用到游戏状态中,并将结果发给所有客户端,保持一致性,上图中方框表示服务端

在这里插入图片描述

严格帧同步:每个关键帧只有当服务器集齐了所有玩家的操作指令,才可以进行转发,进入下一个关键帧,否则就要等待最慢的玩家。
上图表示严格帧同步流程,服务器和客户端约定每5帧同步一次,这里每一帧的时间间隔由服务器决定,UPDATE 0表示服务器发的第0帧数据,CTRL 0表示客户端发的第0帧操作,服务器在第5帧开始前收到了客户端A,B的数据,进行打包再转发给A,B。服务端在第10帧开始时没有收到所有客户端的数据,开始等待,直到收到所有客户端的数据。

乐观帧同步:服务器定时广播操作指令,而不必等待慢的客户端

帧同步服务端代码编写相对简单,只是转发数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1472300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在having、select子句中使用子查询

目录 在having子句中使用子查询 统计出部门平均工资高于公司平均工资的部门编号、平均工资、部门人数 在select子句中使用子查询 查询每个员工的编号、姓名、职位、部门名称 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 在havin…

2024.2.26

1、实现信号灯集 sem.c #include<myhead.h>union semun {int val; /* Value for SETVAL */struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */unsigned short *array; /* Array for GETALL, SETALL */struct seminfo *__buf; /* Buffer …

备考2025年考研数学(一)真题练习和解析——填空题

今天距离2025年考研预计还有10个月的时间&#xff0c;看起来挺长&#xff0c;但是对于备考2025年考研的同学来说&#xff0c;必须用好每一天。为了帮助大家提升考研数学一的成绩&#xff0c;我收集整理了1987-2024年的考研数学一的真题和解析&#xff0c;并把2015-2024年十年的…

一个39岁程序员的自白,大龄程序员的出路在哪里?

一个39岁程序员的自白&#xff0c;大龄程序员的出路在哪里&#xff1f; 大龄程序员&#xff0c;最悲惨的&#xff0c;可能是但凡你发个贴&#xff0c;下面就会有类似这种人来怼你 本文来自知乎一个大龄程序员老哥&#xff08;白圣君&#xff09;的自白&#xff0c;涤生哥已经经…

现在骨传导耳机什么牌子最好?专业选购指南与避坑策略

近些年来&#xff0c;耳机行业飞速发展&#xff0c;耳机已经成为日常生活中不可或缺的伙伴&#xff0c;无论是休闲时刻还是运动健身&#xff0c;耳机都伴随着我们。然而长时间使用传统的入耳式耳机可能会导致听力受损、容易脱落和不卫生等问题。为了解决这些问题&#xff0c;满…

【GameFramework框架内置模块】3、数据表(Data Table)

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录&#xff1a; https://blog.csdn.net/q7…

3 easy 26. 删除有序数组中的重复项

双指针&#xff1a; //给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 //一致 。然后返回 nums 中唯一元素的个数。 // // 考虑 nums 的唯…

服务器防漏扫

什么是漏扫&#xff1f; 漏扫是漏洞扫描的简称。漏洞扫描是一种安全测试方法&#xff0c;用于发现计算机系统、网络或应用程序中的潜在漏洞和安全弱点。通过使用自动化工具或软件&#xff0c;漏洞扫描可以检测系统中存在的已知漏洞&#xff0c;并提供相关的报告和建议&#xf…

如何在Linux部署Portainer并结合内网穿透远程管理本地Docker容器

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

【牛牛送书 | 第四期】《高效使用Redis:一书学透数据存储与高可用集群》带你快速学习使用Redis

前言&#xff1a; 当今互联网技术日新月异&#xff0c;随着数据量的爆炸式增长&#xff0c;如何高效地存储和管理数据成为了每个公司都必须面对的挑战。与此同时&#xff0c;用户对于应用程序的响应速度和稳定性要求也越来越高。在这个背景下&#xff0c;Redis 作为一个…

C++ 学习之函数对象

C 函数对象基本概念 在C中&#xff0c;函数对象&#xff08;Function Objects&#xff09;是一种类或结构体&#xff0c;它重载了函数调用运算符operator()&#xff0c;因此可以像函数一样被调用。函数对象有时也被称为仿函数&#xff08;Functor&#xff09;。 以下是关于C函…

备战蓝桥杯---基础算法刷题2

题目有一点水&#xff0c;不过还是有几个好题的&#xff0c;我在这分享一下&#xff1a; 很容易想到先往最高处跳再往最低处跳&#xff0c;依次类推&#xff0c;那怎么保证其正确性呢&#xff1f; 证法1. 在此&#xff0c;我们从0开始&#xff0c;假设可以跳到a,b,c(a<b<…

Linux中消息队列

消息队列 概念 消息队列是System V IPC对象的一种消息队列有消息队列ID来唯一标识消息队列就是一个消息列表。用户可以在消息队列中添加消息、读取信息等消息队列可以按照类型来发送/结束消息 消息队列使用步骤 打开/创建消息队列 msgget向消息队列发送信息 msgsnd从消息队…

4.4 MySQL存储

目录 1、使用前提 2、使用连接数据库最初步骤 2.1 最初步骤 2.2 connect()方法中参数简单传递 3、创建数据库(创建架构)和创建表 3.1 创建数据库(创建架构) 3.2 创建表 3.2.1 基本创建 3.2.2 创建自增主键 4、Pycharm 可视化连接 MySQL 图形界面 5、插入、更新、查询…

项目管理工具git

git 1. git介绍1.1. 版本控制系统 2. 创建本地版本库2.1 概念2.2 操作步骤 3. 修改文件4. 练习: 添加一个本地项目到仓库5. 添加远程仓库5.1 添加远程仓库5.2 本地仓库同步到远程仓库5.3 克隆远程仓库到本地5.4 SSH设置 6. 分支管理6.1 创建分支6.2 切换分支6.3 合并分支6.4 解…

基于yolov5的苹果检测(pytorch框架)【python源码+UI界面+功能源码详解】

功能演示&#xff1a; 基于yolov5的苹果检测系统&#xff0c;系统既能够实现图像检测&#xff0c;也可以进行视屏和摄像实时检测_哔哩哔哩_bilibili &#xff08;一&#xff09;简介 基于yolov5的苹果检测系统是在pytorch框架下实现的&#xff0c;这是一个完整的项目&#xf…

Go语言必知必会100问题-06 生产者端接口

生产者端接口 Go语言必知必会100问题-05 接口污染中介绍了程序中使用接口是有价值的。在编码的时候&#xff0c;接口应该放在哪里呢&#xff1f;这是Go开发人员经常有误解的一个问题&#xff0c;本文将深入分析该问题。 在深入探讨问题之前&#xff0c;先对提及的术语做一个定…

如何使用Inno Setup制作Unity构建程序的Windows安装程序

1. 准备 &#xff08;1&#xff09;准备好Unity构建的程序集合 必须包括&#xff1a; Data文件夹&#xff08;xxx_Data&#xff09; Mono文件夹&#xff08;MonoBleedingEdge&#xff09; 打包的应用程序文件&#xff08;xxx.exe&#xff09; Unity播放器dll文件&#xff…

mac flutter 配置

下载Flutter Sdk 直接访问官网无法下载&#xff0c;需要访问中国镜像下载 Flutter SDK 归档列表 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter Start building Flutter Android apps on macOS - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 下载后解压…

HCIA-Datacom实验指导手册:5.1 实验一:FTP SFTP TFTP 基础配置实验

HCIA-Datacom实验指导手册&#xff1a;5.1 实验一&#xff1a;FTP 基础配置实验 一、实验介绍&#xff1a;二、实验拓扑&#xff1a;三、实验目的&#xff1a;四、配置步骤&#xff1a;步骤 1 设备基础配置步骤 2 在 Router 上配置 FTP 和SFTP服务器功能及参数步骤 3 配置本地 …