Hello android开发者,
我正在使用OpenGLES 1.0在Eclipse中开发一款适用于Android的简单游戏。我使用三星Galaxy S2 Android(2.3)作为开发设备。
我有一个关于双核并使帧速率保持不变的问题。
所以我设法创建了GLSurfaceView并覆盖onDrawFrame()函数,我调用了LogicUpdate(deltatime)函数和Render()函数。
是的,目前只有单线程。
我遇到的问题是双核心。如果我通过设置 - >省电并禁用系统省电禁用双核,我意识到渲染会自动锁定在30 FPS。但是,如果我通过取消选中系统省电来启用双核,我会发现渲染被锁定在60 FPS,但手机变热并且电池耗电非常快。
所以我的想法是让我的游戏以30 FPS运行以节省一些电量。
为此,我使用下面的代码。
在我进行逻辑更新之前,我称之为代码安静,请记住所有这些都是在onDrawFrame()中完成的。
if( CONST_FPS > 0 && StartTime > 0 )
{
/////////////////////////////////////////////////////////////////
// Get frame time
////////////////////////////////////////////////////////////////
long endTime = System.currentTimeMillis();
long time = endTime - StartTime;
//
long wantedtime = 1000 / CONST_FPS;
//
long wait = 0;
if( time < wantedtime )
{
wait = wantedtime - time;
//
Thread.sleep(wait);
}
else
{
//Time to big game will slow down
}
}
CONST_FPS = 30
然后
StartTime = System.currentTimeMillis(); //
UpdateLogic(1.0 / CONST_FPS);
Render();
30 FPS的游戏玩法非常流畅,主要是因为它不需要锁定FPS。 但是,当试图将60FPS锁定到30 FPS时,我会出现口吃。我做了一些研究,发现Thread.Sleep()不准确。这是真的?当将60FPS锁定到30FPS时,我还能做些什么来使游戏更加流畅。
感谢您的回答......
答案 0 :(得分:6)
您应该使用经过的时间来缩放所有移动,以便在不同的FPS速率下移动保持平滑。你可以像这样得到经过的时间:
long currentTime = System.currentTimeMillis();
float elapsed = (System.currentTimeMillis() - lastFrameTime) * .001f;//convert ms to seconds
lastFrameTime = currentTime;
然后以每秒为单位表达你的速度,并像这样更新位置:
sprite.x += (sprite.xspeed * elapsed);
答案 1 :(得分:3)
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.1f, 0.1f, 0.1f, 1);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
GLES20.glDepthFunc(GLES20.GL_LEQUAL);
GLES20Renderer.programLight = GLES20.glCreateProgram();
int vertexShaderLight = GLES20Renderer.loadShader(GLES20.GL_VERTEX_SHADER, GLES20Renderer.vertexShaderCodeLight);
int fragmentShaderLight = GLES20Renderer.loadShader(GLES20.GL_FRAGMENT_SHADER, GLES20Renderer.fragmentShaderCodeLight);
GLES20.glAttachShader(GLES20Renderer.programLight, vertexShaderLight);
GLES20.glAttachShader(GLES20Renderer.programLight, fragmentShaderLight);
GLES20.glLinkProgram(GLES20Renderer.programLight);
System.gc();
}
public void onSurfaceChanged(GL10 gl, int width, int height) {
gl.glViewport(0, 0, width, height);
float ratio = (float) width / height;
Matrix.setLookAtM(GLES20Renderer.ViewMatrix, 0, 0, 0, 5f, 0, 0, 0, 0, 1, 0);
Matrix.frustumM(GLES20Renderer.ProjectionMatrix, 0, -ratio, ratio, -1, 1, 2, 8);
Matrix.setIdentityM(LightModelMatrix, 0);
Matrix.translateM(LightModelMatrix, 0, -1.0f, 0.0f, 3f);
Matrix.multiplyMV(LightPosInWorldSpace, 0, LightModelMatrix, 0, LightPosInModelSpace, 0);
Matrix.multiplyMV(LightPosInEyeSpace, 0, ViewMatrix, 0, LightPosInWorldSpace, 0);
System.gc();
}
public void onDrawFrame(GL10 gl) {
long deltaTime,startTime,endTime;
startTime = SystemClock.uptimeMillis() % 1000;
gl.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
synchronized (this) {
updateModel(GLES20Renderer._xAngle, GLES20Renderer._yAngle, GLES20Renderer._zAngle);
}
renderModel(gl);
endTime = SystemClock.uptimeMillis() % 1000;
deltaTime = endTime - startTime;
if (deltaTime < 30) {
try {
Thread.sleep(30 - deltaTime);
} catch (InterruptedException e) {
//e.printStackTrace();
}
}
System.gc();
}
<强>注意:强>