在Android上扩展问题 - 为什么图片如此笨拙?

时间:2016-09-04 13:27:16

标签: android 2d game-development

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

enter image description here

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

enter image description here

当我从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的评论,我意识到Paint非常重要。看图片上的差异:

enter image description here

我在3,2“AVD图像上运行了演示应用程序。图片278x786缩放到107x303。

十月更新

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

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

2 个答案:

答案 0 :(得分:1)

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

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

你可以在网上找到更多优化的尺寸转换器..但实际上我最终使用的最佳解决方案是:

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

的优点:

  • 质量最好
  • 有效尺寸
  • 易于编辑

缺点:

  • 并非所有元素都受支持。

或者

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

的优点:

  • 质量好

缺点:

  • 可能导致性能问题

我希望这可能有所帮助,'。

答案 1 :(得分:1)

  

他们使用矢量吗?

SVG / Vector 是一个方便的解决方案,但矢量艺术需要极高的精度,使其不适合许多艺术风格。它很容易使用基本形状的矢量艺术,但很难添加使用SVG符号样式的简单细节虽然可以使用png,jpeg的颜色轻松添加。您可以在SVG上观看性能模式视频,其中googlers建议SVG进行图标设计。大多数游戏都不会将其用于丰富而复杂的图像。

所以我不会去SVG,尤其是那些小细节在游戏中很重要的地方。

  

他们是如何实施的?有一些技巧吗?

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

  2. 您可以使用DisplayMetrics根据手机密度要求,在运行时使用更高密度的图像并缩小图像。理想情况下,您应该保持相同的宽高比。为4制作的游戏: 3显示在16:9看起来很可怕,但16:10适合16:10,没有人注意到。read for more

  3. 您可以使用这种方式轻松获取屏幕的高度和宽度(考虑到您使用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通道有一点问题,但对于图像尺寸压缩来说太好了)

    3. 结论:使用 OpenGL,SurfaceView,NDK 实现最佳实践,并使用缩放因子docs link 有效加载图像,并且也应该尝试这样做。

      您还可以查看9patch图像,您可以在其中放置约束来缩放图像的某些部分而不是整体。这非常有用。

      更新:根据建议,如果您要使用更高分辨率的图像,则also look into thisthis禁用缩放或手动计算缩放系数。祝你好运

      注意:如果您愿意,可以随时使用有效信息编辑此答案。