Constant FPS Android OpenGLES

不打扰是莪最后的温柔 提交于 2019-11-30 10:51:23

You should use elapsed time to scale all your movement, so that the movement stays smooth at varying FPS rates. You can get elapsed time like this:

long currentTime = System.currentTimeMillis();
float elapsed = (System.currentTimeMillis() - lastFrameTime) * .001f;//convert ms to seconds
lastFrameTime = currentTime; 

Then express your velocities in units per second, and update position like this:

sprite.x += (sprite.xspeed * elapsed);
GLES
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();
}

ATTENTION:

  1. Never use sleep in the UI thread; it is very very very bad
  2. Use statics: although this is bad OOP practice, it is useful here
  3. Use vertexbuffer objects
  4. Initialize in onsurfacechanged and fetch locations (glget__location) here too
  5. It is not your fault always because Froyo garbage collector is bad and then on Gingerbread the touch drivers fire too many events (Google this) so gradually switch to other input methods for your app/game that does not use touch like Android sensors
  6. Upgrade to Gingerbread
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!