2012-03-28 47 views
7

我想在android中使用opengl编写一些简单的游戏,但立即遇到了主游戏循环的麻烦。当我在这里阅读:http://developer.android.com/resources/tutorials/opengl/opengl-es10.html每次需要重绘表面时,应用程序都会调用public void onDrawFrame(GL10 gl)。或者像那样行事。我的问题是 - 如何创建一个独立于绘制调用的更新循环。我的意思是 - 它不能像那样工作,只有当设备(应用程序?)想重新绘制表面(或者我错了?)时,我才能更新游戏逻辑。如何用android opengl适当地创建更新/绘制循环?

经过一些谷歌搜索后,我得出了一个结论,我必须为更新循环创建另一个线程。但后来我遇到了另一个问题 - 一个线程负责绘制图形,另一个线程负责更新游戏逻辑,我不知道如何让它们合作。首先,他们是两个独立的类(至少在我的实现中),所以他们不能使用相同的游戏变量和对象(精灵,定时器,不同的变量,计数器等......几乎这两个类需要做的一切他们的工作)。现在我想我可以把它们都装进一个班级。但是 - 第二,我需要以某种方式同步这两个线程。

最后,我来到了这个总体思路:

  • 3类:
    1. public class MyRenderer implements GLSurfaceView.RendereronSurfaceCreated()方法以绘制
    2. public class UpdateThread implements Runnablerun()update()方法的照顾。 run()正在调用update()方法每秒精确60次(我想要一个固定的步进循环)
    3. public class SpritesHolder用作所有游戏对象/变量/东西(如精灵,定时器,状态变量等)的容器...)所有的领域都是公开的。
  • 所以基本上SpritesHolder类是抱着箱子所有需要的变量在一个地方,所以MyRendererUpdateThread类可以访问它,使用它。
  • 至于同步 - 我只是做了水木清华这样的:

    public void update(float delta) 
    { 
        synchronized (spritesHolder) 
        { 
         // whole method code... 
        } 
    } 
    

    和:

    public void onDrawFrame(GL10 gl) 
    { 
        synchronized (spritesHolder) 
        { 
         // whole method code... 
        } 
    } 
    

    使两个线程并没有在同一时间使用spritesHolder。所以更新每秒完成60次,并且每当app(设备?)需要时都进行绘制。

说很多话,对不起,我已经差不多完成了写这篇文章。 ;)无论如何 - 这个(上面描述的)工作,我甚至根据这个'模板'编写了一些游戏,但我认为我的想法可能是疯狂的,并且可以更好地设计它。我会非常感谢所有意见和建议。

+0

只有一个词:http://obviam.net/ :) – akonsu 2012-03-28 20:23:04

回答

1

您的解决方案可能会起作用,但它可能不是最佳的性能。如果你仔细想想,渲染线程和更新线程并不需要100%独占。

最近,我花了一段时间考虑这件事对我的比赛,这就是我最终想出(不一定好,但只是一些思考):

对于每一个渲染对象,我有由更新线程拥有的对象,以及由呈现线程拥有的另一个对象,该对象只是包含有关如何绘制对象(模型矩阵,统一值,meshID等)的指令的普通容器。我运行更新线程,计算可渲染对象的所有最终位置和值,然后同步一个小窗口,在该窗口中将任何在该帧期间更改的值传递给可呈现线程中的对象。然后,只要新信息通过,帧渲染就开始,而下一个更新帧同时运行。因为只有一个小的排除窗口,它允许更新和绘制线程在大部分时间同时运行。

1

我还没有使用OpenGL,但UpdateThread应该是一个TimerTask。 在你的活动启动它与

new Timer().schedule(new UpdateThread(view), 0, 15); //where view is your view, and 15 is the wait time 

TimerTask的调用与处理程序的视图。 e.g(在您的视图类)

Handler refreshHandler = new Handler() { 
    public void handleMessage(Message msg) { 
       //Handle it; e.g. for canvas invalidate() 
      }}; 

在你UpdateThread run方法做到这一点:

view.refreshHandler.sendMessage(new Message()); 

现在,它是独立的gameloop的。此外,你的gameloop不应该在MainActivity中,而应该在Thread(单向OO)中。