【问题标题】:Run multiple animations without noticeable lag运行多个动画而没有明显的延迟
【发布时间】:2017-02-01 18:12:39
【问题描述】:

我正在开发一个简单的 2D 游戏。游戏从一个动画开始,然后玩家点击屏幕,另一个动画应该在没有明显滞后的情况下运行,同时切换到下一个动画。我的第一种方法是使用 AnimationDrawable 和 40 个 PNG [帧] 的动画列表。我想使用两个这样的 AnimationDrawables。由于android在播放动画之前加载动画的所有帧的行为,这种方法会导致OOM。然后我决定将我的单个动画分成 4 个动画,每个 10 帧。 10 帧的第一个动画运行完美,但是当我播放第二个时 [立即在第一个停止后] 我得到 OOM 并且应用程序关闭。

1) 我遇到了这个解决方案: https://stackoverflow.com/a/10993879/6699069 这看起来是我的问题的完美解决方案。但我不知道解决方案中使用的 OnAnimationStoppedListener 对象。在developers.android.com 或其他任何地方都没有关于它的信息。我想直接问 cmets 下的@Pinhassi,但无法添加评论,感谢 50 声望限制。

编辑:我找到了几乎类似的解决方案here 可以正常工作:D 但与我在 4) 中提到的滞后相同 我什至设置了 delayMillis = 0;它仍然以大约 10fps 的速度运行 [观察到]

2) 该帖子已有 5 年历史,所以我想,现在应该有一个预定义的类来使用长动画而不会导致 OOM。如果存在这样的类,请指出它的链接。

3) 一位朋友建议我使用 gif 来代替动画。但我想没有办法以编程方式停止/播放 gif。此外,40 帧的 gif 似乎是一种幻想。如果有人知道将 gif 用作动画的等价物,请遮光。

4) 我的旧方法 [当我不知道 AnimationDrawable 类时] 是使用 SurfaceView 并在画布上循环绘制 40 个位图来模拟动画。它有效,但帧速率慢得令人讨厌。当玩家点击屏幕时,它会变慢。此外,不同手机的帧速率也有很大差异。有人建议我降低图像分辨率。我将图像从 720p 缩小到 320p,但并没有太大区别。有什么方法可以用这种方法加速动画?

如果有人能回答 1) 和 2),我将不胜感激。

【问题讨论】:

  • 移至 GLSurfaceView(或 OpenGL 引擎)和/或查看使用精灵表而不是单个图像。

标签: android android-animation 2d-games animationdrawable


【解决方案1】:

您的问题非常广泛,所以我会尽力提供一些帮助(不确定它是否会给出完整的答案)。当我在 Android 中制作动画时,我会尽可能多地使用原生视图,因为性能几乎总是最好的,即使对于旧设备也是如此。如果您需要做一些更复杂的事情,也许您可​​以考虑使用Animator 类。

ObjectAnimatorAnimator 的继承类之一,它允许您基于对象的单个属性创建自定义动画。我的建议是创建一个自定义视图,该视图将具有一个名为animationFrame 的属性,其值在0-39 范围内。然后,当设置该值时,将加载正确的图像作为视图的背景。您可以使用 Glide 之类的库来优化图像的加载。

所以你的代码应该是这样的:

private class MyAnimation extends View {

    private ObjectAnimator animator = new ObjectAnimator();

    public MyAnimation(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        animator.setTarget(this);
        // the value must match a function with the signature "void setAnimationFrame(int frame)" (using the magic of reflection)
        animator.setPropertyName("animationFrame"); 
        animator.setIntValues(0, 39);
        animator.setRepeatCount(ObjectAnimator.INFINITE);
        animator.setRepeatMode(ObjectAnimator.RESTART);
        animator.setDuration(1000 / 60 * 40);
        animator.setInterpolator(new LinearInterpolator());

        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                // If you need to do something at the end of the animation
            }
        });
    }

    public void startAnimation() {
        animator.start();
    }

    private void setAnimationFrame(int frame) {
        setBackground(getDrawableForFrame(frame));
    }

    private Drawable getDrawableForFrame(int frame) {
        // Here you implement the loading from Glide or any other library or custom code
        return null;
    }
}

【讨论】:

  • +1 将我指向 Glide。我以前没有使用过 3rd 方库,所以在使用它之前必须做一些研究。你能告诉我如何使用 Glide 在这个解决方案中加载图像github.com/hewei05/FramesSequenceAnimation/blob/master/src/com/…。 ObjectAnimator 对我来说也是新的,但它看起来是最简单的解决方案。一旦我能够在我的应用中实现它,我会将您的回复标记为正确答案。
  • 在本例中,加载单个图像资源类似于Glide.with(this).load(R.drawable.ac_screen).into(imageView);
  • 在您的回答的帮助下,我成功制作了一个长动画。我只是扩展了 ImageView 并添加了一个方法 setFrame(int frame)。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-13
  • 1970-01-01
相关资源
最近更新 更多