我一直在学习和制作小游戏,最近我决定尝试为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时渲染的游戏逻辑?穿越我的 应用?将逻辑放在一个单独的方法中,然后从中调用它 绘制方法?
答案 0 :(得分:10)
所以我认为有两种方法可以去这里。
从onDrawFrame()
执行所有更新:这类似于使用GLUT,Android会尽可能多地调用此函数。 (用setRenderMode(RENDERMODE_WHEN_DIRTY)
关闭它。)此函数在其自己的线程(而不是UI线程)上调用,这意味着您在此处调用逻辑更新。你最初的问题是,这似乎有点混乱,我同意,但只是因为该函数名为onDrawFrame()
。如果它被称为onUpdateScene()
,那么更新逻辑将很好地适合这个模型。但这并不是世界上最糟糕的事情,它是以这种方式设计的,人们也这样做。
给逻辑提供自己的线程:这更复杂,因为现在你要处理三个线程:用于输入的UI线程,用于绘制东西的渲染线程onDrawFrame()
,以及连续使用输入和渲染数据的逻辑线程。如果您需要有一个非常准确的模型来使用它,即使您的帧速率正在下降(例如,精确的碰撞响应)。这在概念上可能更清洁,但实际上并不干净。
我会推荐#1。你真的不需要#2。如果你这样做,你可以稍后添加它我想,但大多数人只是使用第一个选项,因为硬件足够快,所以你不必围绕它进行设计。
答案 1 :(得分:6)
让您的设计尽可能简单:) 标准(也许是最好的)方法如下:
public void update(){
while(running){
updateAll();
renderAll();
}
}
我会注意一些时刻:
update
和render
方法,避免一次调用update
两次update
写入数据,render
仅读取glFlush()
除外 - 它完成所有命令)