我发现大多数游戏开发需要一个主游戏循环,但我不知道为什么它是必要的.我们不能实现事件监听器并响应每个用户操作吗?然后可以在事件发生时播放动画(等).
主游戏循环的目的是什么?
在每个游戏循环迭代中调用main.lua脚本 - 是好还是坏设计?它如何影响性能(相对)?
从维护游戏状态一个.C++主机程序或b.来自Lua脚本或c.来自两者并同步它们?
(关于该主题的上一个问题:Lua和C++:职责分离)
(我投票给每个答案.最好的答案将被接受.)
有一种简单的方法可以在JavaScript中制作游戏循环吗?就像是...
onTimerTick() {
// update game state
}
Run Code Online (Sandbox Code Playgroud) 我正在制作一款安卓游戏,目前我还没有达到我想要的性能.我在自己的线程中有一个游戏循环,用于更新对象的位置.渲染线程将遍历这些对象并绘制它们.目前的行为似乎是波涛汹涌/不均匀的运动.我无法解释的是,在我将更新逻辑放入自己的线程之前,我在onDrawFrame方法中,就在gl调用之前.在这种情况下,动画非常流畅,当我尝试通过Thread.sleep来限制我的更新循环时,它只会变得不连贯/不均匀.即使我允许更新线程进行狂暴(无睡眠),动画也是平滑的,只有当涉及Thread.sleep时它才会影响动画的质量.
我已经创建了一个骨架项目来查看是否可以重新创建该问题,下面是渲染器中的更新循环和onDrawFrame方法: Update Loop
@Override
public void run()
{
while(gameOn)
{
long currentRun = SystemClock.uptimeMillis();
if(lastRun == 0)
{
lastRun = currentRun - 16;
}
long delta = currentRun - lastRun;
lastRun = currentRun;
posY += moveY*delta/20.0;
GlobalObjects.ypos = posY;
long rightNow = SystemClock.uptimeMillis();
if(rightNow - currentRun < 16)
{
try {
Thread.sleep(16 - (rightNow - currentRun));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的onDrawFrame方法:
@Override
public void onDrawFrame(GL10 gl) {
gl.glClearColor(1f, 1f, 0, 0); …
Run Code Online (Sandbox Code Playgroud) 我刚开始在android中进行游戏开发,而我正在开发一款超级简单的游戏.
这场比赛基本上就像飞扬的小鸟.
我设法让一切工作,但我得到了很多口吃和滞后.
我用来测试的手机是LG G2,所以它应该并且确实运行的游戏比这更重,更复杂.
基本上有4个"障碍"是全屏宽度彼此分开.
当游戏开始时,障碍物开始以恒定速度移动(朝向角色).玩家角色的x值在整个游戏中是一致的,而其y值会发生变化.
滞后主要发生在角色穿过障碍物时(有时也会在障碍物之后).会发生的是,游戏状态的每个图形都存在不均匀的延迟,导致运动中出现断断续续的情况.
我的想法是有一行或多行代码导致某种延迟发生(因此跳过帧).我也认为这些线路应该是围绕update()
和draw()
方法PlayerCharacter
,Obstacle
以及MainGameBoard
.
问题是,我还是专门针对Android开发和Android 游戏开发的新手,所以我不知道是什么原因导致这种延迟.
我试着在网上寻找答案......不幸的是,我发现所有这些都指向了GC.但是,我不相信这种情况(如果我错了,请纠正我)这些答案对我不适用.我也阅读了android开发者的Performance Tips
页面,但找不到任何帮助.
所以,请帮助我找到解决这些令人讨厌的滞后的答案!
MainThread.java:
public class MainThread extends Thread {
public static final String TAG = MainThread.class.getSimpleName();
private final static int MAX_FPS = 60; // desired fps
private final static int MAX_FRAME_SKIPS = 5; // maximum number of frames to be skipped
private final static int FRAME_PERIOD = 1000 / MAX_FPS; // …
Run Code Online (Sandbox Code Playgroud) 对于独立游戏,基本的游戏循环是(来源:维基百科)
while( user doesn't exit )
check for user input
run AI
move enemies
resolve collisions
draw graphics
play sounds
end while
Run Code Online (Sandbox Code Playgroud)
但是,如果我开发类似客户端服务器的游戏,如Quake,Ragnarock,Trackmania等,
客户端和游戏服务器部分的循环/算法是什么?
我想在Haskell中编写一个游戏,循环的每次迭代都会计算出世界的状态.我以为我应该创建一个函数:
gameLoop :: World -> World
-- ...
Run Code Online (Sandbox Code Playgroud)
并main :: IO ()
称之为:
main = do
gameLoop -- ...
Run Code Online (Sandbox Code Playgroud)
但问题是我缺少一些基本的理解如何包装gameLoop
函数,以便它返回main
的参数值.
如何在Haskell中创建游戏循环?
一段时间以来,我经历了一段间歇性的"口吃",即在我的Android游戏中运行的精灵.这是一款非常简单的2D OpenGL ES 2.0游戏.(这是一个持续存在的问题,我多次重访过).
在我的游戏循环中,我有2个'定时器' - 一个用于记录前一秒的帧数,另一个用于计算从当前onDrawFrame迭代结束到下一个开始的时间(以毫秒为单位).
这就是我发现的:
当不渲染任何东西时,我得到60fps(大部分),并且每次调用onDrawFrame时,它报告自己需要更长的16.667ms.现在,如果我渲染一些东西(无论是1个四边形还是100个四边形,结果是相同的),我得到60fps(大部分)但是现在,只有大约20%的onDrawFrame调用报告自己需要更长的时间比上次通话时的16.667毫秒.
我真的不明白为什么会发生这种情况,首先,为什么当onDrawFrame没有做任何事情时,它被称为"慢慢" - 更重要的是,为什么任何GL调用(一个简单的四边形),仍然需要时间onDrawFrame调用超过16.667ms(尽管频率低得多).
我应该说当onDrawFrame报告从最后一次迭代开始超过16.667ms时,它几乎总是伴随着FPS下降(到58或59),但并非所有时间,有时候,FPS保持不变.相反,有时当FPS下降时,onDrawFrame在最后一次迭代完成的16.667ms内被调用.
所以......
我正在尝试修复我的游戏循环并根除这些"口吃" - 其他一些注意事项:
我显然是在误解某些东西,所以我们将不胜感激.
OnDrawFrame
@Override
public void onDrawFrame(GL10 gl) {
startTime = System.nanoTime();
fps++;
totalTime = System.nanoTime() - timeSinceLastCalled;
if (totalTime > 16667000) {
Log.v("Logging","Time between onDrawFrame calls: " + (totalTime /(double)1000000));
}
//Grab time
newTime = System.currentTimeMillis() * 0.001;
frameTime = newTime - currentTime; //Time the last frame took
if (frameTime > 0.25)
frameTime = 0.25;
currentTime = …
Run Code Online (Sandbox Code Playgroud) 从我所看到的,如果我想做一个非opengl游戏循环我可以做的是有一个游戏线程,在循环期间将更新游戏状态(或游戏物理),并通过锁定a Canvas
来更新图形(正常)SurfaceView
,通过Canvas.drawXXX(...)方法进行绘图,然后将其解锁,此时图形将更新为循环.
使用GLSurfaceView
和时,我真的不知道如何做到这一点Renderer
.根据我的理解,我不能再像我在常规表面那样按照手工制作的gameThread绘制Canvas
,因为现在有一个渲染线程会调用Renderer.onDrawFrame()
(在我实现的渲染器类中,我传递给GLSurfaceView).
那么我的问题是,用GLSurfaceView和Renderer制作游戏循环的好方法是什么?我是否仍然应该制作单独的游戏线程,但只处理其中的游戏状态(物理)更新,然后在我的Renderer.onDrawFrame()实现中使用该游戏状态来实际绘制基于当前状态的图形?我应该只使用Rendere的线程来进行状态更新吗?
在试图在SFML中找到一个可靠的游戏循环的过程中,我遇到了这个我似乎无法弄清楚的问题.我能够删除所有SFML代码,仍然clock()
在time.h中看到问题.然后我走得更远,仍然看到问题使用std::chrono::steady_clock
.
问题:我总是看到跳过更新之间可以完成的工作量.每次更新应该花费1/60秒,剩下的时间用于Draw()
尽可能多地完成绘图.有时抽奖量下降到0或1,没有明显的原因.这会以明显的口吃形式冒泡到实际应用中.除了"跳过"之外,完成的抽签次数非常一致.
这是一个图像(注意更新时间的跳转和绘制中的下降): 问题的控制台输出
一些代码:
#include <iostream>
#include <time.h>
#include <chrono>
using namespace std;
using namespace std::chrono;
void Draw()
{
//for (int i = 0; i < 1000000; i++);
}
int main()
{
steady_clock::time_point update_time;
steady_clock::time_point update_next;
int update_rate = 16666666; // 60 times a second (nanosecs)
int updates;
int max_updates = 5;
int draws = 0;
update_next = steady_clock::now();
while (true)
{
updates = 0;
update_time = steady_clock::now();
while (duration_cast<nanoseconds>(update_time - update_next) > …
Run Code Online (Sandbox Code Playgroud) game-loop ×10
android ×4
c++ ×2
opengl-es ×2
algorithm ×1
clock ×1
game-engine ×1
haskell ×1
java ×1
javascript ×1
lua ×1
performance ×1
surfaceview ×1
thread-sleep ×1