如何阻止每秒帧数下降?

时间:2014-02-10 08:01:22

标签: java android performance game-engine

好的,那么为什么在玩游戏时我的每秒帧数会随机下降?我该怎么做才能解决它。下面我将展示我对构建的引擎的代码。

        public Engine() {
    Log.d("Engine","Engine constructor");
    p_view = null;
    p_canvas = null;
    p_thread = null;
    p_running = false;
    p_paused = false;
    p_resume = false;
    p_paintDraw = null;
    p_paintFont = null;
    p_numPoints = 0;
    p_typeface = null;
    p_preferredFrameRate = 40;
    p_sleepTime = 1000 / p_preferredFrameRate;
    p_pauseCount = 0;
    p_group = new LinkedList<Sprite>();
}

   /**
 * Runnable.run thread method (MAIN LOOP)
 */
@Override 
public void run() {
    Log.d("Engine","Engine.run start");

    ListIterator<Sprite> iter=null, iterA=null, iterB=null;    

    Timer frameTimer = new Timer();
    int frameCount=0;
    int frameRate=0;
    long startTime=0;
    long timeDiff=0;

    while (p_running) {
        // Process frame only if not paused
        if (p_paused) continue;

        // Calculate frame rate
        frameCount++;
        startTime = frameTimer.getElapsed();
        if (frameTimer.stopwatch(1000)) {
            frameRate = frameCount;
            frameCount = 0;

            //reset touch input count
            p_numPoints = 0;
        }


        // Call abstract update method in sub-class
        update();


        /**
         * Test for collisions in the sprite group.
         * Note that this takes place outside of rendering.
         */
        iterA = p_group.listIterator();
        while (iterA.hasNext()) {
            Sprite sprA = (Sprite)iterA.next();
            if (!sprA.getAlive()) continue;
            if (!sprA.getCollidable()) continue;

            /*
             * Improvement to prevent double collision testing
             */
            if (sprA.getCollided()) 
                continue; //skip to next iterator

            //iterate the list again
            iterB = p_group.listIterator(); 
            while (iterB.hasNext()) {
                Sprite sprB = (Sprite)iterB.next();
                if (!sprB.getAlive()) continue;
                if (!sprB.getCollidable()) continue;

                /*
                 * Improvement to prevent double collision testing
                 */
                if (sprB.getCollided()) 
                    continue; //skip to next iterator

                //do not collide with itself
                if (sprA == sprB) continue;

                /*
                 * Ignore sprites with the same ID? This is an important
                 * consideration. Decide if your game requires it or not.
                 */
                if (sprA.getIdentifier() == sprB.getIdentifier())
                    continue;

                if (collisionCheck(sprA, sprB)) {
                    sprA.setCollided(true);
                    sprA.setOffender(sprB);
                    sprB.setCollided(true);
                    sprB.setOffender(sprA);
                    break; //exit while
                }
            }
        }


        // begin drawing
        if (beginDrawing()) {

            // Call abstract draw method in sub-class
            draw();


            /**
             * Draw the group entities with transforms
             */
            iter = p_group.listIterator(); 
            while (iter.hasNext()) {
                Sprite spr = (Sprite)iter.next();
                if (spr.getAlive()) {
                    spr.animate();
                    spr.draw();
                }
            }

            /**
             * Print some engine debug info.
             */
            int x = p_canvas.getWidth()-150;
            p_canvas.drawText("ENGINE", x, 20, p_paintFont);
            p_canvas.drawText(toString(frameRate) + " FPS", x, 40, 
                p_paintFont);
            p_canvas.drawText("Pauses: " + toString(p_pauseCount), 
                x, 60, p_paintFont);

            // done drawing
            endDrawing();
        }

        /*
         * Do some cleanup: collision notification, removing
         * 'dead' sprites from the list.
         */
        iter = p_group.listIterator(); 
        Sprite spr = null;
        while (iter.hasNext()) {
            spr = (Sprite)iter.next();

            //remove from list if flagged
            if (!spr.getAlive()) {
                iter.remove();
                continue;
            }

            //is collision enabled for this sprite?
            if (spr.getCollidable()) {

                //has this sprite collided with anything?
                if (spr.getCollided()) {

                    //is the target a valid object?
                    if (spr.getOffender() != null) {

                        /*
                         * External func call: notify game of collision
                         * (with validated offender)
                         */
                        collision(spr);

                        //reset offender
                        spr.setOffender(null);
                    }

                    //reset collided state
                    spr.setCollided(false);

                }
            }
        }

        // Calculate frame update time and sleep if necessary
        timeDiff = frameTimer.getElapsed() - startTime;
        long updatePeriod = p_sleepTime - timeDiff;
        if (updatePeriod > 0) {
            try {
                Thread.sleep( updatePeriod ); // i notice this is called when frames are low
            }
            catch(InterruptedException e) {}
        }

    }//while
    Log.d("Engine","Engine.run end");
    System.exit(RESULT_OK);
}    


    public void setFrameRate(int rate) {
    p_preferredFrameRate = rate;
    p_sleepTime = 1000 / p_preferredFrameRate;
}

所以这不是整个引擎,但它是处理帧的一切为什么它会随机掉线?当帧数降到15以下时,我注意到正在调用thread.sleep。我正在使用nexus 5来测试android 4.4.2上的运行情况,我的问题是如何阻止帧降低让它睡觉特别是在调用recreate()之后;你输掉比赛的方法?

1 个答案:

答案 0 :(得分:2)

完全取出Thread.Sleep语句。或者只是将“0”传递给Sleep调用(如果您尝试将循环传递给其他线程和进程)。在run()循环的每个循环中,计算实际经过的时间并根据此值更新模拟。换句话说,不要试图强制硬编码帧速率。

设备的帧速率上限(我的设备上为60fps)。因此,无论如何,你可能会在每个循环中睡一会儿。