bad FPS with android SurfaceView - android

I'm aware that there is alot of posts on this subject but non really helped me with my problem. Im fairly new to android programming and built my thread with the helt of a tutorial, the problem is that my emulator dosnt go over 15 fps and the program should run at 50 (FPS is initialized at 50). Here is the code from my thread:
public class MainThread extends Thread {
private static final String TAG = MainThread.class.getSimpleName();
// desired fps
private final static int MAX_FPS = 50;
// maximum number of frames to be skipped
private final static int MAX_FRAME_SKIPS = 5;
// the frame period
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
/* Stuff for stats */
private DecimalFormat df = new DecimalFormat("0.##"); // 2 dp
// we'll be reading the stats every second
private final static int STAT_INTERVAL = 1000; // ms
// the average will be calculated by storing
// the last n FPSs
private final static int FPS_HISTORY_NR = 10;
// last time the status was stored
private long lastStatusStore = 0;
// the status time counter
private long statusIntervalTimer = 0l;
// number of frames skipped since the game started
private long totalFramesSkipped = 0l;
// number of frames skipped in a store cycle (1 sec)
private long framesSkippedPerStatCycle = 0l;
// number of rendered frames in an interval
private int frameCountPerStatCycle = 0;
private long totalFrameCount = 0l;
// the last FPS values
private double fpsStore[];
// the number of times the stat has been read
private long statsCount = 0;
// the average FPS since the game started
private double averageFps = 0.0;
// Surface holder that can access the physical surface
private SurfaceHolder surfaceHolder;
// The actual view that handles inputs
// and draws to the surface
private MainGamePanel gamePanel;
// flag to hold game state
private boolean running;
public void setRunning(boolean running) {
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, MainGamePanel gamePanel) {
super();
this.surfaceHolder = surfaceHolder;
this.gamePanel = gamePanel;
}
#Override
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
// initialise timing elements for stat gathering
initTimingElements();
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
sleepTime = 0;
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
framesSkipped = 0; // resetting the frames skipped
// update game state
this.gamePanel.update();
// render state to the screen
// draws the canvas on the panel
this.gamePanel.render(canvas);
// calculate how long did the cycle take
timeDiff = System.currentTimeMillis() - beginTime;
// calculate sleep time
sleepTime = (int) (FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// we need to catch up
this.gamePanel.update(); // update without rendering
sleepTime += FRAME_PERIOD; // add frame period to check
// if in next frame
framesSkipped++;
}
if (framesSkipped > 0) {
Log.d(TAG, "Skipped:" + framesSkipped);
}
// for statistics
framesSkippedPerStatCycle += framesSkipped;
// calling the routine to store the gathered statistics
storeStats();
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
/**
* The statistics - it is called every cycle, it checks if time since last
* store is greater than the statistics gathering period (1 sec) and if so
* it calculates the FPS for the last period and stores it.
*
* It tracks the number of frames per period. The number of frames since the
* start of the period are summed up and the calculation takes part only if
* the next period and the frame count is reset to 0.
*/
private void storeStats() {
frameCountPerStatCycle++;
totalFrameCount++;
// assuming that the sleep works each call to storeStats
// happens at 1000/FPS so we just add it up
// statusIntervalTimer += FRAME_PERIOD;
// check the actual time
statusIntervalTimer += (System.currentTimeMillis() - statusIntervalTimer);
if (statusIntervalTimer >= lastStatusStore + STAT_INTERVAL) {
// calculate the actual frames pers status check interval
double actualFps = (double) (frameCountPerStatCycle / (STAT_INTERVAL / 1000));
// stores the latest fps in the array
fpsStore[(int) statsCount % FPS_HISTORY_NR] = actualFps;
// increase the number of times statistics was calculated
statsCount++;
double totalFps = 0.0;
// sum up the stored fps values
for (int i = 0; i < FPS_HISTORY_NR; i++) {
totalFps += fpsStore[i];
}
// obtain the average
if (statsCount < FPS_HISTORY_NR) {
// in case of the first 10 triggers
averageFps = totalFps / statsCount;
} else {
averageFps = totalFps / FPS_HISTORY_NR;
}
// saving the number of total frames skipped
totalFramesSkipped += framesSkippedPerStatCycle;
// resetting the counters after a status record (1 sec)
framesSkippedPerStatCycle = 0;
statusIntervalTimer = 0;
frameCountPerStatCycle = 0;
statusIntervalTimer = System.currentTimeMillis();
lastStatusStore = statusIntervalTimer;
// Log.d(TAG, "Average FPS:" + df.format(averageFps));
gamePanel.setAvgFps("FPS: " + df.format(averageFps));
}
}
private void initTimingElements() {
// initialise timing elements
fpsStore = new double[FPS_HISTORY_NR];
for (int i = 0; i < FPS_HISTORY_NR; i++) {
fpsStore[i] = 0.0;
}
Log.d(TAG + ".initTimingElements()",
"Timing elements for stats initialised");
}
}
All my drawing method has is this:
public void render(Canvas canvas) {
canvas.drawColor(Color.BLACK);
happy.draw(canvas);
// display fps
displayFps(canvas, avgFps);
There is some updates in there aswell but thats just to get my sprite moving. If any1 can see a problem or has any tips PLEASE let me know.
Thank you!
}

Do not rely on your emulator for performance benchmarking. While the emulator is good for checking the functionality and correctness of your app, it can take more (or less) time to do certain operations than a real device would. In perticular drawing operations seem to be longer on the emulator. I had a game run at 9-16 fps on the emulator while going 50+ on an old real device.
If your app/game still runs too slow on a real device you can profile your app (with TraceView for example) to see exactly what is taking up all your time and try to either optimize it or remove it (if possible).
Just as an extra tip: if possible try to have your surfaceView format be the same as all the resources that go on it, and try to prescale everything you can in advance (either at compile-time or at app startup/initialization phase), scaling and converting are expensive operations to do each frame.

If using Windows, you might try BlueStacks. Here are some of my results:
*****************************************************
ARM Emulator 2.4 GHz Core 2 Duo
Android Java OpenGL Benchmark 06-Mar-2013 21.17
--------- Frames Per Second --------
Triangles WireFrame Shaded Shaded+ Textured
9000+ 2.66 3.97 3.29 1.61
18000+ 1.48 1.84 1.72 0.88
36000+ 0.82 0.95 0.87 0.46
Screen Pixels 320 Wide 480 High
*****************************************************
BlueStacks Emulator on 3 GHz Phenom
Android Java OpenGL Benchmark 06-Mar-2013 21.25
--------- Frames Per Second --------
Triangles WireFrame Shaded Shaded+ Textured
9000+ 41.72 42.02 32.90 20.72
18000+ 22.11 22.09 19.28 11.58
36000+ 11.16 11.14 10.35 5.89
Screen Pixels 1024 Wide 600 High
*****************************************************
Samsung EXYNOS 5250 Dual 2.0 GHz Cortex-A15, Android 4.2.2
Mali-T604 Quad Core GPU
Android Java OpenGL Benchmark 09-Aug-2013 09.42
--------- Frames Per Second --------
Triangles WireFrame Shaded Shaded+ Textured
9000+ 39.13 41.52 32.19 27.25
18000+ 22.03 20.73 19.69 16.30
36000+ 12.24 12.23 10.75 8.68
Screen Pixels 1920 Wide 1032 High

Related

Blinking while drawing on canvas in loop

I have problem with drawing on android. I'm trying to create simple game that includes robots which will paint screen on different colors. Firstly I'm trying only paint screen without any robot image (I'm planing place it later on higher transparent view) but I encountered problem with flashing canvas.
So this is my render method. I can't use every time canvas.drawColor(Color.BLACK); before drawing because as I said robots need to paint screen with own color (Red and Blue). Other idea was to store every robot location and paint it on every "render" method, but it takes too much time and after few secounds game becoming really slow.
public void render(Canvas canvas) {
if(lastD1X!=-1 && lastD1Y!=-1){
canvas.drawLine(lastD1X, lastD1Y, droid.getX(), droid.getY(), drawPaint);
}
lastD1X = droid.getX();
lastD1Y = droid.getY();
if(lastD2X!=-1 && lastD2Y!=-1){
canvas.drawLine(lastD2X, lastD2Y, droid2.getX(), droid2.getY(), drawPaint2);
}
lastD2X = droid2.getX();
lastD2Y = droid2.getY();
}
This is my game loop:
#Override
public void run() {
Canvas canvas;
Log.d(TAG, "Starting game loop");
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
sleepTime = 0;
while (running) {
canvas = null;
// try locking the canvas for exclusive pixel editing
// in the surface
try {
canvas = this.surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
framesSkipped = 0; // resetting the frames skipped
// update game state
this.gamePanel.update();
// render state to the screen
// draws the canvas on the panel
this.gamePanel.render(canvas);
// calculate how long did the cycle take
timeDiff = System.currentTimeMillis() - beginTime;
// calculate sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// we need to catch up
this.gamePanel.update(); // update without rendering
sleepTime += FRAME_PERIOD; // add frame period to check if in next frame
framesSkipped++;
}
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}

jump method in android game

I'm new in Android Game Development and I started a simple Game in that a Droid can jump over incoming boxes.
I want to call my droid.jump() method in the surface view with an onTouchEvent (just by a simple tap on the screen)
I created a class called Droid:
public class Droid {
// Log Tag for Debugging
public static final String LOG_TAG = "_1Projekt";
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
private boolean touched; // if droid is touched/picked up
private Speed speed; // the speed with its directions
private long mLastTime;
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
this.speed = new Speed();
}
.......
...
And the jump() method is my problem. I would like to have a smooth jump but I don’t know how to calculate this with the current System Time.
My idea was that the droid should update it Y position every –TimePeriod- and should start with a fast velocity and then decrease it to 0 to get a smooth jump.
But I don’t know how to calculate this in my while loop.
My current jump():
public void jump() {
Log.d(LOG_TAG, "Jumping");
long now = System.currentTimeMillis();
int elapsedTime = 100;
int jump = y-30;
while(y > jump)
{
if(System.currentTimeMillis() > now + elapsedTime)
{
now = now + elapsedTime;
elapsedTime -=3;
y = y-1;
}
}
}
Up to know I only implemented the "up" part of Jump.
Thank you for your answers! Greetings DroidDude
You may want to look here (the third post):
Before the mainloop, have
//Get the current time
timeStep = System.currentTimeMillis();
And then do your stuff. Then before the loop goes back to start, have
// Hold to lock at FPS
while(System.currentTimeMillis()-timeStep < 1000/60);
Where 60 is the frames per second to run.
This method also allows you to get the difference in times after the
while loop in order to find out how much time it took to render one
frame. Using this, you could have a variable that you can multiply all
your increments by to get frame-independent speed.
For example, if you divide the number of milliseconds it took to
handle the frame by 16.666, the number will equal 1 when the program
runs at about 60 FPS. When the frame rate is lower, it takes more
milliseconds to render the frame and that factor gets bigger.
Be sure to put it BEFORE repaint however. This is the way video games
are timed also. An example is shown in my video game base applet code
snippet under JAVA.

android game loop surfaceview overlay with framelayout cause lag

i'm currently writing a android game, but now, i'm having some strange issues with the controls
if i have a framelayout with all my controls(the HP, points, game controls..etc) and put it on top of my surfaceview, my fps will never get above 20 fps; if i remove the framelayout, the game will hit 50+fps.
I'm suspecting that the system is rendering my surfaceview and framelayout's content all together in one thread, which explains why it's so slow
here's my game loop code
public void run() {
Canvas c;
initTimingElements();
long beginTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped
sleepTime = 0;
while (_run) {
c = null;
//long start = System.currentTimeMillis();
try {
c = _panel.getHolder().lockCanvas(null); // this is the problem!!
synchronized(_panel.getHolder()) {
beginTime = System.currentTimeMillis();
framesSkipped = 0; // resetting the frames skipped
_panel.updatePhysics();
_panel.checkForHits();
_panel.checkForKill();
_panel.checkForMCHits();
//if i put stuff related to ui in the loop, it will slow the control down to a unblelieveable state
//_panel.checkNPCQt();
_panel.onDraw(c);
timeDiff = System.currentTimeMillis() - beginTime;
// calculate sleep time
sleepTime = (int)(FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
// if sleepTime > 0 we're OK
/*
try {
// send the thread to sleep for a short period
// very useful for battery saving
Thread.sleep(sleepTime);
} catch (InterruptedException e) {}
*/
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// we need to catch up
//_panel.updatePhysics(); // update without rendering
sleepTime += FRAME_PERIOD; // add frame period to check if in next frame
framesSkipped++;
}
if (framesSkipped > 0) {
Log.d(TAG, "Skipped:" + framesSkipped);
}
// for statistics
framesSkippedPerStatCycle += framesSkipped;
// calling the routine to store the gathered statistics
storeStats();
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_panel.getHolder().unlockCanvasAndPost(c);
//Log.d(TAG, "unlock canvas");
}
}
i've pretty sure i got all my game logic and bitmaps are right; if i comment out all onDraw functions and everything else, i still got only 20-23 fps with framelayout there.
is there any alternatives? can create a separate thread for the UI draw? or am i just doing it wrong?
here is my XML state:
Solved, i accidentally messed up the framelayout, clean project is the answer

Android FPS, how to make it smoother?

I am having trouble in constructing a basic game loop for my game. I am at the early phase and all I want to do is to move the the ball at a constant speed (for ex: 3) through the bottom of the screen. The position of the ball is updated in the main panel update method and it is drawed in the render part as expected. Nothing exceptional in the mechanism. The ball moves but it is definitely not smooth, the visual is quiet disturbing.. I measured the implementation times of these methods and the total implementation time of this couple is about 3-4 milliseconds. Under these circumstances, what is the suitable FPS? Are the given constant values suitable What is missing or wrong in my mechanism? Thanks a lot in advance. the code block in main thread.
private final static int MAX_FPS = 200;
private final static int FRAME_PERIOD = 1000 / MAX_FPS;
private final static int MAX_FRAME_SKIPS = 5;
public void run() {
initTimingElements();
long beginTime;
long timeDiff;
int sleepTime;
int framesSkipped;
long beginTime2;
long diff1;
long diff2;
sleepTime = 0;
Canvas canvas;
Log.d(TAG, "Starting game loop");
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
framesSkipped = 0;
this.gamePanel.update();
diff1=System.currentTimeMillis()-beginTime;
beginTime2=System.currentTimeMillis();
this.gamePanel.render(canvas);
diff2=System.currentTimeMillis()-beginTime2;
timeDiff = System.currentTimeMillis() - beginTime;
sleepTime = (int) (FRAME_PERIOD - timeDiff);
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
this.gamePanel.update();
sleepTime += FRAME_PERIOD;
framesSkipped++;
}
if (framesSkipped > 0) {
Log.d(TAG, "Skipped:" + framesSkipped);
}
framesSkippedPerStatCycle += framesSkipped;
storeStats();
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
Try using a TimerTask that fires off every 60ms or so.
That's what I do until I stop being lazy enough to do a proper implementation, but it works well.
Just remember that run() will be executed in a different thread, so use runOnUIThread() to run whatever code you need.

Creating and displaying game objects every 3 seconds on the screen

I am having trouble in creating and displaying multiple game objects on the screen for every 3 seconds. there is no problem when there's only one object but if I want to create multiple, the problem occurs. To explain in detail, There's a main game loop (the one identical with the existing ones on the internet) and in that game loop,in every 3 seconds I want a new object to be created, added to the ArrayList and then update game panel and show all the objects on the screen in every 3 seconds. The code block above works but it is too fast so the screen is filled with images, I want it to be periodic. What must I do? If using a background thread in order to prevent the block of UI thread, how can I do it?
Thanks in advance.
Here's my code block:
MAIN THREAD PART:
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
beginTime = System.currentTimeMillis();
this.gamePanel.update();
this.gamePanel.render(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
and Update method in my MainGamePanel class:
public void update() {
int random = 5 + (int) (Math.random() * (200 - 5));
droid = new Carrier(BitmapFactory.decodeResource(getResources(),
R.drawable.image), random, 1);
Carriers.add(Carrier);
for (int i = 0; i < Carriers.size(); i++) {
Carrier CarrierTemp = Carriers.get(i);
CarrierTemp .update();
}
}
Here's a solution that is built on your current code:
Put this in your thread somewhere:
int savedtime = 0;
long lastTime;
in your update() method:
//Calculate time since last update:
long now = System.currentTimeMillis();
savedtime += now - lastTime;
lastTime = now;
if(savedTime > 3000){//if more than three seconds have passed:
savedTime = 0;
int random = 5 + (int) (Math.random() * (200 - 5));
droid = new Carrier(BitmapFactory.decodeResource(getResources(),R.drawable.image), random, 1);
Carriers.add(Carrier);
}
for (int i = 0; i < Carriers.size(); i++) {
Carrier CarrierTemp = Carriers.get(i);
CarrierTemp .update();
}

Categories

Resources