4

I'm working on a 2D game on Android / Java. During each frame, I use a fixed size Back Buffer bitmap (1024x768) to draw all the game's assets (background, sprites, ...).

Then at the end of the onDraw(), I draw this back buffer on the screen with the right size :

Rect Source = new Rect(0, 0, 1024, 768);
Rect Dest = new Rect(0, 0, m_ScreenWidth, m_ScreenHeight);
canvas.drawBitmap(BackBufferBitmap, Source, Dest, null);

The problem is that when I use this engine to just draw a simple 1024x768 image on the screen (the simplest I can do), the operation takes between 35 and 40 milliseconds on a LG G4 phone (i.e. approx 25fps). Is it possible to get a better fps with another way of managing 2D graphics?

I turn on hardware acceleration, thread's max priority. I don't have this problem on phones with lower pixel count. I guess my problem is linked to the high number of pixels on a LG G4 (2560x1440). Is it possible to do the drawing faster? Or, otherwise, is it possible to just run my game on such high-definition devices with a lower definition (like we do on PC)?

EDIT : here is the full code :

1) my View

public class ElementaryView extends SurfaceView implements SurfaceHolder.Callback
{
private ElementaryThread    m_Thread;
private SurfaceHolder       m_Holder;
private Bitmap      m_SimpleBitmap=null;
private Bitmap      m_BackBuffer =null;
private Canvas      m_BackBufferCanvas =null;

public ElementaryView(Context context)
    {
    super (context);
    m_Holder =getHolder();
    m_Holder.addCallback(this);
    setFocusable(true);
    }

@Override
public void surfaceCreated(SurfaceHolder holder) 
    {
    m_Thread =new ElementaryThread(m_Holder,this);
    m_Thread.setPriority(Thread.MAX_PRIORITY);

    m_BackBuffer =Bitmap.createBitmap(1024,768,Config.ARGB_8888);
    m_BackBufferCanvas =new Canvas(m_BackBuffer);
    m_SimpleBitmap =BitmapFactory.decodeResource(this.getResources(), R.drawable.splashscreen); 
    //"splashscreen" is a 1024x768 jpg image

    m_Thread.setRunning(true);
    m_Thread.start();
    }
@Override
protected void onDraw(Canvas canvas) 
    {
    m_BackBufferCanvas.drawBitmap(m_SimpleBitmap, 0,  0, null);

    Rect Source =new Rect(0,0,1024,768);
    Rect Dest =new Rect(0,0,this.getWidth(),this.getHeight());

    canvas.drawBitmap(m_BackBuffer,Source,Dest,null);
    }
}

2) my thread :

public class ElementaryThread extends Thread
{
private SurfaceHolder   m_SurfaceHolder;
private ElementaryView  m_View;
private boolean         m_Running;

public ElementaryThread(SurfaceHolder sh, ElementaryView view)
    {
    super();
    m_SurfaceHolder = sh;
    m_View = view;
    }

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

@SuppressLint("WrongCall") @Override
public void run() 
    {
    Canvas canvas;

    while (m_Running)
        {
        canvas =null;
        try
            {
            canvas =this.m_SurfaceHolder.lockCanvas();
            this.m_View.onDraw(canvas);
            }
        finally
            {
            if (canvas!=null)   m_SurfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}

And this gives a frame rate lower than 30fps on a LG G4. Yet, a lot of 2D games run with a better fps on my G4. Does anybody knows how they do that ?

JP Depotte
  • 41
  • 2

2 Answers2

0

By default, the LG G4 will always run at a res. of 2560x1440, which of course is going to make it difficult for the phone to render any graphics. This is also why the lesser res. phones will run much more smoothly. So, the only solution to this problem would be to change the resolution dependent on the number of pixels and processing power of the device.

0

First, for this (for games) is better to use SurfaceView

Second, show the method onDraw entirely. Most likely, you have a resource-intensive operation there. (scale etc.)

I have onDraw takes about 3ms with a similar task.

I'm not sure that you are properly working. What do you want? "this.m_View.onDraw(canvas);"

Remove

@Override
protected void onDraw(Canvas canvas)

From ElementaryView

And move code into Thread. Something like this:

@SuppressLint("WrongCall") @Override
public void run() 
    {
    Canvas canvas;

    while (m_Running)
        {
        canvas =null;
        try
            {
            canvas =this.m_SurfaceHolder.lockCanvas();
            Rect Source =new Rect(0,0,1024,768);
            Rect Dest =new Rect(0,0,m_View.getWidth(),m_View.getHeight());

            canvas.drawBitmap(m_SimpleBitmap, 0,  0, null);
            canvas.drawBitmap(m_BackBuffer,Source,Dest,null);
            }
        finally
            {
            if (canvas!=null)   m_SurfaceHolder.unlockCanvasAndPost(canvas);
            }
        }
    }
}
user2413972
  • 1,355
  • 2
  • 9
  • 25