在Surface View中animation和旋转图像

我想在SurfaceView上制作animationanimation。 理想情况下,我想在animation结束后收到通知。

例如:我可能有一辆朝北的汽车。 如果我想animation它以使其面向南方持续500ms,我该怎么办呢?

我使用的是SurfaceView,因此必须手动处理所有animation,我认为我不能使用XML或Android Animator类。

此外,我想知道在SurfaceView中连续animation内容的最佳方法(即步行循环)

手动旋转图像可能有点痛苦,但这就是我如何做到的。

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。 随着汽车的旋转,位图将拉伸并调整以适应新的汽车尺寸,用透明像素填充其周围的空隙。 很难描述它的外观,所以这是一个旋转方块的例子:

替代文字

灰色区域表示位图的完整大小,并填充透明像素。 要解决此问题,您需要使用三角函数。 它有点复杂...如果这最终成为你的问题(我不知道你是如何将你的位图绘制到canvas上所以它可能不是),你无法解决问题,让我知道,我会发布我是如何做到的。

(我不知道这是否是最有效的方法,但只要位图小于300x300左右,它就能顺利运行。也许如果有人知道更好的方法,他们可以告诉我们!)

你想要多个独立的animation对象吗? 如果是这样,那么你应该使用游戏循环。 (一个主循环,循环,逐步更新所有游戏对象。) 这是一个很好的讨论各种循环实现。 (我目前正在为我的Android游戏项目使用“依赖于恒定游戏速度的FPS”。)

那么你的汽车会看起来像这样(很多代码丢失):

 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); } } 

您只需要加载一次位图。 因此,如果您有多个Cars,您可能希望为它们分别提供相同的Bitmap对象(在SurfaceView中缓存Bitmap)。

我还没有进入步行animation,但最简单的解决方案是拥有多个位图,并在每次调用显示时绘制不同的位图。

如果您还没有看过Android文档中的lunarlander.LunarView,请查看。


如果您希望在animation完成时收到通知,则应进行回调。

 interface CompletedTurnCallback { void turnCompleted(Car turningCar); } 

让你的逻辑类实现回调并让你的Car在转弯完成时调用它(在update() )。 请注意,如果您在update_game()中迭代Cars列表并尝试从回调中的该列表中删除Car,则会收到ConcurrentModificationException。 (您可以使用命令队列解决此问题。)