Android 2d canvas game: FPS Jitter problem

后端 未结 5 1535
后悔当初
后悔当初 2021-01-31 07:04

I based my game off of the lunar lander demo, although heavily modified, and I can get around 40-50fps but the problem is it fluctuates between 40-50fps so much that it causes t

5条回答
  •  天涯浪人
    2021-01-31 07:29

    I am thinking there might be, not really something wrong with some of the above code, but rather an inefficiency. I am talking about this code...

       // The important part!
    // This starts another thread (let's call this THREAD_B). THREAD_B will run completely
    // independent from THREAD_A (above); therefore, FPS changes will not affect how
    // our velocity increases our position.
    public void startMyLogicThread() {
        new Thread() {
            public void run() {
                // Store the current time values.
                long time1 = System.currentTimeMillis();
                long time2;
    
                // Once active is false, this loop (and thread) terminates.
                while (active) {
                    try {
                        // This is your target delta. 25ms = 40fps
                        Thread.sleep(25);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
    
                    time2 = System.currentTimeMillis(); // Get current time
                    int delta = (int) (time2 - time1); // Calculate how long it's been since last update
                    update(delta); // Call update with our delta
                    time1 = time2; // Update our time variables.
                }
            }
        }.start(); // Start THREAD_B
    }
    

    Specifically, I am thinking about the following lines...

    // This is your target delta. 25ms = 40fps
    Thread.sleep(25);
    

    It seems to me that just having the thread hang out doing nothing is a waste of valuable processing time, when in fact what you want to be doing is performing the updates, then, if the updates have taken less time than the 25 millis, then sleep the thread for the difference of what was used during the update and 25 millis (or whatever your chosen frame rate is). In this way the update will happen while the current frame is being rendered, and will be completed so the next frame update uses the updated values.

    The only problem I can think of here is that some kind of syncronization will need to occur so that the current frame render does not use partially updated values. Perhaps update into a new instance of your set of values, and then make the new instance the current instance just before rendering.

    I think I remember reading something in a graphics book about the goal being to perform as many updates as you can while staying within your desired frame rate, then, and only them, perform a screen update.

    This of course will require one thread to drive the updates - if you use a SurfaceView, the render is controlled by this thread when you lock the canvas (in theory, according to my understanding anyway).

    So, in code, it would be more like...

    // Calculate next render time
    nextRender = System.currentTimeInMillis() + 25;
    
    while (System.currentTimeInMillis() < nextRender)
    {
        // All objects must be updated here
        update();
    
        // I could see maintaining a pointer to the next object to be updated,
        // such that you update as many objects as you can before the next render, and 
        // then continue the update from where you left off in the next render...
    }
    
    // Perform a render (if using a surface view)
    c = lockCanvas() blah, blah...
    // Paint and unlock
    
    // If using a standard view
    postInvalidate();
    

    Good luck and any feedback from anyone using this would surely help us all learn something...

    rpbarbati

提交回复
热议问题