2010-03-13 9 views
7

मैं एक SurfaceView पर आंदोलन को एनिमेट करना चाहता हूं। एक बार एनीमेशन समाप्त होने के बाद मैं भी अधिसूचित होना चाहूंगा।सतह दृश्य में एक छवि को एनिमेट करना और घूर्णन करना

उदाहरण के लिए: मेरे पास उत्तर की ओर एक कार हो सकती है। अगर मैं इसे एनिमेट करना चाहता था ताकि यह 500ms की अवधि के लिए दक्षिण का सामना कर सके, तो मैं यह कैसे कर सकता हूं?

मैं एक SurfaceView का उपयोग कर रहा हूं, इसलिए सभी एनीमेशन मैन्युअल रूप से संभाला जाना चाहिए, मुझे नहीं लगता कि मैं एक्सएमएल या एंड्रॉइड एनीमेटर कक्षाओं का उपयोग कर सकता हूं।

इसके अलावा, मैं लगातार एक SurfaceView (यानी। टहलने के चक्र) के अंदर कुछ चेतन करने के लिए

उत्तर

8

घूर्णन छवियों मैन्युअल रूप से एक दर्द का एक सा हो सकता है सबसे अच्छा तरीका जानना चाहते हैं, लेकिन यहाँ मैं कैसे किया है है यह।

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 

} 

यह आपके कार बिटमैप को आपके द्वारा निर्दिष्ट समय में निर्दिष्ट कोण में घुमाएगा + अंतिम फ्रेम खींचने का समय। हालांकि, वहाँ एक पकड़ है। यह स्क्रीन पर अपनी स्थिति समायोजित किए बिना आपकी कार बिटमैप को घुमाता है। आप अपने बिटमैप को कैसे आकर्षित कर रहे हैं, इस पर निर्भर करते हुए, आप बिटमैप के ऊपरी-बाएं कोने में रहते हुए अपने कार बिटमैप घूर्णन के साथ समाप्त हो सकते हैं। जैसे-जैसे कार घूमती है, बिटमैप पारदर्शी पिक्सल के साथ इसके चारों ओर अंतराल भरने, नई कार आकार फिट करने के लिए खिंचाव और समायोजित करेगा। यह इस तरह दिखाई देंगे वर्णन करने के लिए मुश्किल है, इसलिए यहाँ एक उदाहरण एक वर्ग घूर्णन है:

alt text

ग्रे क्षेत्र बिटमैप का पूर्ण आकार का प्रतिनिधित्व करता है, और पारदर्शी पिक्सेल से भरा है। इस समस्या को हल करने के लिए, आपको त्रिकोणमिति का उपयोग करने की आवश्यकता है। यह थोड़ा जटिल है ... यदि यह आपके लिए एक समस्या हो रहा है (मुझे नहीं पता कि आप कैनवास में अपने बिटमैप्स कैसे चित्रित कर रहे हैं तो यह नहीं हो सकता है), और आप समाधान को हल नहीं कर सकते हैं मुझे पता है और मैं पोस्ट करूंगा कि मैंने यह कैसे किया।

(मुझे नहीं पता कि यह करने का यह सबसे प्रभावी तरीका है, लेकिन यह मेरे लिए आसानी से काम करता है जब तक कि बिटमैप 300x300 या उससे भी कम हो। शायद अगर कोई बेहतर तरीके से जानता है, तो वे हमें बताएं!)

+0

यदि आप बार-बार अपना बिटमैप बनाते हैं तो आपको प्रदर्शन समस्याओं में भाग लेने की संभावना है। इसके बजाए, इसे एक बार बनाएं और फिर अपने मैट्रिक्स को 'canvas.drawBitmap()' में पास करें। साथ ही, जबकि लूप एनिमेटिंग से कुछ और को रोक देगा जब तक कि आपकी बारी पूरी नहीं हो जाती। गेम लूप आज़माएं: http://www.koonsolo.com/news/dewitters-gameloop/ – idbrii

7

क्या आप कई स्वतंत्र एनिमेटेड ऑब्जेक्ट चाहते हैं? यदि ऐसा है, तो आपको एक गेम लूप का उपयोग करना चाहिए। (एक मास्टर जबकि लूप जो सभी गेम ऑब्जेक्ट्स को क्रमशः अद्यतन करता है।) विभिन्न लूप कार्यान्वयन पर Here's a good discussion। (मैं वर्तमान में "एफपीएस लगातार खेल स्पीड पर निर्भर है" मेरे 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); 
    } 
} 

आप केवल एक बार अपने बिटमैप लोड करने की जरूरत है। तो यदि आपके पास कई कारें हैं, तो आप उन्हें एक ही बिटमैप ऑब्जेक्ट (अपने SurfaceView में बिटमैप कैश करें) देना चाहेंगे।

मुझे अभी तक चलने वाले एनिमेशन में नहीं मिला है, लेकिन सबसे आसान समाधान कई बिटमैप्स होना है और प्रत्येक बार प्रदर्शन को अलग-अलग बिटमैप खींचना है।

यदि आप पहले से नहीं हैं तो lunarlander.LunarView in the Android docs पर एक नज़र डालें।


यदि आप एनीमेशन पूर्ण होने पर अधिसूचित होना चाहते हैं, तो आपको कॉलबैक करना चाहिए।

interface CompletedTurnCallback { 
    void turnCompleted(Car turningCar); 
} 

अपने तर्क वर्ग कॉलबैक को लागू करने और अपनी कार यह जब बारी का पूरा फोन (update() में) है। ध्यान दें कि यदि आप update_game() में कारों की सूची में पुनरावृत्त कर रहे हैं तो आप एक ConcurrentModificationException प्राप्त करेंगे और आप अपनी कॉलबैक में उस सूची से कार को निकालने का प्रयास करते हैं। (आप इसे कमांड कतार के साथ हल कर सकते हैं।)

संबंधित मुद्दे