Анимация и поворот изображения в виде поверхности

Я хотел бы оживить движение на SurfaceView. В идеале я хотел бы также получить уведомление после завершения анимации.

Например: у меня может быть автомобиль, стоящий на севере. Если бы я хотел оживить его так, чтобы он стоял на юге в течение 500 мс, как я мог это сделать?

Я использую SurfaceView, поэтому вся анимация должна обрабатываться вручную, я не думаю, что могу использовать XML или классы андроидного аниматора.

Кроме того, я хотел бы знать, как лучше всего что-то оживить внутри SurfaceView (т. Е. Цикл ходьбы)

Solutions Collecting From Web of "Анимация и поворот изображения в виде поверхности"

Вращение изображений вручную может быть немного больно, но вот как я это сделал.

private void animateRotation(int degrees, float durationOfAnimation){ long startTime = SystemClock.elapsedRealtime(); long currentTime; float elapsedRatio = 0; Bitmap bufferBitmap = carBitmap; Matrix matrix = new Matrix(); while (elapsedRatio < 1){ matrix.setRotate(elapsedRatio * degrees); carBitmap = Bitmap.createBitmap(bufferBitmap, 0, 0, width, height, matrix, true); //draw your canvas here using whatever method you've defined currentTime = SystemClock.elapsedRealtime(); elapsedRatio = (currentTime - startTime) / durationOfAnimation; } // As elapsed ratio will never exactly equal 1, you have to manually draw the last frame matrix = new Matrix(); matrix.setRotate(degrees); carBitmap = Bitmap.createBitmap(bufferBitmap, 0, 0, width, height, matrix, true); // draw the canvas again here as before // And you can now set whatever other notification or action you wanted to do at the end of your animation } 

Это повернет ваш carBitmap в любой угол, указанный вами в указанное время + время, чтобы нарисовать последний кадр. Однако есть улов. Это вращает ваш carBitmap без правильной настройки его положения на экране. В зависимости от того, как вы рисуете растровые изображения, вы можете в конечном итоге поворачивать ваш carBitmap, в то время как верхний левый угол растрового изображения остается на месте. По мере поворота автомобиля растровое изображение будет растягиваться и настраиваться в соответствии с новым размером автомобиля, заполняя пробелы вокруг него прозрачными пикселями. Трудно описать, как это будет выглядеть, вот пример, вращающий квадрат:

Alt text

Серая область представляет полный размер растрового изображения и заполняется прозрачными пикселями. Чтобы решить эту проблему, вам нужно использовать тригонометрию. Это немного сложно … если это будет проблемой для вас (я не знаю, как вы рисуете свои растровые изображения на холсте, чтобы это могло быть не так), и вы не можете решить решение, пусть Я знаю, и я опубликую, как я это сделал.

(Я не знаю, является ли это наиболее эффективным способом сделать это, но он работает плавно для меня, пока растровое изображение меньше 300 × 300 или около того. Возможно, если кто-то знает лучший способ, они могут сказать нам!)

Вам нужен несколько независимых анимированных объектов? Если да, то вы должны использовать игровой цикл. (Один ведущий цикл, который постепенно обновляет все игровые объекты.) Вот хорошее обсуждение различных реализаций цикла. (В настоящее время я использую «FPS, зависящий от постоянной скорости игры» для моего Android-игрового проекта.)

Итак, ваш автомобиль будет выглядеть примерно так (много кода отсутствует):

 class Car { final Matrix transform = new Matrix(); final Bitmap image; Car(Bitmap sprite) { image = sprite; // Created by BitmapFactory.decodeResource in SurfaceView } void update() { this.transform.preRotate(turnDegrees, width, height); } void display(Canvas canvas) { canvas.drawBitmap(this.image, this.transform, null); } } 

Вам нужно только один раз загрузить растровое изображение. Поэтому, если у вас несколько компьютеров, вы можете дать им каждый один и тот же объект Bitmap (кешируйте Bitmap в SurfaceView).

Пока у меня нет анимации в прогулках, но самым простым решением является наличие нескольких растровых изображений и просто рисование разного растрового изображения каждый раз, когда вызывается отображение.

Посмотрите на lunarlander.LunarView в документах Android, если вы еще этого не сделали.


Если вы хотите получать уведомления о завершении анимации, вы должны сделать обратный вызов.

 interface CompletedTurnCallback { void turnCompleted(Car turningCar); } 

Попросите свой логический класс выполнить обратный вызов, и ваш автомобиль вызовет его, когда очередь завершена (в update() ). Обратите внимание, что вы получите ConcurrentModificationException, если вы повторяете список Cars в update_game() и вы пытаетесь удалить автомобиль из этого списка в своем update_game() . (Вы можете решить это с помощью командной очереди.)