2016-02-29 22 views
9

Tôi nhận thấy rằng ứng dụng câu đố khác từ các cửa hàng google play có thể đi lên đến bao nhiêu là 400 mảnh riêng biệt di chuyển câu đốLàm cách nào để tạo một ứng dụng trò chơi trong droid mà không cần hết bộ nhớ?

Tôi đã cố gắng học hỏi làm thế nào để ít nhất có một hình ảnh sẽ đại diện cho câu đố của tôi, Crop một số phần nhất định và che dấu không gian hình ảnh còn lại với thiết kế mảnh ghép để tạo các mảnh ghép riêng lẻ của tôi

Tôi muốn tối đa 20 miếng cho ứng dụng của mình. nhà máy được thực hiện tạo ra một mảnh ghép tôi đang sử dụng lên khoảng 18MB bộ nhớ, sau 20 miếng được tạo ra cùng với tất cả các chức năng khác của ứng dụng tôi đang sử dụng lên 400 mb bộ nhớ mà tôi phải sử dụng “largeHeap = tru e ”để tránh hết bộ nhớ, nhưng tôi quá gần với những giới hạn cao hơn mà ứng dụng là siêu chậm chạp và đủ hoạt động hoạt hình chắc chắn sẽ làm hỏng ứng dụng

Tôi rất muốn biết những gì các cửa hàng chơi khác ứng dụng câu đố đang làm điều đó tôi không phải là

đầu vào bất kỳ được đánh giá rất

FYI tôi đang sử dụng PNG24 cho hình ảnh của tôi và kích thước trên hình ảnh thử nghiệm của tôi là 556x720

Dưới đây là một ví dụ nếu tôi chỉ cần tạo một hình ảnh mảnh ghép có thể hoạt hình

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);//Remove title bar 
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//Hides notification bar 
    this.setContentView(R.layout.activity_main);//set content view AFTER ABOVE sequence (to avoid crash) 

    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

    mainDisplay = getWindowManager().getDefaultDisplay(); 
    mainLayout = (ViewGroup) findViewById(R.id.id_layout); 

    DisplayMetrics m = new DisplayMetrics(); 
    this.getWindowManager().getDefaultDisplay().getMetrics(m); 
    int windowHeight = m.heightPixels; 
    int windowWidth = m.widthPixels; 

    offsetX = (windowWidth/1440.0f); 
    offsetY = (windowHeight/2560.0f); 

    ourContext = this; 

    xpos = new float[2]; 
    ypos = new float[2]; 

    iv_PuzzleOne(); 

    bkgdbm = BitmapFactory.decodeResource(getResources(), R.drawable.puzzleimage); 

    paintObject = new Paint(); 
    paintObject.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR)); 

    bm_PuzzleOne(); 

    thisTimerTask = new ThisClass(); 
    thisTimer = new Timer(); 
    thisTimer.scheduleAtFixedRate(thisTimerTask, 16, 16); 

    touchpad = new ImageButton(this); 
    SetPos(0, 0, 1440, 2560); 
    touchpad.setLayoutParams(layoutPositioner); 
    touchpad.getBackground().setAlpha(1); 
    mainLayout.addView(touchpad); 

    touchpad.setOnTouchListener(new View.OnTouchListener() { 

     //@SuppressLint("NewApi") 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 

      if (event.getAction() == MotionEvent.ACTION_DOWN) { 
       xpos[0] = event.getX(); //storing my finger's position coordinates when I first touch the screen into the 1st element 
       ypos[0] = event.getY(); 

       if ((event.getX() > imgx1) && (event.getX() < imgx1 + imagewidth1) 
         && (event.getY() > imgy1) && (event.getY() < imgy1 + imageheight1)) { 
        touching1Puzzle = true; 
        img1.bringToFront(); 
       } 

      } 

      if (event.getAction() == MotionEvent.ACTION_MOVE) { 

       xpos[1] = event.getX(); //add my finger's new current coordinates into the 2nd element 
       ypos[1] = event.getY(); 

       if (touching1Puzzle) { 
        adjustImg(); 
       } 
      } 

      if (event.getAction() == MotionEvent.ACTION_UP) { 
       if (touching1Puzzle) { 
        touching1Puzzle = false; 
       } 

      } 

      return false; 
     } 

    }); 
} 


void bm_PuzzleOne() 
{ 
    //start of 1st puzzle 

    foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15 
    mutableforegdimg1 = foregdimg1.copy(Bitmap.Config.ARGB_8888, true); //(48.32MB) +5.84 

    compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11 

    imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0 
    imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0 

    img1.setImageBitmap(compositeImage1); 

} 


void iv_PuzzleOne() 
{ 
    img1 = new ImageView(ourContext); 
    SetPos(imgx1, imgy1, imagewidth1, imageheight1); 
    //bkgdimg.setImageResource(R.drawable.c); 
    //img1.setBackgroundColor(0xffF07305); //Orange 
    img1.setLayoutParams(layoutPositioner); 
    mainLayout.addView(img1); 

} 

void adjustImg() 
{ 
    if (touching1Puzzle) 
    { 
     if (xpos[1] > xpos[0]) //if the image had slid to the right 
     { 
      xPositionDifference = xpos[1] - xpos[0]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgx1 += xPositionDifference; //add that difference to the current image position ... 

      xpos[0] += xPositionDifference; // ... store that difference for the next shift in finger postion 

     } else if (xpos[1] < xpos[0]) //if the image had slid to the left 
     { 
      xPositionDifference = xpos[0] - xpos[1]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgx1 -= xPositionDifference; //subtract that difference to the current image position ... 

      xpos[0] -= xPositionDifference; // ... store that difference for the next shift in finger postion 
     } 

     if (ypos[1] > ypos[0]) //if the image had slid to the right 
     { 
      yPositionDifference = ypos[1] - ypos[0]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgy1 += yPositionDifference; //add that difference to the current image position ... 

      ypos[0] += yPositionDifference; // ... store that difference for the next shift in finger postion 

     } else if (ypos[1] < ypos[0]) //if the image had slid to the left 
     { 
      yPositionDifference = ypos[0] - ypos[1]; // find the difference in coordinate value between where my finger was and where it currently is 
      imgy1 -= yPositionDifference; //subtract that difference to the current image position ... 

      ypos[0] -= yPositionDifference; // ... store that difference for the next shift in finger postion 

     } 
    } 

} 

class ThisClass extends TimerTask { 

    @Override 
    public void run() { 
     MainActivity.this.runOnUiThread(new Runnable() { 
      @Override 
      public void run() { 

       if(touching1Puzzle) 
       {SetPos(imgx1, imgy1, imagewidth1, imageheight1); 
        img1.setLayoutParams(layoutPositioner);} 

      } 
     }); 
    } 
} 

public void SetPos(float x, float y, float width, float height) { 
    layoutPositioner = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
    layoutPositioner.topMargin = (int) (offsetY * y); 
    layoutPositioner.leftMargin = (int) (offsetX * x); 
    layoutPositioner.width = (int) (width * offsetX); 
    layoutPositioner.height = (int) (height * offsetY); 
} 

}

Đây là những gì nó trông giống như khi tôi tải 5 hình ảnh

http://s15.postimg.org/ymqspk77v/Screenshot_2016_02_29_07_19_26.png

Trả lời

2

Đơn giản chỉ cần sử dụng vectơ thay vì hình ảnh .. bạn sẽ tiết kiệm dung lượng bộ nhớ để chạy ứng dụng và lưu trữ. Nó được hỗ trợ rất tốt. và bạn có thể sử dụng tài nguyên SVG

+0

Cảm ơn Maher, tôi chưa bao giờ sử dụng véc tơ trước và sau khi chơi với nó trong droid Tôi đang cạo một tải trọng của bộ nhớ với một mình, Nó đau tôi rằng tôi không có đủ thời gian để kiểm tra lời đề nghị của bên thứ 3 của Zeyad và Smartiz trước khi giai đoạn bounty lên [Tôi đang tung hứng 2 công việc và lập trình trong thời gian rảnh rỗi của tôi] nhưng có vẻ như họ là những giải pháp đi đúng hướng ... chiều sâu trả lời nó không phải là giải pháp cho vấn đề cụ thể của tôi – user1091368

3

Được rồi chúng ta hãy xem.

Trước hết bạn không cần mảnh ghép là lớn này, vì vậy bạn có thể mở rộng chúng xuống:

Từ http://developer.android.com/training/displaying-bitmaps/load-bitmap.html

Để nói các bộ giải mã để subsample hình ảnh, tải một nhỏ phiên bản vào bộ nhớ, đặt inSampleSize thành true trong đối tượng BitmapFactory.Options của bạn. Ví dụ: hình ảnh có độ phân giải 2048x1536 được giải mã bằng inSampleSize của 4 sẽ tạo bitmap khoảng 512x384. Tải bộ nhớ này vào bộ nhớ sử dụng 0.75MB thay vì 12MB cho hình ảnh đầy đủ (giả sử cấu hình bitmap của ARGB_8888)

Thứ hai, bạn nên thử tải Bitmap trong AsyncTask để ngăn ứng dụng bị đóng băng.

Thứ ba bạn có thể cache Bitmaps bạn sử dụng LruCache để tăng tốc

http://developer.android.com/training/displaying-bitmaps/cache-bitmap.html

private LruCache<String, Bitmap> mMemoryCache; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    ... 
    // Get max available VM memory, exceeding this amount will throw an 
    // OutOfMemory exception. Stored in kilobytes as LruCache takes an 
    // int in its constructor. 
    final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024); 

    // Use 1/8th of the available memory for this memory cache. 
    final int cacheSize = maxMemory/8; 

    mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { 
     @Override 
     protected int sizeOf(String key, Bitmap bitmap) { 
      // The cache size will be measured in kilobytes rather than 
      // number of items. 
      return bitmap.getByteCount()/1024; 
     } 
    }; 
    ... 
} 

public void addBitmapToMemoryCache(String key, Bitmap bitmap) { 
    if (getBitmapFromMemCache(key) == null) { 
     mMemoryCache.put(key, bitmap); 
    } 
} 

public Bitmap getBitmapFromMemCache(String key) { 
    return mMemoryCache.get(key); 
} 

Đó nên là đủ nhưng trong trường hợp nó không có ở đây là tất cả các nguồn và sau đó một số bổ sung: http://developer.android.com/training/displaying-bitmaps/index.html

Bạn cũng có thể thử sử dụng

void bm_PuzzleOne() 
{ 
    //start of 1st puzzle 
    BitmapFactory.Options opt = new BitmapFactory.Options(); 

    //makes a loaded image mutable 
    opt.inMutable=true; 
    //reduces density to that of screen 
    opt.inTargetDensity = this.context.getResources().getDisplayMetrics().densityDpi; 
    opt.inScaled=true; 

    //makes bitmap half as big 
    opt.inSampleSize=2; 

    //foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15 
    mutableforegdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac,opt) 

    compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11 

    imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0 
    imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0 

    img1.setImageBitmap(compositeImage1); 

} 

thay vì

void bm_PuzzleOne() 
{ 
    //start of 1st puzzle 

    foregdimg1 = BitmapFactory.decodeResource(getResources(), R.drawable.puzzlepieceprac);//puzzle cut out (42.48MB) +6.15 
    mutableforegdimg1 = foregdimg1.copy(Bitmap.Config.ARGB_8888, true); //(48.32MB) +5.84 

    compositeImage1 = Bitmap.createBitmap(mutableforegdimg1);//cuts out foreground info into bkgdimage (54.43MB) +6.11 

    imgCanvas1 = new Canvas(compositeImage1); //canvas references puzzle cut out image (54.43MB) +0 
    imgCanvas1.drawBitmap(croppedBmp, null, new Rect(0, 0, 1500, 2000), paintObject);//places puzzle image on canvas (54.43MB) +0 

    img1.setImageBitmap(compositeImage1); 

} 
+0

khi bạn nói rằng tôi không cần chúng lớn đến mức tôi cho rằng bạn đang đề cập đến bitmap được vẽ tại 1500x2000 ...Các hình ảnh được tải trước không phải là 1500x2000 Tôi buộc phải mở rộng nó đến kích thước đó chỉ để có mảnh ghép mặt nạ nhìn đúng ... kích thước của hình ảnh câu đố của tôi là 425x601 cài đặt sẵn, tôi buộc phải mở rộng kích thước của hình ảnh câu đố cho nó phù hợp với kích thước của mảnh ghép hình của tôi ... Tôi hy vọng điều này có ý nghĩa và cho biết thêm rõ ràng hơn để treo hiện tại của tôi ... Cô ấy là một ví dụ về những gì nó trông giống như ... http: //postimg.org/image/o62dgyw0t/ – user1091368

+0

Thực hiện chỉnh sửa, kiểm tra và cho tôi biết nếu nó hoạt động. Ngoài ra, bạn có sử dụng mutableforegdimg sau khi thêm nó vào compositeImage không? Nếu không, bạn nên cố gắng tái chế nó – JeD

1

Trước hết tôi nên cảm ơn @JeD cho câu trả lời tuyệt vời của mình, nhưng tôi nên đề cập đến mà tôi nghĩ rằng câu trả lời là khác nhau.

Hãy bắt đầu từ những điều cơ bản ...


Mỗi thiết bị Android có một cụ thể "kích thước heap". nó bắt đầu từ 16mg đến 64mg và thậm chí là 128mg ở một số thiết bị! (im không chắc chắn khoảng 128 mg: D)

Vì vậy, bất cứ khi nào bạn sử dụng drawable trong chế độ xem của mình, phải mất một lượng ram cụ thể.

Câu hỏi: Tính toán như thế nào?

Nó theo kích thước drawable s, không phải kích thước. Ví dụ: chúng tôi có hai số drawable s có kích thước 500 KB. Một trong số chúng có kích thước 500 * 500, cái kia có 700 * 700 Cái thứ hai có nhiều heap hơn mặc dù cả hai kích thước đều giống nhau! Công thức là: WIDTH * HEIGHT * 4 BYTE (4 đến từ ARGB, phải mất bốn byte cho mỗi pixel để lưu trữ dữ liệu)

Bây giờ, bạn nên hiểu rằng bạn không thể sử dụng nhiều hình ảnh cùng nhau! Nếu bạn muốn sử dụng LRUCACH như @JeD được đề cập, bạn sẽ mất một số hình ảnh của bạn khi vùng heap của bạn sẽ đầy.

Câu hỏi: Vậy chúng ta nên làm gì ?!

Câu trả lời đang sử dụng công cụ và canvas của bên thứ ba! Các công cụ trò chơi như COCOS2D, BOX2D, v.v ... cũng là các ví dụ tốt hoặc cũng sử dụng NDK làm cho ứng dụng của bạn MIỄN PHÍ NHƯ THẾ NÀO !!! : D

Các vấn đề liên quan