【问题标题】:How to avoid outOfMemory Error on a bitmap without reducing the resolution如何在不降低分辨率的情况下避免位图上的 outOfMemory 错误
【发布时间】:2012-09-15 14:14:32
【问题描述】:
我正在为 android 制作这款 2d TD 游戏。在这个游戏中我的。需要怪物、塔楼等的纹理/图形。我决定保留所有图片,包括在一张图片中的所有单位攻击周期中,以及所有图片,包括在单位步行循环在另一个。
问题是我有很多不同的单位。这导致如果我希望每个怪物纹理具有 100x100 像素的分辨率,则行走位图最终将成为 7000x15000 像素的图片。这个ofc。使我的应用程序崩溃,但同时我需要该图片中的所有内容,并且我不想降低分辨率。如何在不耗尽内存的情况下使用这些图片?或者我是否需要以其他方式组织我的图形 - 如果需要,如果您能告诉我如何进行,我将不胜感激。
【问题讨论】:
标签:
android
bitmap
out-of-memory
【解决方案1】:
稍微计算一下:您的位图有 7000x15000 像素,即 105000000 像素。对于每个像素,您需要 3 或 4 个字节(取决于您是否具有透明度)。假设您使用透明度,这是每个像素 4 个字节,所以总共是 420000000 个字节。 400 MB。
因此,您肯定要重新组织设置。
【解决方案2】:
您确定要使用全部 10000 张图片吗?大多数游戏的完整精灵表通常在数百或数千以下范围内。在 640x480 的屏幕中,您只能放置 24 个不同的字符而不会重叠,在一个屏幕上放置太多相同大小的不同字符可能会太混乱。
您可以采取一些措施来减小 spritesheet 的大小,即降低 sprite 的帧速率,以便使用相同的 sprite 图像渲染多个连续的游戏帧。许多较旧的游戏使用6-8 frames 进行运行循环,它们看起来很棒。更简单的小兵甚至可以切割更多,并且只使用 3-4 张图像。
您可以做的另一件事是更智能的角色和关卡设计,这样您实际上就不需要同时需要所有角色。将每个不同的角色放在他们自己的文件中,您可以根据特定级别的需要加载它们。您还可以重用具有不同颜色的精灵来指示另一个精灵的更强版本,重新着色的精灵实际上并不作为单独的字符存在于精灵表中,而是在运行时组合而成。如果你的角色有可见的装备,你也不需要每个组合都有一个精灵,而是在运行时将装备精灵组合成角色图像。
您还可以降低精灵的颜色深度,大多数手机支持渲染 RGB565 像素格式,并且在许多情况下,使用完整的 RGB888 可能比您实际需要的颜色更多。
此外,对于 DPI 较低的手机(通常功率也较低),您应该使用较低分辨率的图像。在这些手机中,您的 100x100 精灵看起来会非常大。
此外,您可能不需要所有对象都使用 100x100 像素大小的精灵。许多对象可能会比这小得多,您可以为它们使用更小的精灵单元大小。
【解决方案3】:
正如 Lie 所建议的,您应该正确构建游戏,这样您就不需要一次使用所有资源。您当前的内存要求太多了。您可以对位图使用 RGB565 配置,也可以对图像进行二次采样。仅仅降低帧速率是行不通的,因为当前每帧的内存需求非常大。
对于图像资源的子采样,您可以使用以下代码示例:
BitmapFactory.Options boundsOp = new BitmapFactory.Options();
boundsOp.inJustDecodeBounds = true;
BitmapFactory.decodeFile(pathToFile, boundsOp);
if(boundsOp.outWidth == -1)
{
Log.i("Error", "error");
}
int width = boundsOp.outWidth;
int height = boundsOp.outHeight;
int inSampleSize = 1;
int temp = Math.max(width, height);
while(temp > MAX_WIDTH)
{
inSampleSize *= 2;
temp /= 2;
}
BitmapFactory.Options resample = new BitmapFactory.Options();
// RGB 565 configuration
resample.inPreferredConfig = Config.RGB_565;
resample.inSampleSize = inSampleSize;
//bmp = BitmapFactory.decodeFile(pathToFile, resample);
bmp = BitmapFactory.decodeFile(pathToFile);
bmp = Bitmap.createScaledBitmap(bmp, MAX_WIDTH, MAX_HEIGHT, true);
- 除了所有这些之外,您还需要在使用时回收位图
不使用它们。