我们如何理解时间。在现实生活中,时间就是一个有方向的直线。从一个无穷远到另一个无穷远。用数学去抽象地思考,它就是一个从无穷小到无穷大的一维轴。

那么,对于游戏而言,我们需要考虑关于时间的哪一部分?游戏本质就是开发者作为上帝创造的产物,在我们人为创造的世界中,自我们开始游戏的时候,这个世界的所有物体就应该根据一个既定的时间线作为参照物来进行运动——这个标准不是服务于策划文案中的年代、一天的早中晚等写实的时间线,而是动画、逻辑等相关仿真运行的参照。

那么我们应该如何去用代码实现游戏中的时间线呢?我们先对游戏中的时间线进行分析。

游戏中的时间线

真实时间线

真实的时间线指的是和现实的时间线的频率保持一致的时间线。首先我们先明确一点,对于未运行的游戏而言,时间线是没有意义的,因此,游戏中真实的时间线是以软件启动的时刻作为起点,而以软件关闭作为时间线的终点。

游戏引擎一般将真实时间线作为引擎的全局时间线,即全局时钟。全局时钟是游戏时间线的基石,若全局时间线出问题,则游戏所有与时间相关的操作都会发生错误。因此,它的频率严格一致,计时应当是高精度的,且不随游戏的其他因素的变化而变化。此模块的代码将置于核心代码中的最底层,并对其修改操作进行严格的限制。

游戏时间线

游戏时间线依托于真实时间线(全局时钟)。根据不同的需求(一般指快进和减速),游戏中将拥有各种各样的时间线,这些时间线服务于相对应游戏物体的运动和变化。相较于全局时钟严格的不可变性,游戏时钟可以很好的实现设计者的如下需求:

  • 游戏暂停
  • 游戏恢复
  • 人物动画加速
  • 人物动画减速
  • 时间回溯
  • ...

全局时钟的实现方式

大多数操作系统都提供获取系统时间的函数,但这些函数都是低分辨率的,精确到秒或毫秒,则对于全局时钟而言,是不满足要求的。那么,我们应该如何实现呢?CPU恰好提供了硬件级别的高精度时钟供我们去计时。

CPU的高分辨率计时器:每个CPU都存在一个计时器,其功能就是将计算机自启动或重置起经过CPU的周期数记录到对应的寄存器中。

不同硬件访问CPU寄存器的方式是不同的,幸运的是Windows这一个巨大的抽象层帮助我们忽略了各式各样硬件的差异。在Windows API中,获取计时寄存器的相关函数如下:

  • QueryPerformanceCounter():计时寄存器数值
  • QueryPerformanceFrequency():每一秒计时器递增的次数(即计时器频率)

利用这两个函数,我们可以实现一个高精度的计时器作为游戏引擎的全局时钟。极简代码如下所示。

#include "Windows.h"
class Timer
{
public:
Timer()
{
QueryPerformanceFrequency((LARGE_INTEGER*)&m_Frequence);
QueryPerformanceCounter((LARGE_INTEGER*)&m_StartStamp);
} //获取至生成计时器以来运行的秒数
double RunSeconds()
{
__int64 current=0;
QueryPerformanceCounter((LARGE_INTEGER*)&current);
return (current-m_StartStamp)/(double)m_Frequence;
}
private:
__int64 m_StartStamp;
__int64 m_Frequence; }

引擎之旅 Chapter.1 高分辨率时钟的更多相关文章

  1. 引擎之旅 Chapter.4 日志系统

    关于近段时间为何没有更新的解释:Find a new job. 目录 引言 日志语句的分类 控制台窗体 和 VSOutput Tab的日志打印 存储至特定的文件中 展示堆栈信息 引言 一般来说,一个优 ...

  2. 引擎之旅 Chapter.2 线程库

    预备知识可参考我整理的博客 Windows编程之线程:https://www.cnblogs.com/ZhuSenlin/p/16662075.html Windows编程之线程同步:https:// ...

  3. 引擎之旅 前传:C++代码规范

    自己以前写代码时,一个项目一个风格.单人开发的工作使得我并没有注意到代码规范性和可读性的问题.每当项目结束后,看到自己杂乱无章的代码,完全没有二次开发和重构的欲望. 写代码就应该像写诗一样优雅. by ...

  4. Linux时间管理涉及数据结构和传统低分辨率时钟的实现

    上篇文章大致描述了Linux时间管理的基本情况,看了一些大牛们的博客感觉自己写的内容很匮乏,但是没办法,只能通过这种方式提升自己……闲话不说,本节介绍下时间管理下重要的数据结构 设备相关数据结构 // ...

  5. linux 时间管理——概念、注意点(一)【转】

    转自:http://www.cnblogs.com/openix/p/3324243.html 参考:1.http://bbs.eyeler.com/thread-69-1-1.html        ...

  6. 14.1.1 InnoDB as the Default MySQL Storage Engine

    14.1 Introduction to InnoDB 14.1.1 InnoDB as the Default MySQL Storage Engine 14.1.2 Checking InnoDB ...

  7. 初探linux子系统集之timer子系统(二)

    想着博客中还没有翻译过一篇文章,虽然英文水平有限,但是借助google翻译慢慢地翻译出一篇文章也是不错的选择.那就来学习下hrtimer的文档吧,翻译的略搓,可以直接跳过这篇,这里仅作为学习的过程!^ ...

  8. c++ 常用头文件

    1.#include<iostream> iostream 的意思是输入输出流.#include<iostream>是标准的C++头文件,任何符合标准的C++开发环境都有这个头 ...

  9. Linux内核入门到放弃-时间管理-《深入Linux内核架构》笔记

    低分辨率定时器的实现 定时器激活与进程统计 IA-32将timer_interrupt注册为中断处理程序,而AMD64使用的是timer_event_interrupt.这两个函数都通过调用所谓的全局 ...

随机推荐

  1. 分享|智慧环保-生态文明信息化解决方案(附PDF)

    内容摘要: 生态文明建设被提到前所未有的战略高度,我们既要绿水青山,也要金山银山.宁要绿水青山,不要金山银山,而且绿水青山就是金山银山.要正确处理好经济发展同生态环境保护的关系,牢固树立保护生态环境就 ...

  2. 正在运行中的docker容器设置自动重启

    # demo : 你的容器名称 docker update –-restart=always demo

  3. Tapdata肖贝贝:实时数据引擎系列(三) - 流处理引擎对比

      摘要:本文将选取市面上一些流计算框架包括 Flink .Spark .Hazelcast,从场景需求出发,在核心功能.资源与性能.用户体验.框架完整性.维护性等方面展开分析和测评,剖析实时数据框架 ...

  4. Java8 Stream 的最佳实践

    Java8 Stream 的最佳实践 java8stream提供了对于集合类的流失处理,其具有以下特点: Lazy Evaluation(长度可以无限) 只能使用一次 内部迭代 Lazy Evalua ...

  5. BUCK 电路PSIM仿真模型搭建之二 (传递函数模块的使用)

    1. 利用S函数模块进行环路仿真 将PI 写成 截止频率的表示形式 Kp* (Ti*s+1)/Ti*s  ,  这里Kp = 20,  Ti = 0.0001  ,  写入仿真模型参数框 仿真结果: ...

  6. 基于ABP实现DDD--聚合和聚合根实践

      在下面的例子中涉及Repository.Issue.Label.User这4个聚合根,接下来以Issue聚合为例进行分析,其中Issue聚合是由Issue[聚合根].Comment[实体].Iss ...

  7. 零基础学Java(9)在mac上运行命令行提示"找不到或无法加载主类"

    天坑 遇到的问题:使用命令行执行命令:java EightSample,会报以下错误 错误: 找不到或无法加载主类 EightSample 运行环境 mac系统 IntelliJ IDEA编译器 Ja ...

  8. mybatis-plus详解

    旧的代码生成 记得导包,依赖如下 <!-- mybatis-plus --> <dependency> <groupId>com.baomidou</grou ...

  9. CDH集群日常

    1.交换内存告警 该告警通常就是使用了swap分区导致的,在生产环境中,如果服务器内存是256G:建议关闭swap分区,减少跟数据盘之间的交互: 2.修改swap阈值 任何:表示只要使用了swap分区 ...

  10. [eJOI2019]异或橙子 题解

    简要题面 维护一个数据结构,支持单点修改,询问区间所有子区间的异或和的异或和 . 做法 首先,题目要求所有子区间的异或和的异或和,发现每个元素异或两次就变成 \(0\),所以考虑统计每个元素出现的次数 ...