How To Fix Flickering In SpriteGame

In this example we will try to fic flickering issue which comes in our previous example “ SpriteGame”. If you try the code you can note that the screen seem to flicker between two bitmap! It’s due to double buffer of Android’s SurfaceView. In order to solve the problem, we can draw on a single bitmap, then draw the bitmap on canvas.

Algorithm:

1.) Create a new project by File-> New -> Android Project name it FixFlickeringINSpriteExample.

2.) Write following into main.xml:

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello" />
<com.example.fixflickeringinspriteexample.GameSurface
android:id="@+id/myview1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>

 

 

3.) Create and write following into GameThread.java:

 

package com.example.fixflickeringinspriteexample;

public class GameThread extends Thread {

volatile boolean running = false;

GameSurface parent;
long sleepTime;

GameThread(GameSurface sv, long st){
super();
parent = sv;
sleepTime = st;
}

public void setRunning(boolean r){
running = r;
}

@Override
public void run() {
// TODO Auto-generated method stub
while(running){

try {
sleep(sleepTime);
parent.updateSurfaceView();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}

 

 

4.) Create and write following into GameSurface.java:

 

package com.example.fixflickeringinspriteexample;

import java.util.Random;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameSurface extends SurfaceView implements SurfaceHolder.Callback{

SurfaceHolder surfaceHolder;

GameThread myGameThread = null;

int myCanvas_w, myCanvas_h;
Bitmap myCanvasBitmap = null;
Canvas myCanvas = null;
Matrix identityMatrix;

private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
Random random;

public GameSurface(Context context) {
super(context);
// TODO Auto-generated constructor stub
}

public GameSurface(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}

public GameSurface(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {

myCanvas_w = getWidth();
myCanvas_h = getHeight();
myCanvasBitmap = Bitmap.createBitmap(myCanvas_w, myCanvas_h, Bitmap.Config.ARGB_8888);
myCanvas = new Canvas();
myCanvas.setBitmap(myCanvasBitmap);

identityMatrix = new Matrix();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub

}

public void MyGameSurfaceView_OnResume(){

random = new Random();
surfaceHolder = getHolder();
getHolder().addCallback(this);

//Create and start background Thread
myGameThread = new GameThread(this, 200);
myGameThread.setRunning(true);
myGameThread.start();

}

public void MyGameSurfaceView_OnPause(){
//Kill the background Thread
boolean retry = true;
myGameThread.setRunning(false);

while(retry){
try {
myGameThread.join();
retry = false;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

@Override
protected void onDraw(Canvas canvas) {

paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);

//int w = myCanvas.getWidth();
//int h = myCanvas.getHeight();
int x = random.nextInt(myCanvas_w-1);
int y = random.nextInt(myCanvas_h-1);
int r = random.nextInt(255);
int g = random.nextInt(255);
int b = random.nextInt(255);

paint.setColor(0xff000000 + (r << 16) + (g << 8) + b);
myCanvas.drawPoint(x, y, paint);

canvas.drawBitmap(myCanvasBitmap, identityMatrix, null);

}

public void updateStates(){
//Dummy method() to handle the States
}

public void updateSurfaceView(){
//The function run in background thread, not ui thread.

Canvas canvas = null;

try{
canvas = surfaceHolder.lockCanvas();

synchronized (surfaceHolder) {
updateStates();
onDraw(canvas);
}
}finally{
if(canvas != null){
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}

 

5.) Write following permissions to your manifest

 

<activity android:name=".GameSurface" ></activity>
<activity android:name=".GameThread" ></activity>

 

 

6.) Run for output.

Steps:

1.) Create a project named FixFlickeringINSpriteExample and set the information as stated in the image.

Build Target: Android 4.4
Application Name: FixFlickeringINSpriteExample
Package Name: com.example.FixFlickeringINSpriteExample
Activity Name: FixFlickeringINSpriteExampleActivity

flickering1

2.) Open FixFlickeringINSpriteExampleActivity.java file and write following code there:

 

package com.example.fixflickeringinspriteexample;

import android.app.Activity;
import android.os.Bundle;

public class FixFlickeringINSpriteExampleActivity extends Activity {

GameSurface myGameSurfaceView1;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
myGameSurfaceView1 = (GameSurface)findViewById(R.id.myview1);

}

@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
myGameSurfaceView1.MyGameSurfaceView_OnResume();
}

@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
myGameSurfaceView1.MyGameSurfaceView_OnPause();
}
}

 

 

3.) Compile and build the project.

Output

flickering2