Android游戏开发–游戏循环
概括地说,最基本的游戏循环是while循环,该循环一直执行一些指令,直到我们发出信号指示完成为止,通常是通过将一个称为running的变量设置为false来完成
boolean running = true;
while (!running)
{updateGameState();displayGameState();
}
上面的代码盲目运行,无需担心时间和资源。 如果您使用的设备较快,则它将运行得非常快;如果设备较慢,则它将运行得较慢。
updateGameState()更新游戏中每个对象的状态,而displayGameState()将对象渲染为图像,并显示在屏幕上。
在这里我们应该考虑两件事:FPS和UPS。
FPS – 每秒 帧数 – 每秒调用displayGameState()的次数。
UPS – 每秒更新 – 每秒调用updateGameState()的次数。
理想情况下,每秒将update和render方法调用相同的次数(最好是每秒不少于20-25次)。 25 FPS通常在电话上就足够了,因此我们人类不会注意到动画缓慢。
例如,如果我们以25 FPS为目标,则意味着我们必须每40毫秒( 1000/25 = 40毫秒,1000毫秒= 1 秒)调用displayGameState()方法。 我们需要记住,在显示方法之前也要调用updateGameState() ,并且要使我们达到25 FPS,我们必须确保更新– 显示序列恰好在40毫秒内执行。 如果所需时间少于40毫秒,则我们的FPS较高。 如果花费的时间更多,那么我们的游戏运行速度会更慢。
让我们看一些示例,以更好地了解FPS。
下图正好显示了1 FPS。 它需要更新 - 渲染周期恰好执行一秒钟。 这意味着您将看到屏幕上的图像每秒更改一次。
每秒1帧 |
下图显示了10FPS。 更新 – 渲染周期需要100毫秒。 这意味着图像每隔十分之一秒改变一次。
10 FPS |
但是上述情况意味着更新 – 渲染周期每隔1秒就会执行一次。 这是一个假设,我们无法控制周期执行的实际时间,还是可以吗? 如果我们有200个敌人,而每个敌人都向我们开枪怎么办? 我们需要更新每个敌人的状态及其子弹的状态,并在一次更新中检查是否有碰撞。 当我们只有两个敌人时,情况就不同了。 时间显然会有所不同。 渲染方法也是如此。 显然,渲染200个发射机器人比仅渲染2个要花费更多的时间。
那是什么情况呢? 我们可以有一个更新-渲染周期,它可以在不到100毫秒(1/10秒)的时间内完成,恰好在100毫秒内完成,或者在不止于此的时间内完成。 在功能强大的硬件上,它会比功能较弱的硬件上更快。 让我们看一下图。
该周期在所需的时间范围之前完成,因此在运行下一个周期之前,我们有少量的空闲时间。
有时间的框架 |
下图显示了一个落后的周期。 这意味着完成更新渲染周期所花费的时间大于所需的时间。 如果花费12毫秒,则意味着我们落后了2毫秒(仍考虑10FPS)。 这可能会加剧,并且每个周期我们都会失去时间,游戏将缓慢运行。
过期帧 |
第一种情况是所需的。 这使我们有一些空闲时间在开始下一个周期之前做某事。 我们不需要做任何事情,所以我们只是告诉游戏循环在剩余时间段内进入睡眠状态,并在下一个周期到期时醒来。 如果我们不这样做,游戏将比预期的运行得更快。 通过引入睡眠时间,我们获得了恒定的帧速率 。
当循环落后时,第二种情况(我几乎跳过了理想情况,因为它几乎从未发生过),需要一种不同的方法。
为了在游戏中达到恒定的速度,我们需要在需要时更新对象的状态。 想象一下,机器人以恒定的速度接近您。 您知道它是否在一秒钟内通过了屏幕的一半,因此又需要一秒钟才能到达屏幕的另一侧。 为了准确地计算位置,我们需要知道自上一个位置以来的时间增量以及机器人的当前速度,或者我们以恒定的间隔更新机器人的位置(状态)。 我将选择第二个,因为在游戏更新中玩三角洲可能很棘手。 为了达到恒定的游戏速度,我们将不得不跳过显示帧。 游戏速度不是FPS!
检查下图。 在这种情况下, 更新 – 渲染周期花费的时间比预期的时间长,因此我们必须赶上。 为此,我们将跳过此帧的渲染并进行另一次更新,以免影响游戏速度。 我们将在下一帧进行正常循环,甚至需要一些时间来让CPU休息。
可变FPS的恒定游戏速度 |
上面的场景有很多变化。 您可以想象游戏更新需要一个以上的全帧。 在这种情况下,我们无法采取任何措施来保持游戏速度恒定,并且游戏运行速度会变慢。 我们可能必须跳过多个渲染以保持速度恒定,但是我们必须确保设置允许跳过的最大帧数,因为它可能需要花费很多更新才能赶上,并且如果我们跳过15帧,则意味着我们从游戏中损失了很多东西,而且将无法玩。
MainThread.java的run()如下所示:
// desired fps
private final static int MAX_FPS = 50;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 5;
// the frame period
private final static int FRAME_PERIOD = 1000 / MAX_FPS; @Override
public void run() {Canvas canvas;Log.d(TAG, "Starting game loop");long beginTime; // the time when the cycle begunlong timeDiff; // the time it took for the cycle to executeint sleepTime; // ms to sleep (<0 if we're behind)int framesSkipped; // number of frames being skipped sleepTime = 0;while (running) {canvas = null;// try locking the canvas for exclusive pixel editing// in the surfacetry {canvas = this.surfaceHolder.lockCanvas();synchronized (surfaceHolder) {beginTime = System.currentTimeMillis();framesSkipped = 0; // resetting the frames skipped// update game statethis.gamePanel.update();// render state to the screen// draws the canvas on the panelthis.gamePanel.render(canvas);// calculate how long did the cycle taketimeDiff = System.currentTimeMillis() - beginTime;// calculate sleep timesleepTime = (int)(FRAME_PERIOD - timeDiff);if (sleepTime > 0) {// if sleepTime > 0 we're OKtry {// send the thread to sleep for a short period// very useful for battery savingThread.sleep(sleepTime);} catch (InterruptedException e) {}}while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {// we need to catch up// update without renderingthis.gamePanel.update();// add frame period to check if in next framesleepTime += FRAME_PERIOD;framesSkipped++;}}} finally {// in case of an exception the surface is not left in// an inconsistent stateif (canvas != null) {surfaceHolder.unlockCanvasAndPost(canvas);}} // end finally}
}
在实现上述图表背后的逻辑时,请仔细检查以上代码。 您可以在可下载的项目中找到完整的代码。
我喜欢另一种方法。 它是恒定的游戏速度,每秒最大帧数。 它使用插值法绘制状态,并且在下一次游戏更新之前还有时间进行另一次渲染时,它会在快速硬件上发生。 这可以增强游戏的视觉效果,因为它可以使动画更流畅,但是由于我们使用移动设备,因此给CPU休息可以节省大量电池。
有在游戏圈的真棒文章在这里 。 我个人理解游戏循环阅读本文,因此我强烈推荐它。 我能找到的最好的。
请注意,我还修改了Speed.java类中的默认值。 速度以单位/秒为单位。 因为我们将所需的FPS设置为50,这意味着速度将在每次更新时增加50 * speed.value。 假设速度为40像素/秒,则需要将每个刻度的速度增量设置为2(40 /(1000/50)= 2)。 换句话说,您需要机器人在每次游戏更新时(如果您每秒更新50个游戏)前进2个像素,以覆盖每秒40个像素。
在此处下载代码并使用它。
检查它,您将获得具有恒定帧速率的恒定游戏速度。
参考: “ 反对谷物 ”博客的JCG合作伙伴Tamas Jano的《 游戏循环 》。
- Android游戏开发教程简介
- Android游戏开发–游戏创意
- Android游戏开发–创建项目
- Android游戏开发–基本游戏架构
- Android游戏开发–基本游戏循环
- Android游戏开发–使用Android显示图像
- Android游戏开发–在屏幕上移动图像
- Android游戏开发–测量FPS
- Android游戏开发–雪碧动画
- Android游戏开发–粒子爆炸
- Android游戏开发–设计游戏实体–策略模式
- Android游戏开发–使用位图字体
- Android游戏开发–从Canvas切换到OpenGL ES
- Android游戏开发–使用OpenGL ES显示图形元素(原语)
- Android游戏开发– OpenGL纹理映射
- Android游戏开发–设计游戏实体–状态模式
- Android游戏文章系列
翻译自: https://www.javacodegeeks.com/2011/07/android-game-development-game-loop.html
Android游戏开发–游戏循环相关推荐
- android游戏开发_Android游戏开发–游戏循环
android游戏开发 游戏循环是每个游戏的心跳. 到目前为止,我们仅使用了非常简单的一种(您可以在此处找到),无法控制我们更新游戏状态的速度或速度以及要渲染的帧. 概括地说,最基本的游戏循环是whi ...
- android_Android游戏开发–游戏循环
android 游戏循环是每个游戏的心跳. 到目前为止,我们使用的是非常简单的游戏(您可以在此处找到),无法控制我们更新游戏状态的速度或速度以及要渲染的帧. 概括地说,最基本的游戏循环是while循环 ...
- H5数独游戏开发——游戏中的事件处理
假设你正在玩一款角色扮演游戏(RPG),主角走进了一家店铺,你用鼠标点击店铺里管家,这时屏幕显示一个待售物品菜单,然后你可以选购你需要的物品.那么,你知道从你点击鼠标的那一刻起,游戏是怎样响应的吗?让 ...
- H5数独游戏开发——游戏通关及重玩
如何判断游戏是否通关?通关后如何重新开始游戏,让用户重玩?今天给大家详细介绍如何实现以上功能.先看一下数独游戏通关后的提示界面,截图如下: 首先,我们需要判断游戏是否通关,那么如何判断呢?有两个条件: ...
- 1.15 从0开始学习Unity游戏开发--游戏UI
上一章中,我们剩下最后一个任务,需要支持鼠标控制准心来进行设计,那么准心本质上就是一个始终呈现在屏幕上的一个图片,你当然可以用一个3D物体来制作,之前讲解渲染概念的时候也提到过,我们的屏幕就是相机的近 ...
- Xcode与C++之游戏开发: 游戏对象
上一篇:Xcode与C++之游戏开发:Pong游戏 游戏对象 在前面的 Pong 游戏中,没有用不同的类去代表墙,球拍和球,仅仅使用了一个 Game 类.像 Pong 这种简单游戏当然没问题,但它不是 ...
- 游戏运营全过程剖析,游戏开发,游戏运营,游戏推广问题分析
产品策划:一个好的idea至关重要,结合当时的社会环境,游戏开发水平,玩家喜好,市场需求等考虑.精美的画面,流畅的游戏节奏,情节,完善的游戏系统能让你的游戏立于不败之地. 产品开发:游戏主线框架定好后 ...
- Unity游戏开发-游戏热更新以及登录流程
本篇主要分享基于热更新的游戏初始化方案. 整体初始化的流程大致为:检查是否需要解压资需要则解压,之后再检查是否存在需要热更新的资源文件需要则更新,更新完成后则初始化结束可进入登录界面. 关于登录这块的 ...
- 游戏开发——游戏AI的简述
一.游戏AI 游戏AI(Game AI),是指在游戏中,由已经写定好的程序控制的"类人化玩家",俗称电脑玩家.一般的游戏AI能够拥有对真实玩家的一系列操作感知的能力并对此作出交互行 ...
最新文章
- cmake error C2220: 以下警告被视为错误
- PHP实现多服务器session共享之NFS共享
- 【转】C#开发笔记之05-迭代器中的状态机(State Machine)到底是什么?
- 如何在视图中启用thymeleaf
- 全排列及相关扩展算法(三)——利用中介数求排列在字典序排位算法
- asp.net中实现群发邮件功能
- 计算机网络在金融领域的应用,计算机网络毕业论文计算机网络技术在金融领域的应用.pdf...
- vue项目打包,生成dist文件夹,如何修改文件夹的名字
- Visual Studio开发环境下的中文GBK内码获取
- 关于平面设计海报怎么做?——黎乙丙
- 寒假刷刷算法题(13)
- [笔记]--tensorrt及神经网络常用的.wts权重格式解析
- 微信小程序使用 checkbox 如何修改样式?
- 如何给计算机c盘加内存,增加C盘内存的方法
- Apsara Clouder云计算专项技能认证考试题目和答案
- 豆瓣电影排行榜下载,main主文件代码(未完善版)
- Synchronized详细介绍之锁升级过程
- Python requests post上传图片
- 多通道(Multichannel)单通道(singlechannel)图像
- 获取本地json文件