Android:Canvas Spaceship 2D游戏中的严重LAG,需要提高FPS,但如何?

时间:2013-07-30 22:46:03

标签: android opengl-es andengine android-canvas surfaceview

我是Android编程的近乎初学者,我目前正在画布上制作太空飞船游戏,你可以用手指移动宇宙飞船以避开迎面而来的小行星。

现在,我已经在Canvas上编写了整个代码,在Surface-View上是具体的。

有四张照片,我的游戏似乎严重滞后......

那么在我的画布上是否有某种方法来改善每秒帧数,或者我必须使用OpenGL或某些引擎来做到这一点。

下面是我的长代码,如果你看到任何改进FPS(每秒帧数)的方法,请告诉我代码 感谢

package com.zunairgames.zunair;

import java.util.Random;

import android.app.Activity;
import android.content.Context;
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.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);
    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;
    int screenHeight;
    int screenWidth;

Random random = new Random ();
boolean loadStuff = false;

int posX=0;
int posY=0;
int posWidth=100;
int posHeight=100;


int numStars=4;
int starX[]=new int[numStars];
int starY[]=new int[numStars];
int starSpeed[]=new int[numStars];


int score=0;
int backgroundY=0;


Bitmap spaceship;
Bitmap background;
Bitmap starPic;


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 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 newHeight, int newWidth) {
    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();

         if(loadStuff==false){
                for (int i=0; i <numStars; i++){
                    starY[i]=-random.nextInt(200);
                    starX[i]=random.nextInt(canvas.getWidth()-50);
                    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.tile);

                     backgroundY=-(canvas.getHeight());

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


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

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

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

            if(x+posWidth>starX[i]&&x<starX[i]+50 && y+posHeight>starY[i]&&y<starY[i]+50){
                starY[i]=-random.nextInt(200);
                starX[i]=random.nextInt(canvas.getWidth()-50);
                starSpeed[i]=1+random.nextInt(10);
                score++;
            }
        }

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

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

        }
        canvas.drawText("SCORE : "+ score ,(canvas.getWidth()/2) -80, 100, paint);





        canvas.drawBitmap(getResizedBitmap(spaceship,100,100), x,y, null);


        ourHolder.unlockCanvasAndPost(canvas);

    //72
    }

2 个答案:

答案 0 :(得分:2)

您正在做的最大的性能错误是:

 getResizedBitmap//This code is creating a new bitmap every time...

你实际上是在每个渲染周期中创建一个新的位图,所有这些创建都在UI线程中运行,因此,如果战舰和starPic始终相同,则不要尝试尽可能多地创建位图,创建在onCreate或“初始化”功能期间,位图一次,保留该位图的引用并使用方法:

canvas.drawBitmap(bitmap, sourceBitmapRect, trasnlateRect, paint);

您可以重复使用现有的位图,并在屏幕上以任何您想要的位置绘制它, 这将大大提高性能,你不需要使用OpenGL进行简单的渲染游戏,我已经使用这种技术开发了几个安静复杂的渲染游戏,并且只要你非常小心对象创建和资源释放,它就会非常完美。 ..

希望有所帮助

问候!

答案 1 :(得分:0)

请勿在主循环中调用getResizedBitmap。您正在每帧创建和缩放新的位图。