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

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

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

游戏中的时间线

真实时间线

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

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

游戏时间线

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

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

全局时钟的实现方式

大多数操作系统都提供获取系统时间的函数,但这些函数都是低分辨率的,精确到秒或毫秒,则对于全局时钟而言,是不满足要求的。那么,我们应该如何实现呢?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. python+requests+yaml实现接口自动化用例

    前言:最近也思考了一下怎么做接口自动化,以下内容属于自己目前阶段所学习到的内容,也逐渐投入自己实际工作中,把最近的学习新得跟大家分享下,话不多说,切入正题. 对接口自动化测试用例的思考:接口测试大多测 ...

  2. 超 Nice 的表格响应式布局小技巧

    今天,遇到了一个很有意思的问题,一名群友问我,仅仅使用 CSS,能否实现这样一种响应式的布局效果: 简单解析一下效果: 在屏幕视口较为宽时,表现为一个整体 Table 的样式 而当屏幕视口宽度较小时, ...

  3. ASP.NET Core 6 从入门到企业级实战开发应用技术汇总

    系列目录     [已更新最新开发文章,点击查看详细] 本系列博客主要介绍.NET6相关技术,从基础入门.进阶提升到高级升华,最后通过一个企业级项目实战来检验技术应用能力.把个人技术与经验分享出来,抛 ...

  4. 讲给测试人员的docker知识

    docker对测试来说有什么用 docker类似于Windows系统的虚拟机,对于测试来说docker意味着一种新的测试环境部署方式,由于其镜像分层的设置,我们可以在一台物理机上同过docker的方式 ...

  5. Tapdata 与阿里云 PolarDB 开源数据库社区联合共建开放数据技术生态

      近日,阿里云 PolarDB 开源数据库社区宣布将与 Tapdata 联合共建开放数据技术生态.在此之际,一直专注实时数据服务平台的 Tapdata ,也宣布开源其数据源开发框架--PDK(Plu ...

  6. Tapdata 在线研讨会:DaaS vs 大数据平台,是竞争还是共处?

    从20年前的传统数仓,到10年前大数据平台,5年前开始火热的数据中台以及最近出现的湖仓一体新数据平台,今天被数据孤岛困扰的企业,面临着太多的选择.这些数据产品及架构有一个共性:他们本质上解决的大部分都 ...

  7. RS485 MODBUS RTU通信协议

    1.RS485接口标准 RS485由RS232和RS422发展而来,弥补了抗干扰能力差.通信距离短.速率低的缺点,增加了多点.双向通信能力,即允许多个发送器连接在同一条主线上,同时增加了发送器的驱动能 ...

  8. ShardingSphere 云上实践:开箱即用的 ShardingSphere-Proxy 集群

    本次 Apache ShardingSphere 5.1.2 版本更新为大家带来了三大全新功能,其中之一即为使用 ShardingSphere-Proxy chart 在云环境中快速部署一套 Shar ...

  9. Java的main函数(命令行传参)

    javac :编译命令 java  :执行命令

  10. 一个豆瓣电影Top250爬虫

    一个爬虫 这是我第一次接触爬虫,写的第一个爬虫实例. https://movie.douban.com/top250 模块 import requests #用于发送请求 import re #使用正 ...