2012-11-22 17 views
6

मैंने एक कण प्रणाली एप्लेट लिखा है; वर्तमान में मैं बना रहा हूं, और प्रत्येक कण को ​​अलग से खींच रहा हूं। (यहाँ कोड है)कुशलतापूर्वक बहुत सारे कणों को चित्रित करना

BufferedImage backbuffer; 
Graphics2D g2d; 

public void init(){ 
    backbuffer = new BufferedImage(WIDTH,HEIGHT,BufferedImage.TYPE_INT_RGB); 
    g2d = backbuffer.createGraphics(); 
    setSize(WIDTH, HEIGHT); 

    //creates the particles 
    for (int i = 0; i < AMOUNTPARTICLES; i++) { 
     prtl[i] = new particleO(); 
     prtl[i].setX(rand.nextInt(STARTX)); 
     prtl[i].setY(rand.nextInt(STARTY)); 
     prtl[i].setVel(rand.nextInt(MAXSPEED)+1); 
     prtl[i].setFAngle(Math.toRadians(rand.nextInt(ANGLESPREAD))); 

     } 

    //other code 
} 



    public void update(Graphics g) {   

    g2d.setTransform(identity); 

    //set background 
    g2d.setPaint(BGCOLOUR); 
    g2d.fillRect(0,0,getSize().width,getSize().height); 
    drawp(); 
    paint(g);   
    } 


public void drawp() { 

    for (int n = 0; n < AMOUNTPARTICLES; n++) { 

    if (prtl[n].getAlive()==true){ 
      g2d.setTransform(identity); 
      g2d.translate(prtl[n].getX(), prtl[n].getY()); 
      g2d.setColor(prtl[n].getColor()); 

      g2d.fill(prtl[n].getShape()); 


      } 
    } 

} 

यह प्रदर्शन ठीक था मुझे 20,000 कणों (हालांकि, मैं एक सभ्य लैपटॉप) के साथ 40fps मिल सकता है ~। लेकिन उसके बाद मैं (नीचे देखें) टक्कर पता लगाने कहा, उस नंबर, कम से कम 2000 तक गिर

public void particleUpdate(){ 
for (int i = 0; i < AMOUNTPARTICLES; i++) { 
     //other update code (posx, posy, angle etc etc) 

      for (int j = 0; j < AMOUNTPARTICLES; j++) { 

       if (i!=j && prtl[j].getAlive()==true){ 

        if(hasCollided(i, j)){ 
         prtl[i].setcolor(Color.BLACK); 
         prtl[j].setcolor(Color.BLACK); 
    } 
      } 
    } 

public boolean hasCollided(int prt1, int prt2){ 

     double dx = prtl[prt1].getX() - prtl[prt2].getX(); 
     double dy = prtl[prt1].getY() - prtl[prt2].getY(); 
     int edges = prtl[prt1].getRadius() + prtl[prt2].getRadius(); 

     double distance = Math.sqrt((dx*dx) + (dy*dy)); 
     return (distance <= edges); 


    } 

मैं स्क्रीन पर कणों ड्राइंग का एक बेहतर तरीका के लिए काफ़ी खोज की है, लेकिन उदाहरण या तो मुझे उलझन में , या लागू नहीं थे।

मैं गणना की नाव भार (बहुत अधिक) कर रहा हूं। लेकिन मैं इसे करने का एक और तरीका नहीं सोच सका, सुझावों का स्वागत है।

+0

http://stackoverflow.com/questions/13046033/an- कुशल-way-to-simulate-many-particle-collisions –

+0

एक बार यह स्वीकार करने के बाद मत भूलना कि किसने आपको सबसे ज्यादा मदद की है। – PearsonArtPhoto

उत्तर

5

सबसे पहले, टकराव का पता लगाने जैसे कुछ में जोड़ने से हमेशा बहुत सारी मेमोरी होती है। हालांकि, के अपने टक्कर पता लगाने एल्गोरिथ्म को देखो

public void particleUpdate(){ 
for (int i = 0; i < AMOUNTPARTICLES; i++) { 
     //other update code (posx, posy, angle etc etc) 

      for (int j = 0; j < AMOUNTPARTICLES; j++) { 

       if (i!=j && prtl[j].getAlive()==true){ 

        if(hasCollided(i, j)){ 
         prtl[i].setcolor(Color.BLACK); 
         prtl[j].setcolor(Color.BLACK); 
       } 
      } 
    } 

के नाटक करते हैं वहाँ था केवल 2 कण, 1 और 2. आप आदेश 1,1 1,2 2,1 2,2 में, जाँच करेगा

सच्चाई यह है कि आपको केवल इस मामले में 1 बनाम 2 की जांच करने की आवश्यकता है। यदि 1 हिट 2, 2 भी 1 हिट करेगा। तो पहले परीक्षण किए गए लूप स्किप के लिए अपना बदलें, और उस मामले के लिए एक ही संख्या।

public void particleUpdate(){ 
for (int i = 0; i < AMOUNTPARTICLES; i++) { 
     //other update code (posx, posy, angle etc etc) 

      for (int j = i+1; j < AMOUNTPARTICLES; j++) { 

एक और बात मैं चलता है कि आप sqrt आपरेशन करते हैं, लेकिन केवल क्या एक स्थिर संख्या की तरह लग रहा करने के लिए तुलना करने के लिए है। यदि आप इसे हटाते हैं, और इसे संख्या वर्ग से तुलना करते हैं, तो आपको एक बड़ा सुधार मिलेगा, खासकर आप जो कुछ भी करते हैं उसके साथ।

double distance_squared = ((dx*dx) + (dy*dy)); 
    return (distance <= edges*edges); 

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

  1. यह देखने के लिए जांचें कि क्या कण मैं जीवित हूं, इससे पहले कि मैं देखने के बाद किसी और चीज की गणना करता हूं।
  2. जोड़े पर त्वरित पास करें, केवल अगर वे नज़दीक हैं तो विस्तार से जांचने के लिए भी परेशान हैं। एक सरल तरीका यह पता लगाने के लिए होगा कि क्या वे एसकर्ट ऑपरेशन लेने से पहले एक्स और वाई आयामों में पहले हैं या नहीं। जटिल करने से पहले हमेशा सस्ता परीक्षण करें।
  3. यह देखने के लिए कि क्या आप वास्तव में गणना की गई सभी मानों का उपयोग करते हैं, या यदि आप किसी भी तरह से संचालन की संख्या को कम करने में सक्षम हो सकते हैं, तो अपने कोड को देखें।
  4. शायद आप नियमित स्ट्रोक के साथ छवियों को नियमित आधार पर क्लस्टर कर सकते हैं, फिर केवल उन ऑब्जेक्ट को परिशोधित करें जो प्रारंभिक क्लस्टर को समय के लिए पारित करते हैं, फिर एक विस्तृत क्लस्टर एल्गोरिदम करें।
  5. आप टकराव का पता लगाने थ्रेड कर सकते हैं। हालांकि, अगर आप ऐसा करने जा रहे हैं, तो आपको केवल यह जांचने के लिए थ्रेड करना चाहिए कि कुछ टकरा गया है या नहीं, और उन सभी धागे के बाद, ऑब्जेक्ट को दृश्य पर अपडेट करें।
  6. वैकल्पिक आर्किटेक्चर में देखें, जो कुछ चीजों को गति दे सकता है।
+0

बहुत बहुत धन्यवाद, मैं ऐसा कुछ सोच रहा था (इसके लिए घोंसला) लेकिन यह मेरे सिर (+ 1'ed) – user1159424

+0

से बाहर नहीं आएगा कोई समस्या नहीं। इस तरह की चीजों को अनुकूलित करना शायद प्रोग्रामिंग का मेरा पसंदीदा हिस्सा है :-) – PearsonArtPhoto

+0

इसके अलावा, कणों को जांचने के बारे में कैसे पता चला है? केवल अंतिम फ्रेम के बाद से चले गए कण खींचें। टकराव के लिए भी यही है; 2 कण जो स्थानांतरित नहीं हुए हैं वे एक-दूसरे में टकराएंगे। –

4

चित्रकारी एक जटिल प्रक्रिया है और रंग अनुरोध किन्हीं भी कारणों से के लिए शुरू किया जा सकता है, ओएस खिड़की अपडेट करना चाहें, रीपेंट प्रबंधक फिर से रंगना, programer फिर से रंग देना चाहते हो सकता है चाहते हो सकता है।

paint प्रक्रिया के भीतर कणों को अपडेट करना बुरा विचार है। आप एक अलग बफर पर अलग थ्रेड में कणों को अद्यतन करना चाहते हैं। जब आप तैयार हों, तो अनुरोध करें कि बफर को चित्रित करने के लिए ज़िम्मेदार घटक पुन: चित्रित करने के लिए बफर की एक नई प्रतिलिपि पास कर रहा है (आप बफर पर पेंटिंग नहीं करना चाहते हैं जो स्क्रीन पर अपडेट होना शुरू हो गया है, आप ' गंदा पेंट्स के साथ खत्म हो जाएगा)।

आपको कोड से बताना मुश्किल है, लेकिन ऐसा लगता है कि आप java.awt.Applet का उपयोग कर रहे हैं, व्यक्तिगत रूप से, मैं javax.swing.JApplet पर अपग्रेड करूँगा।

मैं एक java.swing.JPanel को पेंटिंग के लिए कदम होगा। स्विंग घटक डबल बफरिंग (साथ ही अन्य बफरिंग रणनीतियों) प्रदान करते हैं। कण इंजन के पास एक नया फ्रेम होने पर स्क्रीन पर एक बफर पेंट करने के लिए इस पैनल में एकमात्र नौकरी है।

कण इंजन सभी कणों को अद्यतन करने और इन परिणामों को बैकिंग बफर (BufferedImage) पर चित्रित करने के लिए ज़िम्मेदार है, फिर इसे पैनल को सौंप दिया जाएगा और पैनल एक प्रतिलिपि बनायेगा और एक अपडेट शेड्यूल करेगा।

स्विंग सुरक्षित सूत्र नहीं है। यही है, आपको किसी भी थ्रेड से इवेंट डिस्पैचिंग थ्रेड से यूआई में बदलाव नहीं करना चाहिए। इस अंत तक, आप क्लाइंट को ऑफ स्क्रीन बफर को पुनर्वितरण के समाधान के लिए Concurrency in Swing के माध्यम से पढ़ना चाहेंगे।

+0

+1 अच्छा स्थान: पी – MadProgrammer

+0

बहुत जानकारीपूर्ण, ty – user1159424

0

आप सभी particless सभी के साथ टकराने की जाँच कर रहे particlesand यह काफी requeriment (2,000 कणों 4000000 संयोजन का मतलब है, प्रत्येक फ्रेम के लिए) है, एन^2 के आदेश की।

मुद्दा जावा लेकिन एल्गोरिथ्म नहीं है। बेहतर विकल्प होना चाहिए, लेकिन आपके साथ शुरू करने से तुलना कम हो सकती है; यदि आपके पास अधिकतम गति एस है और टी द्वारा आपकी दुनिया में वृद्धि का समय टी के साथ है, तो आपको एक कण की अधिकतम दूरी डी मिलती है जो आप जिस कण पर विचार कर रहे हैं उसके साथ टकरा सकते हैं। उन कणों को खोज कम करें जो उस दूरी के बराबर या उससे कम दूरी पर हैं। हो सकता है कि खोज को आपके कण में केंद्रित वर्ग में ऊंचाई/चौड़ाई डी के साथ सीमित करना आसान हो जाएगा (इसमें कुछ कण शामिल होंगे जो बहुत दूर हैं, लेकिन चेक को आसान बना देंगे)।

साथ ही, अपने कोड में आप बनाम P2 और P2 बनाम पी 1 है जो एक ही है P1 की टक्कर जाँच कर रहे हैं, कि एक फालतूपन कि आप आसानी से बच सकते हैं है।

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