- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
一个简单的游戏循环运行起来有点像这样:
MSG msg;
while (running){
if (PeekMessage(&msg, hWnd, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
try{
onIdle();
}
catch(std::exception& e){
onError(e.what());
close();
}
}
(取自this question)
为了示例,我在这里以 Windows 为例,它可以是任何平台。如果我弄错了请纠正我,但这样的循环会使用 100% 的 cpu/核心(在我的计算机上使用 50% 的一个核心),因为它总是检查 running
变量的状态.
我的问题是,使用操作系统(在示例 Windows 中)定时器功能实现游戏循环是否会更好(性能方面),根据每个游戏逻辑所需的滴答数设置所需的间隔第二?我问这个是因为我假设定时器功能使用 CPU 的 RTC 中断。
最佳答案
通常,即使用户什么都不做,游戏也会一直绘制新帧。这通常会发生在您调用 onIdle() 的地方。如果您的游戏仅在用户按下按钮或类似按钮时更新窗口/屏幕,或者偶尔在两者之间更新,则 MSGWaitForMultipleObjects
是一个不错的选择。
但是,在连续动画游戏中,如果可以的话,您通常根本不想在渲染线程中阻塞或休眠,而是希望以最大速度渲染并依赖在垂直同步上作为 throttle 。这样做的原因是计时、阻塞和休眠往好里说是不精确的,往坏里说是不可靠的,而且它很可能会给您的动画添加令人不安的人工制品。
您通常想要做的是尽快将属于帧的所有内容推送到图形 API(最有可能是 OpenGL,因为您说的是“任何平台”),向工作线程发出信号以开始执行游戏逻辑和物理等,并且然后在 SwapBuffers 上阻塞。
所有计时器、超时和 sleep 都受调度程序分辨率的限制,在 Windows 下为 15ms(可以使用 timeBeginPeriod
设置为 1ms)。在 60fps 下,一帧是 16.666ms,所以阻塞 15ms 是灾难性的,但即使是 1ms 仍然是相当长的时间。您无法获得更好的分辨率(这在 Linux 下要好得多)。
Sleep
,或任何具有超时的阻塞函数,保证您的进程至少只要您要求就可以休眠(事实上,在 Posix 系统上,如果发生中断,它可能睡得少)。它不保证您的线程会在时间一到时立即运行,也不提供任何其他保证。
Windows 下的 Sleep(0) 更糟。文档说“线程将放弃其剩余时间片但保持就绪状态。请注意,不能保证就绪线程立即运行”。现实情况是它在大多数情况下都可以正常工作,阻塞从“根本不”到 5-10 毫秒不等,但有时我也看到 Sleep(0) 阻塞 100 毫秒,这在它发生时是灾难性的.
使用 QueryPerformanceCounter
是自找麻烦 -- just don't do it .在某些系统(带有最新 CPU 的 Windows 7)上,它会工作得很好,因为它使用了可靠的 HPET,但在许多其他系统上,您会看到各种奇怪的“时间旅行”或“倒转时间”效果,没有人可以解释或调试。那是因为在那些系统上,QPC 的结果读取取决于 CPU 频率的 TSC 计数器。 CPU 频率不是恒定的,多核/多处理器系统上的 TSC 值不需要保持一致。
然后是同步问题。两个独立的计时器,即使以相同的频率计时,也必然会变得不同步(因为没有“相同”这样的东西)。您的显卡中已经有一个计时器在进行垂直同步。使用这个同步意味着一切都会正常,使用不同的同步意味着事情最终会不同步。不同步可能根本没有效果,可能会绘制一个半完成的帧,或者可能会阻塞一整帧,等等。
虽然丢失一帧通常不是什么大问题(如果它只是一个并且很少发生),但在这种情况下,您首先可以完全避免这种情况。
关于windows - 使用操作系统计时器处理游戏循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5559985/
如主题所述,是否有可能没有 future 的问题?。基本上我发布此线程以供将来引用,以便人们可以观看该场景。mongodb 被限制为 2Gb 的原因是什么?能否请您指出引用资料,以便像我这样的菜鸟可以
我正在使用 Bootstrap 4 轮播。它适用于所有 Windows 和 Android 操作系统,但不适用于 Mac 和 iPhone 操作系统。有什么解决办法吗?这是我的代码github.com
Condition Synchinzation--条件同步 实现同步有两种方式:competition(compete for a variable that two processes al
1 定义:计算机资源虚拟化 服务器虚拟化主要通过软件技术将物理服务器的硬件资源抽象化,创建多个独立的虚拟服务器环境。 虚拟化技术是当今云计算、大数据和AI得以繁荣发展的核心基础技术
目录 内存管理硬件结构 早期内存的使用方法 分段 分页 逻辑地址,线性地址(intel架构) 虚拟地址 物理地址
页表的一些术语 现在Linux内核中支持四级页表的映射,我们先看下内核中关于页表的一些术语: 全局目录项,PGD(Page Global Directory) 上级目录项,PUD(
1. 文件路径 绝对路径 绝对路径 (absolute path) : 以一个盘符开头的路径,就是绝对路径 例如这里的 D:\java\IntelliJ IDEA Community Edition
1. 进程介绍 1.1 进程的概念 程序是由指令和数据组成的,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,将数据加载至内存。在指令运行过程中还需要用到磁盘和网络等设备。进程就是用来加载指
1. 文件路径 绝对路径 绝对路径 (absolute path) : 以一个盘符开头的路径,就是绝对路径 例如这里的 D:\java\IntelliJ IDEA Community Edition
我有 REST APIManager 类 - 用于使用服务器 api 的单例。有返回用户Token实体的登录方法; 所有其他 API 方法都使用 token 来发出请求。登录后我应该在哪里存储该 to
当我在学习操作系统类(class)时,我不明白为什么下面代码的输出是这样的 代码: #include #include #include #include int main (int argc
我正在尝试在 C++ 中使用 fork() 和 wait() 系统调用。 我的代码非常简单。但是我收到以下错误: error C3861: 'fork': identifier not found 我
我需要播放不同格式的网络广播。我尝试使用 MPMoviePlayerController 播放广播,但它在 3-4 秒后停止。 var urlAddress = "http://streaming.r
多线程(进阶) 1. 常见的锁策略 1.1 乐观锁 悲观锁 乐观锁 : 总是假设最好的情况,每次去拿数据的时候都认为别人不会修改数据,但是在对数据提交更新的时候,再去判断这个数据在这个期间是否有别人对
如何让内存用起来? 内存使用:将程序放到内存中,PC指向开始地址 那就让首先程序进入内存 让程序从磁盘加载到内存中来,首先需要考虑要将程序代码安放在内存的什么位置 如果把入口地址直接放在0地址处,然后
操作系统 内存 HBase一定需要RAM! 64位 使用64位平台(和64位JVM)。 交换 注意交换,将swappiness设为0。 CPU 确保已将Hadoop设置为使用本机的硬件
我想编写一个脚本,将当前打开的 Windows 移动到某个位置。 理想情况下,我的程序应该是这样的: var window = FindWindow("Winamp"); window.setPos(
以下问题是我对操作系统的测试评论,但我不知道如何回答。我会第一次尝试解决他们的问题,但我也不知道如何开始。 Given the following information for an assembl
在操作系统方面我见过几次这个词。匿名内存 ,但我真的不知道,那是什么。 如果有人问我一些关于它的事情,我真的无法非常确定地说出那是什么。 我也搜索了它的解释,但不幸的是我还没有找到任何令人满意的东西。
在 Abraham Silberschatz 等人的“操作系统概念”第 9 版中,作者说: "Some operating systems support only static linking, i
我是一名优秀的程序员,十分优秀!