当前位置: 首页 > article >正文

游戏设计模式阅读 - 游戏循环

游戏与普通程序最大的不同点在于:

        游戏不像其他大多数软件,游戏即使在没有玩家输入时也继续运行。 如果你站在那里看着屏幕,游戏也不会冻结。动画会持续播放。视觉效果继续闪烁。 如果运气不好的话,怪物会继续暴揍你的角色。

那么维持这一切的必要条件是什么,在代码层面又是如何维持你的游戏世界不陷入时停的呢?

这个概念就是:循环

循环的意图

        将游戏的进行和玩家的输入解耦,和处理器速度解耦。

事件循环

        游戏即使在没有玩家输入时也继续运行。

        这是真实游戏循环的第一个关键部分:它处理用户输入,但是不等待它

while (true) {processInput();update();render();
}// processInput()处理上次调用到现在的任何输入。
// update()让游戏模拟一步。 运行AI和物理。
// render()绘制游戏,

什么是帧率

        我们用实际时间来测算游戏循环运行的速度,就得到了游戏的“帧率”(FPS)。如果游戏循环的更快,FPS就更高,游戏运行得更流畅、更快。

两个因素决定了帧率:

1、每帧要做多少工作

        复杂的物理,众多游戏对象,图形细节都让CPU和GPU繁忙,这决定了需要多久能完成一帧。

2、底层平台的速度

         更快的芯片可以在同样的时间里执行更多的代码。 多核,GPU组,独立声卡,以及系统的调度都影响了在一定时间内能够做多少东西。

每秒的帧数

        早期的游戏被仔细地编码,一帧只做一定的工作,开发者可以让游戏以想要的速率运行。

        但是如果你想要在快些或者慢些的机器上运行同一游戏,游戏本身就会加速或减速。

一个游戏循环在游戏运行过程中被不断执行。 每一次循环,它无阻塞地处理玩家输入更新游戏状态渲染游戏。 追踪时间的消耗并控制游戏的速度

优化上面的简易循环代码

        上面代码的问题是无法控制游戏运行得有多快

        假设游戏需要以60FPS运行,那么每帧约等于16ms。只要用少于这个时长处理游戏内的所有内容,就可以以稳定的帧率运行。所需要做的就是处理这一帧,然后等待,直到处理下一帧。

while (true) {double start = getCurrentTime();processInput();update();render();sleep(start + MS_PER_FRAME - getCurrentTime());
}

但如果每次循环消耗的时间超过16ms,那它永远也跟不上

需要解决的问题:

1、每次更新将游戏时间推动一个固定量。

2、消耗一定量的真实时间来处理它。

因此还可以基于上帧到现在有多少真实时间流逝来选择前进的时间。这一帧花费的时间越长,游戏的间隔越大。

double lastTime = getCurrentTime();
while (true){double current = getCurrentTime();double elapsed = current - lastTime;processInput();update(elapsed);render();lastTime = current;
}

每一帧,计算上次游戏更新到现在有多少真实时间过去了。在更新游戏状态时将其传入,然后游戏引擎内推进一定的时间量。

假设有一颗子弹跨过屏幕。 使用固定的时间间隔,在每一帧中根据它的速度移动它。 使用变化的时间间隔,根据过去的时间拉伸速度。 随着时间间隔增加,子弹在每帧间移动得更远。 无论是二十个快的小间隔还是四个慢的大间隔,子弹在真实时间里移动同样多的距离。

但这个方案也不合理:游戏不再是确定的了,也不再稳定。

游戏时间追逐真实时间

        计算上一次游戏循环过去了消耗了多少真实时间。 为游戏的“当前时间”模拟推进相同长度的时间,以追上玩家的时间。

double previous = getCurrentTime();
double lag = 0.0;
while (true) {double current = getCurrentTime();double elapsed = current - previous;previous = current;lag += elapsed;processInput();while (lag >= MS_PER_UPDATE){update();lag -= MS_PER_UPDATE;}render();
}
// 在每帧的开始,根据过去了多少真实的时间来更新lag。 这个变量表明了游戏世界时钟比真实世界落后了多少。
// 使用一个固定时间步长的内部循环进行追赶。 一旦追上真实时间,就执行渲染然后开始新一轮循环
// MS_PER_UPDATE只是更新游戏的间隔。 这个间隔越短,就需要越多的处理次数来追上真实时间。// 可以通过限制内层循环的最大次数来保证游戏不会完全卡死

由于render()次数比update()次数更少,就有可能出现render()发生在两次update()之间。

因此,需要在lag不为零lagMS_PER_UPDATE更小时,跳出循环进行渲染。 lag的剩余量就是到下一帧的时间。

render(lag / MS_PER_UPDATE);

决策

使用平台的事件循环:

1、简单
        不必担心编写和优化自己的游戏核心循环。

2、平台友好
        你不必明确地给平台一段时间让它处理它自己的事件,不必缓存事件,不必管理任何平台输入模型和你的不匹配之处。

3、失去了对时间的控制。

使用游戏引擎的循环:

1、不必自己编写
        编写游戏循环非常需要技巧。 由于是每帧都要执行的核心代码,小小的漏洞或者性能问题就对游戏有巨大的影响。 稳固的游戏循环是使用现有引擎的原因之一。

2、无法自己编写
        代价就是如果引擎无法满足真正的需求,开发者也没法获得控制权。

自己写:    

1、完全可控
        可以做任何想做的事情。可以为游戏的需求订制开发。

2、需要与平台交互
        应用框架和操作系统通常需要时间片去处理自己的事件和其他工作。 如果拥有应用的核心循环,平台就没有这些时间片了。 开发者得显式定期检查,保证框架没有挂起或者混乱。

相关文章:

游戏设计模式阅读 - 游戏循环

游戏与普通程序最大的不同点在于: 游戏不像其他大多数软件,游戏即使在没有玩家输入时也继续运行。 如果你站在那里看着屏幕,游戏也不会冻结。动画会持续播放。视觉效果继续闪烁。 如果运气不好的话,怪物会继续暴揍你的角色。 那么…...

(五)趣学设计模式 之 建造者模式!

目录 一、 啥是建造者模式?二、 为什么要用建造者模式?三、 建造者模式怎么实现?四、 建造者模式的应用场景五、 建造者模式的优点和缺点六、 总结 🌟我的其他文章也讲解的比较有趣😁,如果喜欢博主的讲解方…...

github 怎么创建一个私有repository 并从另外一台电脑拉取下来更新

1.github上新建一个repository 设置为private tips删除在这 点setting 然后往下拖动 会有个这里是用来删项目的 2.另外 一台电脑拉取这个repository的时候 需要配置 一个ssh key 这个key的内容生成参考本地电脑的生成 然后在这配置 2.1 生成 SSH 密钥(如果还没有…...

Spring Boot嵌入式服务器深度解析:从配置到调优的全方位指南

文章目录 引言一、嵌入式服务器核心原理1.1 架构设计特点1.2 主流服务器对比 二、嵌入式服务器配置实战2.1 基础配置模板2.2 HTTPS安全配置 三、高级调优策略3.1 线程池优化(Tomcat示例)3.2 响应压缩配置3.3 访问日志配置 四、服务器切换实战4.1 切换至U…...

DeepSeek-R1本地化部署的硬件要求

DeepSeek-R1本地化部署的硬件要求全解析 引言 DeepSeek-R1作为一款高效的AI推理模型,凭借其卓越的推理性能和灵活的训练机制,成为了春节期间的热议话题。 然而,要在本地成功部署DeepSeek-R1,尤其是其满载的 671B 参数版本&#…...

AGI觉醒假说的科学反驳:从数学根基到现实约束的深度解析

文章目录 引言:AGI觉醒论的核心迷思一、信息论视角:意识产生的熵约束1.1 香农熵的物理极限1.2 量子退相干的时间屏障二、数学根基:形式系统的自指困境2.1 哥德尔不完备定理的现代诠释三、概念解构:AGI觉醒假说的认知陷阱3.1 术语混淆的迷雾3.2 拟人化谬误的认知根源四、意识…...

CSS—盒模型(3分钟结合示例精通盒模型)

个人博客:haichenyi.com。感谢关注 1. 目录 1–目录2–概念3–内容4–内边距5–边框6–外边距7–类型 概念 在HTML中,每一个元素都可以看作一个矩形的盒子。如图 如上图所示,一个一个的矩形都可以堪称一个元素。矩形有大有小,边有…...

蓝桥杯 3.搜索

蓝桥杯 3.搜索 文章目录 蓝桥杯 3.搜索DFS回溯DFS剪枝记忆化搜索编程66-75 DFS回溯 回溯法简介 使用**DFS(深度优先搜索)**实现, DFS是一种遍历或搜索图, 树或者图像等数据结构的算法, 当然这个图, 树未必要存储下来(隐式处理就是回溯法)搜索树一般是排列型搜索树 (总节点个数…...

JQD武学思想

无意识,无我,空,无形, 刚柔相济,时机, 战胜对手,克服内心。不预测结果,自发反击。 简单直接的攻击,去除一切冗余的东西。 李小龙其实反复在解释这些概念,常…...

供应链管理-谈判:分配式谈判、整合式谈判、原则式谈判

一、分配式谈判 序号要点解释1特点双方在一定资源或利益范围内进行分配,一方所得即另一方所失,因此也被称为“零和谈判”。2适用场景资源有限、关系不是关键因素,以及需要快速决策的情况。例如,在竞争对手之间,如拍卖…...

C语言递归——青蛙跳台阶问题和汉诺塔问题

一、青蛙跳台阶问题 •题目描述: 一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上n级台阶总共有多少种跳法。 •问题分析: 青蛙跳台阶问题可以分成n个子问题。假设青蛙要跳上n级台阶,那么它的最后一步有两种选择&…...

relief=tk.RAISED详细介绍 relief是指定控件的边框样式

relieftk.RAISED 是在使用 Python 的 Tkinter 库创建图形用户界面(GUI)时,用于设置控件外观样式的一个参数设置,下面为你详细解释: 整体功能概述 在 Tkinter 里,relief 参数用于指定控件的边框样式&#x…...

基于ffmpeg+openGL ES实现的视频编辑工具-添加转场(九)

在视频编辑的广阔领域中,转场效果无疑是提升视频流畅性与观赏性的关键要素。巧妙运用转场,能够让不同视频片段之间的衔接更为自然,同时赋予视频独特的创意魅力。本文将深入探讨如何借助 ffmpeg 和 openGL ES 技术,在视频编辑工具中实现丰富多样的转场效果。 一、转场技术原…...

2025.2.21 日校内模拟赛总结(AC自动机, 期望,倍增)

文章目录 时间安排题解 时间安排 将近两个半小时才过 T 1 T1 T1,后面花一个半小时过了 T 2 T2 T2,最后半个小时写不出 T 3 T3 T3 暴力没有获得分数。 反思: T 1 T1 T1 这种题要敢于去猜结论打表,由于没有直接猜结论做了很长时…...

STM32的“Unique device ID“能否修改?

STM32F1系列的"Unique device ID"寄存器的地址为0x1FFFF7E8。 这个寄存器是只读的。 "Unique device ID"寄存器位于“System memory”中。“System memory”地址范围为“0x1FFF F000- 0x1FFF F7FF”。 所有STM32 MCU上都存在系统引导加载程序。顾名思义&a…...

[内网基础] 内网基础知识 —— Windows 工作组

关注这个专栏的其他相关笔记:[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01:Windows 工作组介绍 在一个大型单位里,可能有成百上千台计算机互相连接组成局域网,如果不对这些计算机进行分组,网络的混乱程度是可想而知…...

【新手初学】SQL注入之二次注入、中转注入、伪静态注入

二次注入 一、概念 二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。 二、原理 防御者可能在用户输入恶意数据时对其中的特殊字符进行了转义处理,但在恶意数据插入到数据库时被处…...

Deepseek存算分离安全部署手册

Deepseek大火后,很多文章教大家部署Dfiy和ollamadeepseek,但是大部分都忽略了数据安全问题,本文重点介绍Deepseek存算分裂安全架设,GPU云主机只负责计算、CPU本地主机负责数据存储,确保数据不上云,保证私有…...

单页图床HTML源码+本地API接口图床系统修复版源码

源码介绍 图床系统是一种用于存储和管理图片文件的在线服务。它允许用户上传图片文件,并生成相应的图片链接,从而方便用户在网页、社交媒体或其他平台上分享图片。 PS:源码压缩包分为两个版本,一个是调用360第三方api接口,另外一…...

XML DOM4J 三、XPath

1 什么是XPath XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。起初 XPath 的提出的初衷是将其作为一个通用的、介于XPointe…...

IDEA使用Maven方式构建SpringBoot项目

1、环境准备 确保你已经安装了以下工具: Java JDK(推荐 JDK 8 或更高版本) IntelliJ IDEA(推荐使用最新版本) 2、创建 Spring Boot 项目 (1) 打开 IntelliJ IDEA。 (2&#xff09…...

【SPIE出版,见刊快速,EI检索稳定,浙江水利水电学院主办】2025年物理学与量子计算国际学术会议(ICPQC 2025)

2025年物理学与量子计算国际学术会议(ICPQC 2025)将于2025年4月18-20日在中国杭州举行。本次会议旨在汇聚全球的研究人员、学者和业界专家,共同探讨物理学与量子计算领域的最新进展与前沿挑战。随着量子技术的快速发展,其在信息处…...

EMC Isilon存储节点挂掉--Journal故障问题处理

EMC isilon 的集群存储系统经常会遇到有些节点关机后无法启动,使用串口或者接上显示器去看,会看到node节点启动到下面的位置就不正常启动了。典型的console输出如下: 老的版本,OneFS 7.0版本以前的: Checking Isilon…...

掌握 ElasticSearch 组合查询:Bool Query 详解与实践

掌握 ElasticSearch 组合查询:Bool Query 详解与实践 一、引言 (Introduction)二、Bool 查询基础2.1 什么是 Bool 查询?2.2 Bool 查询的四种子句2.3 语法结构 三、Bool 查询的四种子句详解与示例3.1 must 子句3.2 filter 子句3.3 should 子句3.4 must_no…...

Spring Boot 3 集成 RabbitMQ 实践指南

Spring Boot 3 集成 RabbitMQ 实践指南 1. RabbitMQ 核心原理 1.1 什么是RabbitMQ RabbitMQ是一个开源的消息代理和队列服务器,使用Erlang语言开发,基于AMQP(Advanced Message Queuing Protocol)协议实现。它支持多种消息传递模…...

查看cmd下python的安装路径 + Windows 命令行添加环境变量和不重启刷新环境变量

1、查看cmd下python的安装路径 cmd ----》输入“python” 命令 ---》输入 import sys; print(sys.executable) 即可看到当前系统python的安装路径: 注:系统所使用的python实际上就是在系统环境变量下配置的python目录。 2、刷新path命令:在c…...

C/C++跳动的爱心

系列文章 序号直达链接1C/C李峋同款跳动的爱心2C/C跳动的爱心3C/C经典爱心4C/C满屏飘字5C/C大雪纷飞6C/C炫酷烟花7C/C黑客帝国同款字母雨8C/C樱花树9C/C奥特曼10C/C精美圣诞树11C/C俄罗斯方块小游戏12C/C贪吃蛇小游戏13C/C孤单又灿烂的神14C/C闪烁的爱心15C/C哆啦A梦16C/C简单…...

Linux 命令大全完整版(10)

4. 压缩与解压缩命令 gzip(gnu zip) 功能说明&#xff1a;压缩文件。语  法&#xff1a;gzip [-acdfhlLnNqrtvV][-S <压缩字尾字符串>][-<压缩效率>][–best/fast][文件…] 或 gzip [-acdfhlLnNqrtvV][-S <压缩字尾字符串>][-<压缩效率>][–best/f…...

Cannot deserialize instance of java.lang.String out of START_ARRAY token

这个错误 Cannot deserialize instance of java.lang.String out of START_ARRAY token 表示 Jackson 正在尝试将一个 JSON 数组反序列化成一个 String 类型的字段&#xff0c;但是 JSON 中传递的是一个数组而不是单一的字符串。 具体来说&#xff0c;这段堆栈信息&#xff1a…...

一、初始爬虫

1.爬虫的相关概念 1.1 什么是爬虫 网络爬虫&#xff08;又被称为网页蜘蛛&#xff0c;网络机器人&#xff09;就是模拟浏览器发送网络请求&#xff0c;接收请求响应&#xff0c;一种按照一定的规则&#xff0c;自动地爬取互联网信息的程序。 原则上&#xff0c;只要是浏览器…...