2017-02-01 4 views
2

Я разрабатываю простую 2D-игру. Игра начинается с одной анимации, затем игроки нажимают на экран, а другая анимация должна работать без заметной задержки при переключении на следующую анимацию. Мой первый подход состоял в том, чтобы использовать AnimationDrawable с списком анимации из 40 PNG [кадров]. Я хотел использовать два таких AnimationDrawables. Этот подход вызывает OOM из-за поведения android по загрузке всех кадров анимации, прежде чем играть в нее. Затем я решил разделить мою одиночную анимацию на 4 анимации по 10 кадров каждый. Первая анимация из 10 кадров работает отлично, но когда я играю второй [сразу после первого прекращения], я получаю OOM и приложение закрывается.Запуск нескольких анимаций без заметного отставания

1) Я наткнулся на это решение: https://stackoverflow.com/a/10993879/6699069 Это похоже на идеальное решение моей проблемы. Но я не знаю об объекте OnAnimationStoppedListener, который используется в решении. О нем нет на сайтах developers.android.com или где-либо еще. Я хотел напрямую спросить @Pinhassi по комментариям, но не могу добавить комментарий, благодаря 50 репутациям.

Edit: я нашел почти аналогичное решение here работает без каких-либо ошибок: D Но имеет такую ​​же задержку, как я уже говорил в 4) Я даже установить delayMillis = 0; Он по-прежнему работает примерно на 10fps [наблюдается]

2) Должность составляет 5 лет, поэтому я думаю, теперь должен существовать предопределенный класс для использования длинных анимаций без появления OOM. Пожалуйста, укажите мне ссылку, если такой класс существует.

3) Друг предложил мне использовать gif вместо анимации. Но я думаю, что нет возможности остановить/сыграть gif программно. Кроме того, gif с 40 кадрами кажется фантазией. Если кто-то знает использовать gif в качестве эквивалента анимации, пожалуйста, заткните немного света.

4) Мой старый подход [когда я не знал о классе AnimationDrawable] должен был использовать SurfaceView и рисовать 40 растровых изображений на холсте в цикле для имитации анимации. Это сработало, но частота кадров раздражающе медленная. Он становится медленнее, когда игрок удаляет экран. Кроме того, частота кадров значительно отличается на разных телефонах. Некоторые люди предложили мне уменьшить разрешение изображения. Я уменьшил свои изображения с 720p до 320p, но это не имело большого значения. Любой способ ускорить анимацию с помощью этого подхода?

Я был бы очень благодарен, если кто-то может ответить 1) и 2).

+0

Переход к 'GLSurfaceView' (или OpenGL двигатель) и/или посмотреть на использование спрайт листа вместо отдельных изображений. – Tigger

ответ

0

Ваш вопрос довольно широк, поэтому я попытаюсь немного помочь (не уверен, даст ли он полный ответ). Когда я делаю анимацию в Android, я стараюсь как можно больше использовать собственные представления, поскольку производительность почти всегда лучшая, даже для более старых устройств. Если вам нужно сделать что-то более сложное, возможно, вы можете использовать класс Animator.

ObjectAnimator является одним из классов наследования Animator и позволяет создавать пользовательскую анимацию, основанную на одном свойстве вашего объекта. Мое предложение состоит в создании пользовательского представления, которое будет иметь свойство, называемое 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; 
    } 
} 
+0

+1 для указания на Glide. Раньше я раньше не использовал стороннюю библиотеку, поэтому перед ее использованием нужно будет провести некоторое исследование. можете ли вы дать мне подсказку о том, как я могу использовать Glide для загрузки изображений в этом решении https://github.com/hewei05/FramesSequenceAnimation/blob/master/src/com/example/framessequenceanimation/MainActivity.java. ObjectAnimator также новичок для меня, но он выглядит как самое простое решение. Я буду отмечать ваш ответ как правильный ответ, как только я смогу реализовать его в своем приложении. – sziraqui

+0

В этом примере загрузка одного ресурса изображения будет чем-то вроде «Glide.with (this) .load (R.drawable.ac_screen) .into (imageView);' –

+0

Я успешно создал длинную анимацию с помощью вашего ответа , Я просто расширил ImageView и добавил метод setFrame (int frame). Большое спасибо! – sziraqui

Смежные вопросы