使用OpenGL将游戏逻辑与Android的快节奏游戏分离的最佳方法是什么?

时间:2011-12-15 15:34:48

标签: android opengl-es

我一直在学习和制作小游戏,最近我决定尝试为Android开发游戏。

对我来说,从原生C ++代码跳转到Android Java并不是那么难,但是让我头疼的是考虑如何将逻辑与渲染分开。

我一直在这里和其他网站上阅读:

  

最好不要为它创建另一个线程,因为   Android肯定没有处理问题。

意思是代码是这样的:

public void onDrawFrame(GL10 gl) {
    doLogicCalculations();
    clearScreen();
    drawSprites();
}

但我不确定这是否是最佳方法。因为我不认为如果我把我的逻辑放在GLRenderer::onDrawFrame方法中它会是什么样子。据我所知,这个方法只是为了绘制,如果我把逻辑放在那里,我可能会减慢帧的速度。更不用说它在我的理解中伤害了POO的概念。

我认为使用线程可能就是这样,这就是我的计划方式:

主要活动:

public void onCreate(Bundle savedInstanceState) {
    //set fullscreen, etc

    GLSurfaceView view = new GLSurfaceView(this);
    //Configure view

    GameManager game = new GameManager();
    game.start(context, view);

    setContentView(view);
}

游戏管理:

OpenGLRenderer renderer;
Boolean running;
public void start(Context context, GLSurfaceView view) {
    this.renderer = new OpenGLRenderer(context);
    view.setRenderer(this.renderer);

    //create Texturelib, create sound system...

    running = true;
    //create a thread to run GameManager::update()
}

public void update(){
    while(running){
        //update game logic here
        //put, edit and remove sprites from renderer list
        //set running to false to quit game
    }
}

最后,OpenGLRenderer:

ListOrMap toDraw;
public void onDrawFrame(GL10 gl) {
    for(sprite i : toDraw)
    {
        i.draw();
    }
}

这是一个粗略的想法,并不完全完整。 这种模式会让它们全部分开,看起来会好一点,但它是最好的表现吗?

只要我研究过,大多数线程游戏的例子都使用canvas或surfaceview,那些不适合我的情况,因为我使用的是OpenGLES。

所以这是我的问题:

  

哪种方式可以分开我的   使用OpenGLES时渲染的游戏逻辑?穿越我的   应用?将逻辑放在一个单独的方法中,然后从中调用它   绘制方法?

2 个答案:

答案 0 :(得分:10)

所以我认为有两种方法可以去这里。

  1. onDrawFrame()执行所有更新:这类似于使用GLUT,Android会尽可能多地调用此函数。 (用setRenderMode(RENDERMODE_WHEN_DIRTY)关闭它。)此函数在其自己的线程(而不是UI线程)上调用,这意味着您在此处调用逻辑更新。你最初的问题是,这似乎有点混乱,我同意,但只是因为该函数名为onDrawFrame()。如果它被称为onUpdateScene(),那么更新逻辑将很好地适合这个模型。但这并不是世界上最糟糕的事情,它是以这种方式设计的,人们也这样做。

  2. 给逻辑提供自己的线程:这更复杂,因为现在你要处理三个线程:用于输入的UI线程,用于绘制东西的渲染线程onDrawFrame() ,以及连续使用输入和渲染数据的逻辑线程。如果您需要有一个非常准确的模型来使用它,即使您的帧速率正在下降(例如,精确的碰撞响应)。这在概念上可能更清洁,但实际上并不干净。

  3. 我会推荐#1。你真的不需要#2。如果你这样做,你可以稍后添加它我想,但大多数人只是使用第一个选项,因为硬件足够快,所以你不必围绕它进行设计。

答案 1 :(得分:6)

让您的设计尽可能简单:) 标准(也许是最好的)方法如下:

public void update(){
    while(running){
        updateAll();
        renderAll();
    }
}

我会注意一些时刻:

  • 您需要调用后续updaterender方法,避免一次调用update两次
  • 如果您更喜欢多线程(我没有),请设计您的方法,以便update写入数据,render仅读取
  • 请记住,OpenGL有自己的“线程”,所以当你调用GL函数时它只向OpenGL发送一些命令(glFlush()除外 - 它完成所有命令)