I'm using Surfaceview in my Android app. I have two threads, one for UI and another for rendering and updading the UI.
I am limiting my frames per second to 30 fps and have employed frame-skipping to a max of 3 frames.
I am using delta to update my sprite positions.
All works as it should apart from one thing - the sprites don't move entirely 'smoothly'
They seem to 'jerk' randomly. And I'm just wondering, is this just the way surfaceview is? I'm guessing it's when the device is doing something else? Can I give priority to my app somehow or does anyone have any tips (apart from switching to OpenGL !!) On optimising surfaceView and to get it to run a bit smoother?
Thanks
I've removed everything from my onDraw() and update() methods and just put 1 small sprite in onDraw() and added 1 to the sprites X position in my update() method. The sprite still 'jerks' along, hard to explain, but it moves smoothly for a little while then there's a slight stutter.
Edit: Some code as requested..... (I've given my onDraw, update and run methods here)
@Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(scaledBackground, 0, 0, null);
canvas.drawBitmap(scaledSmallCloud, cloudX, cloudY, null};
}
public void update() {
cloudX++;
}
protected class preThread extends Thread {
private SurfaceHolder mySurfaceHolder;
private Context myContext;
// flag to hold game state
private boolean running;
public preThread(SurfaceHolder surfaceholder, Context context, Handler handler) { // Constructor
mySurfaceHolder=surfaceholder;
myContext=context;
res = myContext.getResources();
}
public void setRunning(boolean running) {
this.running = running;
}
@Override
public void run() {
Canvas c;
while (running) {
c=null;
timestart = System.currentTimeMillis(); //Get time at start of loop for FPS calc
try {
c = mySurfaceHolder.lockCanvas(null);
synchronized(mySurfaceHolder) {
onDraw(c);
update();
}
} finally {
if (c != null) {
mySurfaceHolder.unlockCanvasAndPost(c);
}
}
//Frame limiting and skipping calcs
timeend = System.currentTimeMillis(); //Get end time of current frame
frametime = timeend-timestart; //Time frame took to render and update
sleepfor = (int) ((1000/fps)-frametime); // this is the time that the thread will sleep for if <target time
if (sleepfor>0){ // If the 'sleepfor' variable is >0 then set the thread to sleep for it's value (expressed in ms)
try {
MainThread.sleep(sleepfor); //send thread to sleep for value of sleepfor (determined above).
} catch (InterruptedException e) {} //in case of exception
} //close if statement
while (sleepfor<0 && framesskipped<maxframesskipped) { //if sleepfor is < 0 (ie, frame took longer to render than target time and the maxframesskipped has not reached it's limit)
update(); //Update animation variables without rendering to the screen while these conditions are met
sleepfor+=33.33333333333333; //time to sleep plus the time frame took to render
framesskipped++; //add one to framesskipped variable so this only skips a certain number of frames
//Log.v("Timer","frame skipped!");
//frame=0;
}
}
}
This is basically a really stripped down onDraw() which simply displays a static background and a single moving sprite.
I have removed my delta-sprite movement to rule that out and am simply incrementing the sprite's x position by an explicit value (1).
I've also tried the following:
Removing the drawing of the background image
Changing 'overridden' onDraw() to doDraw and moving it to the preThread class.
Increasing upper frame rate limit to 60fps (as @Lumis suggested in comments)
I've removed my frame limiting and skipping so the game just runs flat out at the max frame rate - this gives a slightly different effect, less of a 'quick skip' and more of an intermittent prolonged 'slow down', then 'speed up' of the sprites.
What actually happens - the sprite does move smoothly (even at 30 fps), but every now and then (more often than I would like) - it kind of 'lags' or 'jerks', it's a small effect but is extremely annoying.
Any more suggestions would be very much appreciated - thank you again!