#java #android #анимация #animate
В моей словесной игре типа "Эрудита" для Android отсутствует анимация - Например, при выборе в меню "Вернуть буквы" фишки просто удаляются с игрового поля и потом (вдруг!) показываются внизу экрана. Тоже самое с "Помешать буквы" - фишки просто рисуются на новых позициях внизу экрана: Конечно, это выглядит не очень наглядно и мне хотелось бы добавить простые анимации для буквенных фишек - но при этом не терять совместимость с Android 2.2 - поэтому нельзя например использовать ValueAnimator. Кроме того, мне кажется, что можно обойтись без Runnable и создания дополнительных thread-ов - потому что я уже успешно анимирую flinging игрового поля (когда пользователь скроллит его энергичным движением пальца) в главном thread при помощи ScrollerCompat. Вот класс буквенных фишек: public class Tile { public static int sWidth; public static int sHeight; // этот прямоугольник содержит координаты и размер фишки private Rect mRect = new Rect(); Для анимации я решил добавить в этот класс конечные координаты и флаг, что движение фишки еще не закончилось: private Point mTarget = new Point(); public boolean moving = false; И два метода для перемещения фишки - без и с анимацией: public void move(int x, int y) { mRect.left = x; mRect.top = y; mRect.right = x + sWidth; mRect.bottom = y + sHeight; } public void moveAnimated(int x, int y) { moving = true; mTarget.x = x; mTarget.y = y; } Потом, в методе отрисовки моего главного custom View я вызываю: public class GameView extends View { private static final int DELAY = 30; private ArrayListmBarTiles = new ArrayList (); @Override protected void onDraw(Canvas canvas) { if (mGameBoard.isFlinging()) { postInvalidateDelayed(DELAY); } else { for (SmallTile tile: mBoardTiles) { if (tile.moving) { postInvalidateDelayed(DELAY); break; } } } // нарисовать (с учетом scroll-а) игровое поле с фишками mGameBoard.draw(canvas, mBoardTiles); // нарисовать до 7 фишек внизу экрана - с анимацией for (SmallTile tile: mBarTiles) tile.draw(canvas); // нарисовать 1 фишку которую тащит пользователь mDraggedTile.draw(canvas); } Как видите наверху, если одна из фишек еще в процессе движения (и ее флаг moving=true), то вызывается onDraw еще раз через 30 миллисекунд. То же самое для анимации игрового поля - если оно еще движется (isFlinging() возвращает true) - но это уже работает без проблем. Теперь собственно мой вопрос: В процедуре отрисовке фишки нужно учесть ее движение и выставить ее актуальные координаты: public void draw(Canvas canvas) { if (moving) { int dx = mTarget.x - mRect.left; int dy = mTarget.y - mRect.top; // ВОТ ЗДЕСЬ Я ЗАСТРЯЛ - КАКИЕ КООРДИНАТЫ ВЫСТАВИТЬ? move(XXX, YYY); // ЕСЛИ ФИШКА ДОЛЕТЕЛА - НУЖНО ВЫСТАВИТЬ moving=false } // нарисовать background фишки - желтый прямоугольник canvas.drawRect(mRect, mPaint); // нарисовать Bitmap с буквой и ее числовым значением canvas.save(); canvas.translate(mRect.left, mRect.top); Drawable d = sLetters.get(mLetter); d.draw(canvas); canvas.restore(); } К сожалению, я не знаю как правильно подсчитать координаты! У меня есть актуальные координаты фишки: mRect.left и mRect.top У меня есть координаты куда должна прилететь фишка: mTarget.x и mTarget.y Пока moving==true, каждые 30 миллисекунд вызывается код отрисовки фишки, которому нужно дать новые координаты - но как их подсчитать?
Ответы
Ответ 1
Тогда вам нужно выбрать время анимации, допустим 1 секунда = 1000 миллисек. Тогда поделив 1000 на 30 (fps по сути) получаем 33 - количество раз, которое мы вызовем метод draw для достижения цели. Получается, что наш путь dx и dy тоже нужно поделить на 33, тогда мы получим шаг, на который у нас будет сдвигаться фишка, при каждом вызове draw. Ну а дальше остается прибавлять этот шаг к текущим координатам и с ними вызывать метод move: move(mRect.left + (int) (dx / 33), mRect.top + (int) (dy / 33));
Комментариев нет:
Отправить комментарий