ANDROID: How to eliminate lag and improve FPS in Android Canvas SurfaceView?

老子叫甜甜 提交于 2019-12-13 05:19:45

问题


I am a near beginner android programmer, and i have made a simple 2D spaceship game in surfaceView class where you can control the spacehip with your finger and you have dodge oncoming objects.

However, now that i am using a lot of bitmaps my game seems to be lagging a bit.

So i was wondering is there a way to destroy/garbage pictures after you use them, so they don't create so much lag. (because i think, the pictures are creating the lag)

Please tell me another simple way to make my game smoother without lags, and please tell me something related to canvas, since i want to stay with android canvas, not with an engine or OpenGL

Thanks A LOT

below is my long code if you want to check it out....

package com.zunairgames.zunair;

import java.util.Random;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager;

public class GFXSurface extends Activity implements OnTouchListener
{

MyBringBackSurface ourSurfaceView;
float x, y;
boolean testingFinger = false;
@ Override
    protected void onCreate (Bundle savedInstanceState)
{
    // TODO Auto-generated method stub
    super.onCreate (savedInstanceState);
    ourSurfaceView = new MyBringBackSurface (this);
    ourSurfaceView.setOnTouchListener (this);
    x = 0;
    y = 0;

    requestWindowFeature (Window.FEATURE_NO_TITLE);
    getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);     /////////////////////////////////////////////////CHECK THIS MIGHT NOT WORK
    setContentView (ourSurfaceView); //ourSurfaceView
}


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


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


public boolean onTouch (View v, MotionEvent event)
{
    // TODO Auto-generated method stub

    x = event.getX ();
    y = event.getY ();

    if (event.getAction () == MotionEvent.ACTION_DOWN)
    {
        testingFinger = true;
        return true;
    }
    if (event.getAction () == MotionEvent.ACTION_UP)
    {
        testingFinger = false;
        return false;
    }



    return false;
}


public class MyBringBackSurface extends SurfaceView implements Runnable
{
    //vertical
    SurfaceHolder ourHolder;
    Canvas canvas = (Canvas) ourHolder;
    Thread ourThread = null;
    boolean isRunning = false;

    DisplayMetrics metrics = new DisplayMetrics ();
    // getWindowManager().getDefaultDisplay().getMetrics(metrics);
    int screenWidth = metrics.widthPixels;
    int screenHeight = metrics.heightPixels;

    int scrWidth = getWindowManager ().getDefaultDisplay ().getWidth ();
    int scrHeight = getWindowManager ().getDefaultDisplay ().getHeight ();
    int scrRes = getWindowManager ().getDefaultDisplay ().getPixelFormat ();
    Random random = new Random ();

    boolean loadStuffPlayGame = false;
    boolean loadStuffMenu = false;


    boolean onGame = false;
    boolean onMenu = true;
    boolean onInstruction = false;



    int shipX = 0;
    int shipY = 0;
    int shipWidth = 0;
    int shipHeight = 0;


    int numStars = 4;
    int starX[] = new int [numStars];
    int starY[] = new int [numStars];
    int starWidth = 0;
    int starHeight = 0;
    int starSpeed[] = new int [numStars];


    int score = 0;
    int backgroundY = 0;

    Bitmap menuScreenBackground;
    Bitmap playGameButton;
    Bitmap instructionButton;
    //playGamePictures////
    Bitmap spaceship;
    Bitmap background;
    Bitmap starPic;
    ///end of playGame Pics//

    public MyBringBackSurface (Context context)
    {
        // TODO Auto-generated constructor stub
        super (context);
        ourHolder = getHolder ();


    }

    public void pause ()
    {
        isRunning = false;
        while (true)
        {
            try
            {
                ourThread.join ();
            }
            catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace ();
            }
            break;
        }
        ourThread = null;
    }
    public void resume ()
    {
        isRunning = true;
        ourThread = new Thread (this);
        ourThread.start ();
    }

    public int dpToPx (int dp)
    {
        DisplayMetrics displayMetrics = getContext ().getResources ().getDisplayMetrics ();
        int px = Math.round (dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
        return px;
    }

    public int round (double d)
    {
        double dAbs = Math.abs (d);
        int i = (int) dAbs;
        double result = dAbs - (double) i;
        if (result < 0.5)
        {
            return d < 0 ? -i:
            i;
        }
        else
        {
            return d < 0 ? -(i + 1):
            i + 1;
        }
    }

    public Bitmap getResizedBitmap (Bitmap bm, int newWidth, int newHeight)
    {
        int width = bm.getWidth ();

        int height = bm.getHeight ();

        float scaleWidth = ((float) newWidth) / width;

        float scaleHeight = ((float) newHeight) / height;

        // create a matrix for the manipulation

        Matrix matrix = new Matrix ();

        // resize the bit map
        matrix.postScale (scaleWidth, scaleHeight);
        // recreate the new Bitmap

        Bitmap resizedBitmap = Bitmap.createBitmap (bm, 0, 0, width, height, matrix, false);

        return resizedBitmap;

    }

    public void run ()
    {
        // TODO Auto-generated method stub


        while (isRunning)
        {

            if (!ourHolder.getSurface ().isValid ())
                continue;

            canvas = ourHolder.lockCanvas ();

            Paint paint = new Paint ();
            paint.setColor (Color.GREEN);
            paint.setTextSize (45);


            if (onMenu == true)
            {

                if (loadStuffMenu == false)
                {
                    menuScreenBackground = BitmapFactory.decodeResource (getResources (), R.drawable.menuscreen);
                    playGameButton = BitmapFactory.decodeResource (getResources (), R.drawable.menuplaygame);
                    instructionButton = BitmapFactory.decodeResource (getResources (), R.drawable.menuinstruction);

                    menuScreenBackground = getResizedBitmap (menuScreenBackground, canvas.getWidth (), canvas.getHeight ());
                    playGameButton = getResizedBitmap (playGameButton, round (canvas.getWidth () / 1.3), canvas.getHeight () / 8);
                    instructionButton = getResizedBitmap (instructionButton, round (canvas.getWidth () / 1.3), canvas.getHeight () / 8);
                    loadStuffMenu = true;
                }
                canvas.drawARGB (23, 3, 4, 4);

                canvas.drawBitmap (menuScreenBackground, 0, 0, null);

                paint.setTextSize (20);
                paint.setColor (Color.WHITE);
                canvas.drawText ("By: Zunair Syed", round (canvas.getWidth () / 1.5), round (canvas.getHeight () / 1.05), paint);





                if (x > dpToPx (15) && x < dpToPx (305) && y > dpToPx (190) && y < dpToPx (250))
                {
                    onMenu = false;
                    onGame = true;
                }

                else if (x > dpToPx (15) && x < dpToPx (305) && y > dpToPx (270) && y < dpToPx (335))
                {
                    paint.setColor (Color.BLUE);
                    canvas.drawCircle (20, 50, 100, paint);
                }

                else if (x > dpToPx (17) && x < dpToPx (305) && y > dpToPx (355) && y < dpToPx (420))
                {
                    paint.setColor (Color.GREEN);
                    canvas.drawCircle (20, 50, 100, paint);
                }


            }
            else if (onGame == true)
            {
                shipX = round (x) - (round (shipWidth / 2));
                shipY = round (y) - (round (shipHeight / 2));


                if (loadStuffPlayGame == false)
                {
                    shipX = round (canvas.getWidth () / 2);
                    shipY = round (canvas.getHeight () / 2);

                    shipWidth = canvas.getWidth () / 5;
                    shipHeight = canvas.getHeight () / 8;

                    starWidth = canvas.getWidth () / 10;
                    starHeight = canvas.getHeight () / 20;

                    for (int i = 0 ; i < numStars ; i++)
                    {
                        starY [i] = -random.nextInt ((canvas.getHeight () / 4));
                        starX [i] = random.nextInt (canvas.getWidth () - (starWidth));
                        starSpeed [i] = 1 + random.nextInt (5);
                    }
                    spaceship = BitmapFactory.decodeResource (getResources (), R.drawable.spaceship);
                    background = BitmapFactory.decodeResource (getResources (), R.drawable.background);
                    starPic = BitmapFactory.decodeResource (getResources (), R.drawable.star);

                    spaceship = getResizedBitmap (spaceship, dpToPx (shipWidth), dpToPx (shipHeight));
                    background = getResizedBitmap (background, (canvas.getWidth ()), (canvas.getHeight ()) * 2);
                    starPic = getResizedBitmap (starPic, dpToPx (starWidth), dpToPx (starHeight));

                    backgroundY = -(canvas.getHeight ());

                    x = canvas.getWidth () / 2;
                    y = canvas.getHeight () / 2;
                    loadStuffPlayGame = true;
                }




                for (int i = 0 ; i < numStars ; i++)
                {
                    starY [i] += starSpeed [i];

                    if (starY [i] > canvas.getHeight ())
                    {
                        starY [i] = -random.nextInt ((canvas.getHeight () / 4));
                        starX [i] = random.nextInt (canvas.getWidth () - starWidth);
                        starSpeed [i] = starSpeed [i] + random.nextInt (2);
                    }

                    if (shipX + shipWidth > starX [i] && shipX < starX [i] + starWidth && shipY + shipHeight > starY [i] && shipY < starY [i] + starHeight)
                    {
                        starY [i] = -random.nextInt ((canvas.getHeight () / 4));
                        starX [i] = random.nextInt (canvas.getWidth () - starWidth);
                        starSpeed [i] = 1 + random.nextInt (10);
                        score++;
                    }
                }

                backgroundY++;
                if (backgroundY > -10)
                {
                    backgroundY = -canvas.getHeight ();
                }
                canvas.drawRGB (3, 120, 12);
                canvas.drawBitmap (background, 0, backgroundY, null);

                for (int i = 0 ; i < numStars ; i++)
                {
                    canvas.drawBitmap (starPic, starX [i], starY [i], null);

                }

                /*      canvas.drawText("SCORE : "+ score  + "DENSITY :"+ canvas.getDensity() +" screenWidth :"+scrWidth,0, 100, paint);
                        canvas.drawText("ScreenHight:" + scrHeight +" scrRes" + scrRes + "20 pixels ="+dpToPx(20) ,0, 150, paint);
                 */
                canvas.drawText ("SCORE :" + score, canvas.getWidth () / 2 - (canvas.getWidth () / 7), canvas.getHeight () / 80 + canvas.getHeight () / 30, paint);

                canvas.drawBitmap (spaceship, shipX, shipY, null); //1/3 of screen




            }
            else if (onInstruction == true)
            {

            }
            //72

            ourHolder.unlockCanvasAndPost (canvas);

        }
    }

}

}


回答1:


I don't see any constructors being called in loops, so I think you are ok in regards to GC.

It looks like you are rendering all the objects on the cpu. You could gain some speed by using OpenGL to do the rendering instead.

There are some of the basics of using OpenGL within Android in the Android guide.



来源:https://stackoverflow.com/questions/18066928/android-how-to-eliminate-lag-and-improve-fps-in-android-canvas-surfaceview

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!