问题
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