android - 内存不足 !为我的游戏使用大量位图时,位图 Vm 内存超出预算错误

标签 android canvas bitmap

    package com.anu;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.SurfaceHolder.Callback;
public class GameView extends SurfaceView {
  public static int a,y;
private Bitmap bm ,hud;
   private SurfaceHolder holder;
   private GameLoopThread gameLoopThread;

   private long lastClick;
private Bitmap bmpBlood ;
private static boolean ab=true;
Timex n = new Timex();



private List<Sprite> sprites = new ArrayList<Sprite>();
private List<Sprite> sprites2 = new ArrayList<Sprite>();
private List<Sprite> sprites3 = new ArrayList<Sprite>();
private List<Sprite> sprites4 = new ArrayList<Sprite>();
private List<Sprite> sprites5 = new ArrayList<Sprite>();
private List<Sprite> sprites6 = new ArrayList<Sprite>();

private List<TempSprite> temps = new ArrayList<TempSprite>();

       public GameView(Context context) {
         super(context);
         gameLoopThread = new GameLoopThread(this);
         holder = getHolder();
         holder.addCallback(new Callback()
           {
                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                }
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    int t2 =Timex.a;
                                      createSprites();
                                      cs2();
                                      cs3();
                                      cs4();


                                    /*  if(t2>10){
                                      cs2();}
                                      if(t2>20){
                                      cs3();}
                                      if(t2>30){
                                      cs4();}
                                      if(t2>40){
                                          cs5();
                                      }*/
                       gameLoopThread.setRunning(true);
                       gameLoopThread.start();
                       n.start();

                }
                @Override
                public void surfaceChanged(SurfaceHolder holder, int format,
                              int width, int height) {
                }
         });
         bmpBlood = BitmapFactory.decodeResource(getResources(), R.drawable.blood2);
          bm = BitmapFactory.decodeResource(getResources(), R.drawable.sky4);
          Bitmap  o = Bitmap.createScaledBitmap( bm, 800, 490, false);
          bm=o;


   }

   private void createSprites() {
       sprites.add(createSprite(R.drawable.act0));
       sprites.add(createSprite(R.drawable.act0));
       sprites.add(createSprite(R.drawable.act0));
       sprites.add(createSprite(R.drawable.act0));
       sprites.add(createSprite(R.drawable.act0));


   }

   private Sprite createSprite(int resouce) {
        Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
         return new Sprite(this, bmp);
   }
   private void cs2() {
       sprites2.add(createSprite(R.drawable.act));
       sprites2.add(createSprite(R.drawable.act));
       sprites2.add(createSprite(R.drawable.act));
       sprites2.add(createSprite(R.drawable.act));
       sprites2.add(createSprite(R.drawable.act ));
   }
   private void cs3() {
       sprites3.add(createSprite(R.drawable.act1));
       sprites3.add(createSprite(R.drawable.act1));
       sprites3.add(createSprite(R.drawable.act1));
       sprites3.add(createSprite(R.drawable.act1));
       sprites3.add(createSprite(R.drawable.act1));


   }
   private void cs4() {
       sprites4.add(createSprite(R.drawable.act2));
       sprites4.add(createSprite(R.drawable.act2));
       sprites4.add(createSprite(R.drawable.act2));
       sprites4.add(createSprite(R.drawable.act2));
       sprites4.add(createSprite(R.drawable.act2));
   }
   private void cs5() {
       sprites5.add(createSprite(R.drawable.act3));
       sprites5.add(createSprite(R.drawable.act3));
       sprites5.add(createSprite(R.drawable.act3));
       sprites5.add(createSprite(R.drawable.act3));
       sprites5.add(createSprite(R.drawable.act3));


   }
   private void cs6() {
         sprites6.add(createSprite(R.drawable.act4));
         sprites6.add(createSprite(R.drawable.act4));
         sprites6.add(createSprite(R.drawable.act4));
         sprites6.add(createSprite(R.drawable.act4));
         sprites6.add(createSprite(R.drawable.act4));
           }


   @Override
   protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.rgb(21, 181, 195));
        canvas.drawBitmap(bm, 0, 0, null);

             for (int i = temps.size() - 1; i >= 0; i--) {
             temps.get(i).onDraw(canvas);
       } 
         int tt = Timex.a;
             if(tt>0){
             for (Sprite wave2 : sprites) {
              wave2.onDraw(canvas);

              }
             if(tt>10){

             for (Sprite wave2 : sprites2) {
              wave2.onDraw(canvas);
              }
             if(tt>20){
                for (Sprite wave2 : sprites3) {
                      wave2.onDraw(canvas);
                      }
            }
             if(tt>30){
                for (Sprite wave2 : sprites4) {
                      wave2.onDraw(canvas);

                      }
                 if(tt>40){
                     for (Sprite wave2 : sprites5) {
                      wave2.onDraw(canvas);
                      }
                 }

               }

         }



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

         }
          }
             @Override
            public boolean onTouchEvent(MotionEvent event) {
           int kt=Timex.a;
           if (System.currentTimeMillis() - lastClick > 500) {
                  lastClick = System.currentTimeMillis();
             synchronized (getHolder()) {
             float x = event.getX();
                float y =event.getY();
                if(kt>0){
                   for (int i = sprites.size() - 1; i >= 0; i--) {
                        Sprite sprite = sprites.get(i);
                        if (sprite.isCollition(x, y)) {
                              sprites.remove(sprite);

                            temps.add(new TempSprite(temps, this, x, y, bmpBlood));
                              break;
                        }
                    }}
                if(kt>10){
                   for (int i = sprites2.size() - 1; i >= 0; i--) {
                       Sprite sprite = sprites2.get(i);
                       if (sprite.isCollition(x, y)) {
                             sprites2.remove(sprite);

                        temps.add(new TempSprite(temps, this, x, y, bmpBlood));
                             break;
                       }}
                   }
                if(kt>20){
                   for (int i = sprites3.size() - 1; i >= 0; i--) {
                       Sprite sprite = sprites3.get(i);
                       if (sprite.isCollition(x, y)) {
                             sprites3.remove(sprite);

                        temps.add(new TempSprite(temps, this, x, y, bmpBlood));
                             break;
                       }
                   }}
                if(kt>30)
                   for (int i = sprites4.size() - 1; i >= 0; i--) {
                       Sprite sprite = sprites4.get(i);
                       if (sprite.isCollition(x, y)) {
                             sprites4.remove(sprite);

                        temps.add(new TempSprite(temps, this, x, y, bmpBlood));
                             break;
                       }
                   }
                if(kt>40)
                       for (int i = sprites5.size() - 1; i >= 0; i--) {
                           Sprite sprite = sprites5.get(i);
                           if (sprite.isCollition(x, y)) {
                                 sprites5.remove(sprite);

                            temps.add(new TempSprite(temps, this, x, y, bmpBlood));
                                 break;
                           }
                       }
                if(kt>50)
                       for (int i = sprites6.size() - 1; i >= 0; i--) {
                           Sprite sprite = sprites6.get(i);
                           if (sprite.isCollition(x, y)) {
                                 sprites6.remove(sprite);

                            temps.add(new TempSprite(temps, this, x, y, bmpBlood));
                                 break;
                           }
                       }
                }
         }
         return true;
   }
  }

这是我的游戏代码。我在列表中获得多个 Sprite 并使用它们通过 On draw 方法在 Canvas 中显示它们游戏运行良好直到 cs4(); 在我的代码运行时..当我调用cs5(); 我收到错误提示 bitmap vm budget out of memory 。我想当我在玩游戏时摧毁 Sprite 时我可以减少预算,但我总是遇到同样的错误。我想在我的游戏中一次又一次地使用 cs2();,cs3(),cs4(),cs5() 而不会超出 vm 预算。如何通过清除内存中清除的先前位图并从该方法创建新图像并再次使用它们来使其运行..我认为缩放会有所帮助但我的位图非常小所以如果我缩放它们它们会变得非常小所以我想要使用相同大小的相同图像并在 Canvas 中一次又一次地显示 谢谢你们 !

更新 我的 Sprite 类

  package com.anu;

  import java.util.Random;

  import android.graphics.Bitmap;

  import android.graphics.Canvas;

 import android.graphics.Rect;

 public class Sprite {
  // direction = 0 up, 1 left, 2 down, 3 right,
   // animation = 3 back, 1 left, 0 front, 2 right
   int[] DIRECTION_TO_ANIMATION_MAP = { 3, 1, 0, 2 };
   private static final int BMP_ROWS = 4;
   private static final int BMP_COLUMNS = 3;
 //  private static final int MAX_SPEED = 9;
   private GameView gameView;
   private Bitmap bmp;
   private int x = 0;
   private int y = 0;
   private int xSpeed =15;
   private int ySpeed=15;
   private int currentFrame = 0;
   private int width;
   private int height;

   public Sprite(GameView gameView, Bitmap bmp) {
         this.width = bmp.getWidth() / BMP_COLUMNS;
         this.height = bmp.getHeight() / BMP_ROWS;
         this.gameView = gameView;
         this.bmp = bmp;
         Random rnd = new Random();
         x = rnd.nextInt(gameView.getWidth() - width);
         y = rnd.nextInt(gameView.getHeight() - height);
    //     xSpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
      //   ySpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
  }
   private void update() {
         if (x >= gameView.getWidth() - width - xSpeed || x + xSpeed <= 0) {
                xSpeed = -xSpeed;
         }
         x = x + xSpeed;
         if (y >= gameView.getHeight() - height - ySpeed || y + ySpeed <= 0) {
                ySpeed = -ySpeed;
         }
         y = y + ySpeed;
         currentFrame = ++currentFrame % BMP_COLUMNS;
  }

   public void onDraw(Canvas canvas) {
         update();
         int srcX = currentFrame * width;
         int srcY = getAnimationRow() * height;
         Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
         Rect dst = new Rect(x, y, x + width, y + height);
         canvas.drawBitmap(bmp, src, dst, null);
   }

   private int getAnimationRow() {
         double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
         int direction = (int) Math.round(dirDouble) % BMP_ROWS;
         return DIRECTION_TO_ANIMATION_MAP[direction];
   }

   public boolean isCollition(float x2, float y2) {
         return x2 > x && x2 < x + width && y2 > y && y2 < y + height;
   }
   }

最佳答案

以下代码是错误的,因为您在每个 cs2、cs3 等中创建了 5 次相同的位图/ Sprite 。这是错误的,也是您拥有 OOM 的原因。没有理由将相同的位图添加到列表中 5 次...

private Sprite createSprite(int resouce) {
    Bitmap bmp = BitmapFactory.decodeResource(getResources(), resouce);
     return new Sprite(this, bmp);
}
private void cs2() {
   sprites2.add(createSprite(R.drawable.act));
   sprites2.add(createSprite(R.drawable.act));
   sprites2.add(createSprite(R.drawable.act));
   sprites2.add(createSprite(R.drawable.act));
   sprites2.add(createSprite(R.drawable.act ));
}
private void cs3() {
   sprites3.add(createSprite(R.drawable.act1));
   sprites3.add(createSprite(R.drawable.act1));
   sprites3.add(createSprite(R.drawable.act1));
   sprites3.add(createSprite(R.drawable.act1));
   sprites3.add(createSprite(R.drawable.act1));
}
private void cs4() {
   sprites4.add(createSprite(R.drawable.act2));
   sprites4.add(createSprite(R.drawable.act2));
   sprites4.add(createSprite(R.drawable.act2));
   sprites4.add(createSprite(R.drawable.act2));
   sprites4.add(createSprite(R.drawable.act2));
}
private void cs5() {
   sprites5.add(createSprite(R.drawable.act3));
   sprites5.add(createSprite(R.drawable.act3));
   sprites5.add(createSprite(R.drawable.act3));
   sprites5.add(createSprite(R.drawable.act3));
   sprites5.add(createSprite(R.drawable.act3));
}
private void cs6() {
     sprites6.add(createSprite(R.drawable.act4));
     sprites6.add(createSprite(R.drawable.act4));
     sprites6.add(createSprite(R.drawable.act4));
     sprites6.add(createSprite(R.drawable.act4));
     sprites6.add(createSprite(R.drawable.act4));
}

更新

i want to create 5 enemies each time i call the function later on i send enemies in different combos

所以你应该为你的每个敌人重复使用一个(!!)可绘制对象。这意味着:创建一个将使用相同可绘制对象的敌人类。这会将每种敌人类型的使用图像减少到 1 个。

关于android - 内存不足 !为我的游戏使用大量位图时,位图 Vm 内存超出预算错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19562949/

相关文章:

c# - 控件上的透明图像

android - Android的Bitmap类的getPixels()的使用及使用方法

jquery - 有没有更好的Android webview

android - 在指定的个人资料页面上打开 Facebook 应用程序

android - 在 Android 中准备 jar 库时无法获取资源布局文件

python matplotlib Canvas 未调整大小

assembly - 位图 ASM 中的颜色特定行

Android Textview 不更新

jquery - 我需要一个方便的 jQuery 工具(插件)来处理 map

javascript - 在 html5 Canvas 中创建一个非填充弧?