I'm new in Android and i'm developing the Insult Swordfighting of Monkey Island 1, but i'm facing some noob problems :)
This is my GameLoop:
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;
// 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++;
}
}
} finally {
// in case of an exception the surface is not left in
// an inconsistent state
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
} // end finally
}
}
First noob question:
Is it legit that the background or fixed images (like a finished animation frame) are rendered constantly? Is it a waste of memory?
I'd like to start with a cheap memory logic before to start with a major use of animations.
Second question:
In my render() function I call
canvas.drawBitmap(background, null,new Rect(0, 0,canvas.getWidth(),canvas.getHeight()), paint);
or
Rect dest = new Rect(this.getXpos(), getYpos(), getXpos() + (rclip.right - rclip.left),
getYpos() + (rclip.bottom - rclip.top));
canvas.drawBitmap(tileSheet, rclip, dest, null);
Is it right to call all that "new"? GC cleans those after using them?
Related
I'm trying to build a simple Simon Says game. I have 3 randomly placed bitmaps that will change their animation from sleeping to waking up to sleeping and I call this the light up sequence so when app starts, each bitmap will go from sleeping smiley face bitmap->wake up smiley face bitmap-->sleeping face bitmap and there is delay of 1000ms between each transition of smiley faces for each of the 3 bitmaps randomly placed on screen. I get a black screen and I check Android Monitor and it says "sending message to a Handler on a dead thread".
I named my bitmaps that light up a g. dot or good dot. The update method updates the state of the bitmap's image as sleep bitmap or awake bitmap to draw per
bitmap on screen. I'm currently using 3 randomly placed bitmaps. Please help, appreciate it. I didn't include my GoodDot class which is just a class that assigns the default sleep bitmap smiley face and has a method to check that 2 bitmaps don't land on same location on screen and of course tracks a bitmap's location on screen so (x,y) coordinate. Please help, appreciate it.
So part 1 of game is when a new level starts or when app is opened (I'll worry about saving state later) then a random positioned and randomly assigned sequence of the 3 bitmaps will light up
part 2: just to run the while loop at bottom of the run method and basically i'll add detecting touch for player to press on the bitmaps in correct sequence to win a level.
Here is the MainActivity class:
public class MainActivity extends Activity {
private Handler myHandler;
Canvas canvas;
Paint paint;
GameView gameView;
Bitmap restBitmap;
Bitmap awakeBitmap;
final int NUM_GOOD_DOTS = 3;
static int curPos = 0;//cur g. dot doing its light up sequence
GoodDot goodDotList[];
int screenWidth;
int screenHeight;
//The size in pixels of a place on the game board
int blockSize;
int numBlocksWide;
int numBlocksHigh;
static boolean isFirstTimeSettingUpGoodDotPosns = false;
static boolean isLightUpSequenceFinishedForCurLevel = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new GameView(this);
canvas = new Canvas( );
paint = new Paint ( );
myHandler = new Handler();
configureDisplay();
setContentView(gameView);
}//END METHOD: onCreate
class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private SurfaceHolder surfaceHolder;//this lets us access the canvas but still need to use Canvas class
private Thread myThread;
public GameView(Context context) {
super(context);
myThread = new Thread();
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
myThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
// What do I enter here???
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
while (retry) {
try {
myThread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLightUpSequenceFinishedForCurLevel = false;
}
protected void drawSomething ( ) {
Log.i ("curPos so far:", "" + curPos );
if (surfaceHolder.getSurface().isValid() ) {
canvas = surfaceHolder.lockCanvas();
if (isFirstTimeSettingUpGoodDotPosns == false) {
//assign random posns to bitmaps
// as they are NOT on same spot on screen!
Random r = new Random();
for (int i = 0; i < NUM_GOOD_DOTS; i++) {
goodDotList[i] = new GoodDot(1, 1, restBitmap);
goodDotList[i].setGoodDotX((r.nextInt(3) + 1) * blockSize);
goodDotList[i].setGoodDotY((r.nextInt(3) + 1) * blockSize);
}
//this method ensures no bitmaps land on same position
// on screen
gameView.assignProperPosnForGoodDots();
isFirstTimeSettingUpGoodDotPosns = true;
}
canvas.drawColor(Color.BLACK);//the background
paint.setColor(Color.argb(255, 255, 255, 255));
paint.setStrokeWidth(3);
// for loop to draw all g. dots
for (int i = 0; i < NUM_GOOD_DOTS; i++) {
canvas.drawBitmap(goodDotList[i].getBitmap(),
goodDotList[i].getGoodDotX(), goodDotList[i].getGoodDotY(), paint);
}
//this method called is only for testing
drawGrid(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
}//END IF BLOCK: For valid surfaceHolder
}//END METHOD: drawSomething
//this method is only for testing to see the grid that each bitmap is inside a block
private void drawGrid ( Canvas canvas ) {
//var to draw horizontal line part of grid
float rowStartX = 0; float rowStartY = 0;
float rowEndX = screenWidth; float rowEndY = 0;
//var to draw vertical line part of grid
int colStartX = 0; int colStartY = 0;
int colEndX = 0; int colEndY = screenHeight;
// Log.d("NUM BLOCKS HIGH", "Value:" + numBlocksHigh );
//draw the horizontal lines
for ( int i = 0; i < numBlocksHigh; i++ ) {
canvas.drawLine ( rowStartX, rowStartY, rowEndX, rowEndY , paint );
rowStartY += blockSize;
rowEndY += blockSize;
}
//draw the vertical lines
for ( int i = 0; i < numBlocksWide; i++ ) {
canvas.drawLine ( colStartX, colStartY, colEndX, colEndY , paint );
colStartX += blockSize;
colEndX += blockSize;
}
}//END METHOD: drawGrid
//Each g. dot goes thru 3 states: rest, light up/awake, rest
public void update() {
switch ( goodDotList [ curPos ].getGoodDotState() ) {
case 1:
goodDotList[ curPos ].setBitmap( restBitmap );
break;
case 2:
goodDotList[ curPos ].setBitmap( awakeBitmap );
break;
case 3:
goodDotList[ curPos ].setBitmap( restBitmap );
break;
default:
break;
}
//Go to next g. dot once 3 states finished for a given g. dot
if ( goodDotList [ curPos ].getGoodDotState() > 3 ) {
curPos++;
}
else {
goodDotList [ curPos ].setGoodDotState(
goodDotList [ curPos ].getGoodDotState() + 1 );
}
}//END METHOD: update
//this method makes sure no GOOD DOTS land on same spot
public void assignProperPosnForGoodDots ( ) {
int curGdotPos = 0;
Random rand = new Random ();
boolean isHitFound = false;
while ( curGdotPos < NUM_GOOD_DOTS ) {
for (int j = curGdotPos + 1; j < NUM_GOOD_DOTS; j++ ) {
if ( goodDotList [ curGdotPos ].checkForHit( NUM_GOOD_DOTS, goodDotList [ j ] ) ) {
goodDotList[curGdotPos].setGoodDotX( (rand.nextInt(3) + 1) * blockSize ) ;
goodDotList[curGdotPos].setGoodDotY( ( rand.nextInt(3) + 1) * blockSize );
isHitFound = true;
break;
}
}//END INNER FOR LOOP
if ( isHitFound ) {
curGdotPos = 0;
isHitFound = false;//reset for next round
}
else
curGdotPos++;
}//END WHILE LOOP
}//END METHOD: assignProperPosnForGoodDots
#Override
public void run() {
if (curPos < NUM_GOOD_DOTS) {
Log.i("hi", "hi, more g. dots to light up!");
gameView.update();
gameView.drawSomething();
}
if ( curPos < NUM_GOOD_DOTS ) {
myHandler.postDelayed(this, 1000);
}
else {
isLightUpSequenceFinishedForCurLevel = true;
}
while ( isLightUpSequenceFinishedForCurLevel )
gameView.drawSomething( );
}
}//END INNER CLASS: GameView
/**
* BELOW are Main Activity Life Cycle Call Back methods!
*/
#Override
protected void onStop() {
super.onStop();
Log.d("onStop", "Main Activity's onStop called");
gameView.surfaceDestroyed( gameView.getHolder() );
this.finish();
}
#Override
protected void onResume() {
super.onResume();
Log.d("onResume", "Main Activity's onResume called");
gameView = new GameView(this);
setContentView(gameView);
gameView.surfaceCreated( gameView.getHolder() );
}
#Override
protected void onPause() {
super.onPause();
Log.i("onPause", "Main Activity's onPause called");
gameView.surfaceDestroyed( gameView.getHolder() );
}
public void configureDisplay() {
//find out the width and height of the screen
Display display =
getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
//Determine the size of each block/place on the game board
blockSize = screenWidth/10;
//Determine how many game blocks will fit into the
//height and width
//Leave one block for the score at the top
numBlocksWide = 10;
numBlocksHigh = ( ( screenHeight ) ) / blockSize;
//Load and scale bitmaps
restBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.good_dot_rest_state );
awakeBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.good_dot_light_up_state );
//scale the bitmaps to match the block size
restBitmap = Bitmap.createScaledBitmap( restBitmap,
blockSize , blockSize , false);
awakeBitmap = Bitmap.createScaledBitmap( awakeBitmap,
blockSize , blockSize , false);
goodDotList = new GoodDot[ NUM_GOOD_DOTS ];
//initialize g. dots w coordinate (0,0)
for ( int i = 0; i < NUM_GOOD_DOTS; i++ )
goodDotList [ i ] = new GoodDot( 0, 0, restBitmap );
}//END METHOD: configureDisplay
}//END CLASS: MainActivity
Silly of me, the reason my bitmaps weren't changing from rest smiley face bitmap to awake smiley face bitmap back to rest smiley face bitmap was because in my bitmap class my setter was redundant as in: public void setBitmap (Bitmap bmp_) {
this.bmp = this.bmp;}...should be: this.bmp = bmp_!
I'm trying to draw some shapes but when i load the app there is just a black screen. I've checked the logcat and it says that the output is to much and that the main thread may be working to hard. how do i deal with this. whenn my app first runs the logcat prints what i want but after a while it just prints called unimplemented OpenGL ES API over and over again. How to stop main thread from working so hard.
#Override
public void onDrawFrame(final GL10 gl) {
// Clears the screen and depth buffer.
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();//replace the current matrix with the identity matrix
main.runOnUiThread(new Runnable() {
public void run() {
Random r = new Random();
if(System.currentTimeMillis() >= (now+delay)){
if(starAdded < starTotal) {
if ((r.nextInt() % 2) == 0) {
star[starAdded] = new Star();
starAdded++;
Log.i("MyGLRenderer", "3 star added");
}
else {
star[starAdded] = new fourStar();
starAdded++;
Log.i("MyGLRenderer", "4 star added");
}
now = System.currentTimeMillis();
}
}
for(int a = 0; a < starAdded; a++) {
star[a].draw(gl);
}}});
}
Use a game thread.. e.g
public class GameThread extends Thread{
private static int MAX_FRAME_SKIPS;
private static int FRAME_PERIOD;
private final Game game;
private final GameViewRenderer gameView;
private boolean gameRunning = true;
private boolean running = false;
Handler handler = new Handler();
public GameThread(Game game, GameViewRenderer gameView, int maxFPS, int maxFrameSkips) {
this.game = game;
this.gameView = gameView;
MAX_FRAME_SKIPS = maxFrameSkips;
FRAME_PERIOD = 1000 / maxFPS;
}
#Override
public void run() {
long beginTime;
long timeDiff;
int sleepTime;
int framesSkipped;
beginTime = System.currentTimeMillis();
framesSkipped = 0;
gameRunning = game.isRunning();
game.updateState(); // Update game
gameView.postInvalidate(); // Render the game
timeDiff = System.currentTimeMillis() - beginTime; // Calculate cycle length
sleepTime = (int)(FRAME_PERIOD - timeDiff); // Calculate time available to sleep
// Checks if got time to sleep, either sleeps thread or catches up
if (sleepTime > 0) {
if(gameRunning && running){
handler.postDelayed(this, sleepTime);
}
while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
game.updateState(); // Update without rendering
sleepTime += FRAME_PERIOD; // Add frame period to check if in next frame
framesSkipped++;
if(gameRunning && running) {
this.run(); // No time to wait! RUN! CATCH UP!
}
}
}
}
public void setRunning(boolean running) {
this.running = running;
}
}
Or decrease the fps
I am making an Android Game in which i am only getting in and around 20 FPS. This is the Thread Class i am using:
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 PlayView playView;
// flag to hold game state
private boolean running;
public void setRunning(boolean running)
{
this.running = running;
}
public MainThread(SurfaceHolder surfaceHolder, PlayView playView)
{
super();
this.surfaceHolder = surfaceHolder;
this.playView = playView;
}
#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.playView.update();
// render state to the screen
// draws the canvas on the panel
this.playView.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.playView.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
}
}
private void storeStats()
{
frameCountPerStatCycle++;
totalFrameCount++;
// 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));
playView.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");
}
}
Despite my best efforts to improve the FPS, it is not improving. All suggestion for optimizing this code are welcome.
i have a problem running my app using an external Thread for game loop in OpenGL ES 2.0.
here is my onCreate in my Starting class:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new MyGLView(this);
System.out.println(running);
setContentView(mGLView);
loop = new GameLoop();
//loop.run(); <- this is supposed to run the loop but when its called,
// nothing really appears on screen. just title of the app.
}
my GameLoop Class
private final static int maxFPS = 30;
private final static int maxFrameSkips = 5;
private final static int framePeriod = 1000 / maxFPS;
public static boolean running;
public final static String TAG = "test";
public GameLoop() {
}
#Override
public void run() {
running = StartPoint.isRunning();
long beginTime;
long timeDiff;
int sleepTime;
int framesSkipped;
sleepTime = 0;
while (running) {
running = StartPoint.isRunning();
beginTime = System.currentTimeMillis();
framesSkipped = 0;
StartPoint.mGLView.requestRender(); // <- supposed to re-render?
timeDiff = System.currentTimeMillis() - beginTime;
sleepTime = (int) (framePeriod - timeDiff);
if (sleepTime > 0) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
}
}
while (sleepTime < 0 && framesSkipped < maxFrameSkips) {
sleepTime += framePeriod;
framesSkipped++;
Log.d(TAG, "Frames Skipped");
}
}
}
and finally my renderer class:
private static final String TAG = "Renderer";
BoundsSquare square;
private final float[] mMVPMatrix = new float[16];
private final float[] mProjMatrix = new float[16];
private final float[] mVMatrix = new float[16];
private final float[] mRotationMatrix = new float[16];
private int camWidth,camHeight;
Camera2D cam;
Vector3 vec;
public long cycle = 0; // used this to determine how many cycles
//went through, it is stuck on cycle 0, nothing else happens after first render
#Override
public void onDrawFrame(GL10 nope) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
//set camera position
cam.setFrustum(mProjMatrix, mVMatrix, mMVPMatrix);
square.draw(mMVPMatrix);
//square.animate(tick);
//square.setBounds(vec);
System.out.println("Cycle " + cycle + " Ended");
cycle++;
}
#Override
public void onSurfaceChanged(GL10 nope, int width, int height) {
cam.setRatio(width, height);
GLES20.glViewport(0, 0, width, height);
}
public static int loadShader(int type, String shaderCode) {
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
#Override
public void onSurfaceCreated(GL10 gl,
javax.microedition.khronos.egl.EGLConfig config) {
GLES20.glClearColor(0.0f, 0.0f, 1.0f, 0.5f);
camWidth=480;camHeight=320;
cam= new Camera2D(0, 0, camHeight, camWidth);
// initialize a square
vec = new Vector3 (10,10,40,90);
square = new BoundsSquare(vec);
System.out.println("Surface Created");
}
so basically what happens is that if i do not call loop.run(); i get a static picture, which is basically one cycle of onDrawFrame, after its done with this, nothing else pops up on the logCat.
the next thing that happens is if i do call loop.run(), basically the loop goes through forever and everything, but, nothing appears on the screen. i just see a title screen, not the glView.
What am i doing wrong? Is there another way to update the Screen?
Threads must be started with start() not run().
I have a third party framework that shows video on a SurfaceView. I would like to measure the framerate of the video to check if the phone is capable of showing the video fast enough, or if I need to use another solution to show the information to the user.
How can I measure the speed with that a SurfaceView is updated?
If the code is not clear just ask.
LinkedList<Long> times = new LinkedList<Long>(){{
add(System.nanoTime());
}};
#Override
protected void onDraw(Canvas canvas) {
double fps = fps();
// ...
super.onDraw(canvas);
}
private final int MAX_SIZE = 100;
private final double NANOS = 1000000000.0;
/** Calculates and returns frames per second */
private double fps() {
long lastTime = System.nanoTime();
double difference = (lastTime - times.getFirst()) / NANOS;
times.addLast(lastTime);
int size = times.size();
if (size > MAX_SIZE) {
times.removeFirst();
}
return difference > 0 ? times.size() / difference : 0.0;
}
try this!
private long mLastTime = 0;
private int fps = 0, ifps = 0;
#Override
protected void onDraw(Canvas canvas) {
long now = System.currentTimeMillis();
// perform other operations
System.out.println("FPS:" + fps);
ifps++;
if(now > (mLastTime + 1000)) {
mLastTime = now;
fps = ifps;
ifps = 0;
}
}