Android上的缩放问题 – 为什么图片如此笨拙?

我没有2D图形和游戏体验。 我自学了数百个错误和数十个小时。 我从简单的装扮游戏开始。 我使用Nexus 5x进行开发,屏幕显示正常。 当我完成了一个里程碑,我试图在大联想平板电脑和小三星迷你手机上的游戏。 它看起来非常可怕。

在这里输入图像描述

一个原始的矢量PSD文件看起来很完美,PNG导出也没有任何问题。 但是,当我缩放图片时,它是颠簸。 我知道这是位图。 但是还有另一张图片在其他地方缩放,看起来很好(两张图片都是32位):

在这里输入图像描述

当我从Google Play玩一些游戏时,他们从来没有缩放问题。 他们如何实施? 他们使用矢量? 有一些窍门吗?

我把所有东西放到assets文件夹,尽管花了1 MB。 我反编译了一些apk,并没有为每个分辨率设置变体。 虽然他们很好地缩放图片。

一些源代码片段:

 protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); this.w = w; this.h = h; canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); drawCanvas = new Canvas(canvasBitmap); } protected void onDraw(Canvas canvas) { if (baseBitmap != null) { double scale = Math.min((double) w / (double) figure.getW(), (double) h / (double) figure.getH()); figure.setScaleRatio(scale); int sw = (int) (scale * figure.getW()); int x = ((w - sw) >> 1); figure.setX(x); paintDressPart(canvas, figure, figure.getMain()); if (displayedParts != null) { for (DressPart dressPart : figure.getParts()) { if (displayedParts.contains(dressPart.getId())) { paintDressPart(canvas, figure, dressPart); } } } } } private void paintDressPart(Canvas canvas, Figure figure, DressPart part) { double scale = figure.getScaleRatio(); int sh = (int) (scale * part.getH()); int sw = (int) (scale * part.getW()); int sdx = (int) (scale * part.getDestX()); int sdy = (int) (scale * part.getDestY()); scaledRect.set(figure.getX() + sdx, sdy, figure.getX() + sw + sdx, sh + sdy); Rect partRect = part.getRect(); canvas.drawBitmap(baseBitmap, partRect, scaledRect, canvasPaint); } 

如果你想自己看,我准备在GitHub上完成项目,所以你可以下载并自行运行:

https://github.com/literakl/DressUp

更新

降尺寸也很糟糕。 但是,由于Paavnet的评论,我意识到油漆很重要。 查看图片上的区别:

在这里输入图像描述

我在3,2“AVD图片上运行了演示程序。图片278×786被缩放到了107×303。

十月更新

我重写了应用程序使用资源文件夹,而不是资产。 Android缩放图片,然后我重新调整它。 虽然看起来比我不使用Android资源缩放更好。 资源缩放图片通常比未缩放的nodpi /资产图片更好。

我发现mdpi效果最好。 我甚至有xxhdpi图片,它比mdpi更糟糕。 我认为,即使在xxhdpi设备! 但画面不好的可能是一个麻烦。 Android资源缩放可能会平滑线条边缘。

我面临同样的问题..那个缩放不那么顺利..最好的标准方法

 Bitmap resized = Bitmap.createScaledBitmap(yourBitmap, newWidth, newHeight, true); 

你可以在网上找到更多的优化大小转换器..但实际上最好的解决方案我结束使用:

1。 使用矢量SVG资源..这是完美的质量100%的工作。 只要确保SVG元素与android兼容(请参阅: https : //developer.android.com/studio/write/vector-asset-studio.html )

优点:

  • 最好的质量
  • 有效的大小
  • 容易编辑

缺点:

  • 不是所有的元素都被支持。

要么

第2位。 提供高分辨率的图像(一个在xxxhdpi就足够了)

优点:

  • 高品质

缺点:

  • 可能会导致性能问题

我希望这可以帮助,'。

他们使用矢量?

SVG / Vector是一个方便的解决方案,但矢量艺术需要非常高的精度,使其不适合许多艺术风格。使用基本形状的矢量艺术很容易,但可以很难添加SVG符号风格的简单细节,虽然它可以添加很容易与png,jpeg油漆。 您可以在SVG上观看性能模式视频,其中Google提供SVG图标设计。大多数游戏不会将其用于丰富和复杂的图像。

所以我不会专门去SVG那里,小细节在游戏中很重要。

他们如何实施? 有一些窍门吗?

  1. 一种方法是只发布一个常规资产支持(MDPI,HDPI)的应用程序,如果屏幕密度要求高分辨率,然后向用户显示一个对话框,询问他是否要下载高分辨率资产。

  2. 您可以获得更高密度的图像,并在运行时根据使用DisplayMetrics手机密度要求对其进行缩放。理想情况下,您应保持相同的宽高比。适合以4:3显示的游戏适合16:9,但16:10,16:9,没有人会注意到。 阅读更多 。

您可以使用这种方式轻松获取屏幕的高度和宽度( 考虑到您正在使用SurfaceView作为最佳实践

 DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); int screenHeight = metrics.heightPixels; int screenWidth = metrics.widthPixels; 

为了获得新的旋转宽度:

surfaceChanged(SurfaceHolder holder, int format, int width, int height)

该方法给你的表面的宽度/高度,所以你现在可以使用:

 Bitmap.createScaledBitmap (Bitmap src, int dstWidth, int dstHeight, boolean filter) 

从Bitmap类中重新调整图像的大小,使其与您正在绘制的曲面的大小成比例。您可以查看一些技巧来找到合适的缩放因子。

  1. OpenGL,kotlin可以为您创造丰富的图形应用程序的优势。有了这些,你可以控制内存和GPU性能,基本上是大多数游戏的骨干,再加上你可以利用GPU and native memory space更有效地控制渲染再加上你能想到的东西还有很多,如果你不熟悉这些东西需要一些时间,但是一旦你拿到了,他们可以做很多魔术。

  2. Webp会帮助你减小大的图像的大小相当大的差异。应该尝试webp。 (建议,webp在某些设备上对图像的alpha通道有一些小问题,但对于图像大小的压缩效果太好)

结论:实现使用OpenGL,SurfaceView,NDK的最佳实践并使用比例因子文档链接有效地加载图像,也应该尝试。

你也可以看看9patch图像,你可以放置约束来缩放图像的一部分,而不是整个。这是非常有用的。

更新 :如建议,如果你打算使用更高分辨率的图像,那么也看看这个和这个禁用缩放或手动计算比例因子。好运

注意:如果你喜欢,伙计们可以随意用有效的信息编辑这个答案。

Interesting Posts