游戏循环是每个游戏的心跳。 到目前为止,我们仅使用了非常简单的一种(您可以在此处找到),无法控制我们更新游戏状态的速度或速度以及要渲染的帧。

概括地说,最基本的游戏循环是while循环,该循环一直执行一些指令,直到我们发出信号指示完成为止,通常是通过将一个称为running的变量设置为false来完成

boolean running = true;
while (!running)
{updateGameState();displayGameState();
}

上面的代码盲目运行,无需担心时间和资源。 如果您使用的设备较快,则它将运行得非常快;如果设备较慢,则它将运行得较慢。

updateGameState()更新游戏中每个对象的状态,而displayGameState()将对象渲染为图像,并显示在屏幕上。

在这里我们应该考虑两件事:FPS和UPS。

FPS每秒 帧数每秒调用displayGameState()的次数。
UPS每秒更新每秒调用updateGameState()的次数。

理想情况下,每秒将updaterender方法调用相同的次数(最好是每秒不少于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.javarun()如下所示:

// 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游戏 ArkDroid (以下屏幕截图) 。 您的反馈将大有帮助!
相关文章:
  • 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游戏开发–游戏循环相关推荐

  1. android游戏开发_Android游戏开发–游戏循环

    android游戏开发 游戏循环是每个游戏的心跳. 到目前为止,我们仅使用了非常简单的一种(您可以在此处找到),无法控制我们更新游戏状态的速度或速度以及要渲染的帧. 概括地说,最基本的游戏循环是whi ...

  2. android_Android游戏开发–游戏循环

    android 游戏循环是每个游戏的心跳. 到目前为止,我们使用的是非常简单的游戏(您可以在此处找到),无法控制我们更新游戏状态的速度或速度以及要渲染的帧. 概括地说,最基本的游戏循环是while循环 ...

  3. H5数独游戏开发——游戏中的事件处理

    假设你正在玩一款角色扮演游戏(RPG),主角走进了一家店铺,你用鼠标点击店铺里管家,这时屏幕显示一个待售物品菜单,然后你可以选购你需要的物品.那么,你知道从你点击鼠标的那一刻起,游戏是怎样响应的吗?让 ...

  4. H5数独游戏开发——游戏通关及重玩

    如何判断游戏是否通关?通关后如何重新开始游戏,让用户重玩?今天给大家详细介绍如何实现以上功能.先看一下数独游戏通关后的提示界面,截图如下: 首先,我们需要判断游戏是否通关,那么如何判断呢?有两个条件: ...

  5. 1.15 从0开始学习Unity游戏开发--游戏UI

    上一章中,我们剩下最后一个任务,需要支持鼠标控制准心来进行设计,那么准心本质上就是一个始终呈现在屏幕上的一个图片,你当然可以用一个3D物体来制作,之前讲解渲染概念的时候也提到过,我们的屏幕就是相机的近 ...

  6. Xcode与C++之游戏开发: 游戏对象

    上一篇:Xcode与C++之游戏开发:Pong游戏 游戏对象 在前面的 Pong 游戏中,没有用不同的类去代表墙,球拍和球,仅仅使用了一个 Game 类.像 Pong 这种简单游戏当然没问题,但它不是 ...

  7. 游戏运营全过程剖析,游戏开发,游戏运营,游戏推广问题分析

    产品策划:一个好的idea至关重要,结合当时的社会环境,游戏开发水平,玩家喜好,市场需求等考虑.精美的画面,流畅的游戏节奏,情节,完善的游戏系统能让你的游戏立于不败之地. 产品开发:游戏主线框架定好后 ...

  8. Unity游戏开发-游戏热更新以及登录流程

    本篇主要分享基于热更新的游戏初始化方案. 整体初始化的流程大致为:检查是否需要解压资需要则解压,之后再检查是否存在需要热更新的资源文件需要则更新,更新完成后则初始化结束可进入登录界面. 关于登录这块的 ...

  9. 游戏开发——游戏AI的简述

    一.游戏AI 游戏AI(Game AI),是指在游戏中,由已经写定好的程序控制的"类人化玩家",俗称电脑玩家.一般的游戏AI能够拥有对真实玩家的一系列操作感知的能力并对此作出交互行 ...

最新文章

  1. cmake error C2220: 以下警告被视为错误
  2. PHP实现多服务器session共享之NFS共享
  3. 【转】C#开发笔记之05-迭代器中的状态机(State Machine)到底是什么?
  4. 如何在视图中启用thymeleaf
  5. 全排列及相关扩展算法(三)——利用中介数求排列在字典序排位算法
  6. asp.net中实现群发邮件功能
  7. 计算机网络在金融领域的应用,计算机网络毕业论文计算机网络技术在金融领域的应用.pdf...
  8. vue项目打包,生成dist文件夹,如何修改文件夹的名字
  9. Visual Studio开发环境下的中文GBK内码获取
  10. 关于平面设计海报怎么做?——黎乙丙
  11. 寒假刷刷算法题(13)
  12. [笔记]--tensorrt及神经网络常用的.wts权重格式解析
  13. 微信小程序使用 checkbox 如何修改样式?
  14. 如何给计算机c盘加内存,增加C盘内存的方法
  15. Apsara Clouder云计算专项技能认证考试题目和答案
  16. 豆瓣电影排行榜下载,main主文件代码(未完善版)
  17. Synchronized详细介绍之锁升级过程
  18. Python requests post上传图片
  19. 多通道(Multichannel)单通道(singlechannel)图像
  20. 获取本地json文件

热门文章

  1. 强大的wrapper
  2. xamarin其是一个鸡肋么?
  3. Android应用开发 MP3音乐播放器滚动歌词实现
  4. mysql 字段移动平均值_MYSQL简单移动平均值计算
  5. Java实现PC微信扫码支付
  6. LeetCode292 Nim 游戏
  7. .NET 程序员-开源项目【藏】
  8. Linux搭建git仓库
  9. iview安装使用以及遇到的问题汇总(持续更新)
  10. 2012-9-5 白色风车、心雨、退后 忆往事