2010-03-13 3 views
7

SurfaceView에서 움직임을 움직이기를 원합니다. 애니메이션이 끝나면 알림을 받고 싶습니다.표면 뷰에서 이미지 애니메이션 및 회전

예를 들어

: 나는 북한에 직면 자동차가있을 수 있습니다. 500ms의 지속 시간 동안 남쪽을 향하도록 애니메이션을 만들고 싶다면 어떻게해야합니까?

내가 그렇게 모든 애니메이션을 수동으로 처리해야하는 서피스 뷰 SurfaceView를 사용하고, 나는 XML 또는 안드로이드 애니메이터 클래스를 사용할 수 있다고 생각하지 않습니다.

또한, 나는

답변

8

이미지 회전 수동으로 약간의 고통이 될 수 지속적으로 서피스 뷰 SurfaceView (예. 산책주기) 내부에 뭔가를 애니메이션하는 가장 좋은 방법을 알고 싶습니다,하지만 여기에 내가했던 방법 그것.

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

회색 영역은 비트 맵의 ​​전체 크기를 나타내며, 투명 픽셀으로 가득합니다. 이 문제를 해결하려면 삼각법을 사용해야합니다. 조금 복잡합니다 ... 이것이 문제가되는 경우 (캔버스에 비트 맵을 그리는 방법이 무엇인지 모르겠으므로 그렇지 않을 수 있습니다), 솔루션을 해결할 수는 없습니다. 나 알고 있고 내가 어떻게했는지 게시 할게.

(이 방법이 가장 효율적인 방법인지는 잘 모르겠지만 비트 맵이 300x300 미만인 한 원활하게 작동합니다. 누군가가 더 좋은 방법을 알고 있다면 우리에게 말해주세요!)

+0

반복적으로 비트 맵을 생성하면 성능 문제가 발생할 가능성이 있습니다. 대신 그것을 한 번 만들고 행렬을'canvas.drawBitmap()'에 전달하십시오. 또한, while 루프는 턴이 끝날 때까지 다른 것들이 움직이지 않게합니다. 게임 루프를 사용해보십시오. http://www.koonsolo.com/news/dewitters-gameloop/ – idbrii

7

여러 개의 독립적 인 애니메이션 객체를 원하십니까? 그렇다면 게임 루프를 사용해야합니다. (모든 게임 개체를 점차적으로 업데이트하는 하나의 마스터 while 루프) Here's a good discussion 다양한 루프 구현. (나는 현재 내 안드로이드 게임 프로젝트에 대해 "일정한 게임 속도에 따라 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 캐시)를 각각 제공해야 할 수 있습니다.

나는 아직 도보 애니메이션에 합격하지 않은,하지만 가장 간단한 솔루션은 여러 개의 비트 맵이 단지마다 표시가 호출되는 다른 비트 맵을 그릴 수있다. 당신이 이미하지 않은 경우

lunarlander.LunarView in the Android docs에서보세요.


애니메이션이 완료되었을 때 알림을 받으려면 콜백을해야합니다.

interface CompletedTurnCallback { 
    void turnCompleted(Car turningCar); 
} 

는 로직 클래스는 콜백을 구현하고 자동차 ( update() 년) 때 차례의 전체 호출이 되세요. 자동차 목록을 반복하여 update_game()에 있고 콜백의 해당 목록에서 Car를 제거하려고하면 ConcurrentModificationException이 발생합니다. (명령 대기열로 해결할 수 있습니다.)

관련 문제