Frame-rate not constant android game -
at university last spring studied android , last assignment develop game. not give details game used class extends surfaceview gamepanel , put game-loop in background-thread. game took 1 month hard work finish outcome - launched on android market , have more , more downloads. there 1 rather big drawback , follows here:
to highest rate in assignment 1 had make game frame-rate must constant. , because got highest degree , teachers satisfied source code thought there no bugfix. - thing frame-rate not constant. , more strange: graphical objects moves across screen - moves slower faster cpu is.
i have 3 phones of different models shows 3 different speeds:
- samsung galaxy mini (processor clock speed 1 ghz) here objects move fast
- samsung galaxy s3 (processor clock speed 1.8 ghz) here objects move @ medium speed
- samsung galaxy s4 (processor clock speed 2.3 ghz) here objects move slow
so briefly - more powerful smartphone in context of processor slower graphical objects move on screen - 1 expext opposite - frame-rate higher faster smartphones.
i present backgroundthread below holds gameloop - cannot see did wrong in code - nor teachers
public class mainthread extends thread { private static final string tag = mainthread.class.getsimplename(); private final static int max_fps = 50; // antal frames per sekund. private final static int max_frame_skips = 5; // antal förlorade frames. private final static int frame_period = 1000 / max_fps; private surfaceholder surfaceholder; private gamepanel gamepanel; private boolean running; public void setrunning(boolean running) { this.running = running; } public mainthread(surfaceholder surfaceholder, gamepanel gamepanel) { super(); this.surfaceholder = surfaceholder; this.gamepanel = gamepanel; } @override public void run() { canvas canvas; log.d(tag, "starting game loop"); long begintime; // cykelns starttid long timediff; // tiden det tar för en cykel int sleeptime; // cykel (update + render = timediff) + sleeptime => frameperiod. int framesskipped; // antalet förlorade frames. sleeptime = 0; while (running) { canvas = null; try { canvas = this.surfaceholder.lockcanvas(); synchronized (surfaceholder) { begintime = system.currenttimemillis(); framesskipped = 0; try { this.gamepanel.update_graphics(); this.gamepanel.render_graphics(canvas); } catch (exception e) { system.out.println("fel uppstod bakgrundstråden: " + e); } timediff = system.currenttimemillis() - begintime; sleeptime = (int)(frame_period - timediff); //system.out.println("sleeptime: " + sleeptime); if (sleeptime > 0) { // sleeptime ska vara positiv, med marginal. (annars risk för hackig animation) try { thread.sleep(sleeptime); // tråden sover en stund. } catch (interruptedexception e) {} } while (sleeptime < 0 && framesskipped < max_frame_skips) { // används för att "komma igen/komma ikapp". try { this.gamepanel.update_graphics(); // endast updatering. } catch (exception e) { system.out.println("fel uppstod bakgrundstråden: " + e); } sleeptime += frame_period; framesskipped++; } if (framesskipped > 0) { //log.d(tag, "skipped:" + framesskipped); } } } { if (canvas != null) { surfaceholder.unlockcanvasandpost(canvas); } } // slut } }
}
thanks in advance
i assuming update_graphics
method based on fixed delta time of frame_period
.
the problem while (sleeptime < 0 && framesskipped < max_frame_skips)
catch-up loop not account time left on when finishes catching model.
for example: frame_period
20ms. suppose galaxy mini takes 2ms run update_graphics
, 19ms run render_graphics
. enter catch-up loop sleeptime=-1ms
, run update_graphics
once. on next time while loop continues, calls update_graphics
, render_graphics
again in try block. time render_graphics
finishes drawing second time, has been 23ms since last time finished, update_graphics
has been called twice. therefore, appears 40ms of game time have passed in space of 23ms, game appear running 40/23 or 173% of intended speed.
meanwhile, on fast device sleep time positive, game appear correct.
also note, speed difference between galaxy mini , galaxy s3 have gone in other direction (with s3 appearing faster) depending on relative times takes update , render methods , ratio frame_period
.
but aside above simplified situation (which ignores vsync), sleep time never going applied os--it vary plus or minus few ms each time.
for simple game doesn't have physics simulation, simpler solution use variable delta time in update method.
if have fixed delta time (which may need game physics, or game using fixed delta time), this site presents clear explanation of how implement it.
Comments
Post a Comment