Animating and rotating a surface image

I would like to animate the movement on SurfaceView. Ideally, I would also like to be notified after the animation is complete.

For example: I may have a car standing in the north. If I wanted to revive him so that he looked South for 500 ms, how could I do this?

I use SurfaceView, therefore all animation should be processed manually, I do not think that I can use XML or classes of an android animator.

Also, I would like to know how best to animate something inside a SurfaceView (i.e. a walk loop)

+7
android
Mar 13 '10 at 17:38
source share
2 answers

Rotating images manually can be a little painful, but here's how I did it.

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 } 

This will rotate your carBitmap to any angle you specify at the specified time + time to draw the last frame. However, there is a catch. This rotates your carBitmap without properly adjusting its position on the screen. Depending on how you draw bitmaps, you may end up rotating your carBitmap, while the top left corner of the bitmap remains in place. As the car rotates, the bitmap will be stretched and adjusted in accordance with the new size of the car, filling in the spaces around it with transparent pixels. It is difficult to describe how this will look, so an example rotating a square:

alt text

The gray area represents the full size of the bitmap and is filled with transparent pixels. To solve this problem, you need to use trigonometry. This is a little complicated ... if this is a problem for you (I don’t know how you draw your bitmap images on canvas so that it could be wrong), and you cannot solve the solution, even if I know, and I will post how I did it.

(I don’t know if this is the most efficient way to do this, but it works smoothly for me, as long as the bitmap is less than 300 Γ— 300 or so. Maybe if someone knows about the best way, they can tell us!)

+8
Mar 13
source share

Do you need some independent animated objects? If so, then you should use the game loop. (One lead loop that gradually updates all game objects.) Here's a good discussion on the various loop implementations. (I am currently using "Constant Game Speed ​​Dependent FPS" for my Android game project.)

So, your car will look something like this (a lot of code is missing):

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

You only need to download the bitmap once. Therefore, if you have several cars, you can give them the same Bitmap object (cache Bitmap in SurfaceView).

I have not yet participated in the walk animation, but the simplest solution is to have several bitmaps and just draw a different bitmap every time a display is called.

See lunarlander.LunarView in Android docs if you haven't already.




If you want to receive notifications of animation completion, you must make a callback.

 interface CompletedTurnCallback { void turnCompleted(Car turningCar); } 

Ask your logical class to make a callback and ask him to call the author when he completes the move (in update() ). Note that you will get a ConcurrentModificationException if you repeat the Cars list in update_game() , and you are trying to remove the car from this list in your callback. (You can solve this using the command line.)

+7
Nov 03 '10 at 19:43
source share



All Articles