2010-08-26 16 views
6

Próbuję dowiedzieć się, jak obejść mój problem. Przeczytałem http://groups.google.com/group/android-developers/browse_thread/thread/a2aac88a08cb56c2/b7dff4ba388cd664?lnk=gst&q=SurfaceView#b7dff4ba388cd664, który odpowiada na moje pytanie, ale z tego, co wiem, jest to rodzaj "trudnego szczęścia". Oto mój problem:SurfaceView migotanie/łzawienie

Używam SurfaceView w normalny sposób (lock/unlockAndPost), aby narysować mapę bitową mojego tła gry za każdym razem, gdy zmieni się jej powierzchnia (np. Orientacja itp.) I wykonuję serię ruchów kółka (do 30 o promieniu około 25f). Dane x, y dla pozycji tych kół pochodzą z serwera i wszystko działa poprawnie. Wszystkie obiekty w okręgu są przechowywane na liście, a ich pozycja jest aktualizowana, uważając, aby ta aktualizacja była zsynchronizowana. Jednak po narysowaniu tych okręgów na ekranie (podczas canvas.lock()), przez większość czasu renderują one dobrze, ale sporadycznie (np. Raz na kilka sekund), niektóre kręgi wydają się odrywać lub migotać krótko dla ramki. Liczba okręgów jest zawsze stała, więc to nie jest problem i nie ma równoczesnych modyfikacji listy kręgów (tak jak powiedziałem, jest zsynchronizowana). Próbowałem nawet rysować wszystkie te okręgi do bitmapy w każdej pętli renderowania i rysować tę mapę bitową na płótnie głównym. To tylko wydaje się wpływać na wydajność jeszcze bardziej (~ 13FPS w przeciwieństwie do ~ 30FPS przy rysowaniu kół bezpośrednio do głównego płótna). Przepraszam, jeśli informacje są trochę niewyraźne, (próbując utrzymać firmę w przyjemności: p), ale zastanawiałem się, czy ktoś może mi dać wskazówkę? Czy mam po prostu pecha? Należy zauważyć, że dane pozycjonowania pochodzące z serwera są danymi w czasie rzeczywistym i niezwykle ważne jest, aby renderowanie odzwierciedlało te pozycje w czasie rzeczywistym.

Dzięki za pomoc! Chris

EDIT:

Słusznie. Oto run() z wątku renderowania.

@Override 
    public void run() { 
     Canvas c; 
     while (mRun) { 
      c = null; 
      try { 
       c = mSurfaceHolder.lockCanvas(null); 
       synchronized (mSurfaceHolder) { 
        panel.onDraw(c); 
       } 
      } finally { 
       if (c != null) { 
        mSurfaceHolder.unlockCanvasAndPost(c); 
       } 
      } 
     } 
    } 

dość standardowy rzeczy (prawie wierną kopią księżycowego lądownika: p)

@Override 
public void surfaceCreated(SurfaceHolder holder) { 
    mBackground= Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.RGB_565); 
    screenOrientation = getResources().getConfiguration().orientation; 
    if(thread.getState()== Thread.State.TERMINATED){ 
     thread = new RenderThread(holder, this); 
     thread.setRunning(true); 
     thread.start(); 
    }else { 
     thread.setRunning(true); 
     thread.start(); 
    } 
} 



@Override 
public void surfaceChanged(SurfaceHolder holder, int format, int width, 
     int height) { 
    Canvas c = new Canvas(mField); 
    c.drawARGB(255,0,144,0); 
    backgroundDetails.renderOnPanel(c, this); 
    screenOrientation = getResources().getConfiguration().orientation; 
} 

Dość łatwy do naśladowania, tylko przerysowanie bitmapy tła Jeżeli zmiany orientacji i rozpocząć wątek renderowania.

public void onDraw(Canvas canvas) { 
    canvas.drawBitmap(mField,0,0,null); 
    drawPositionBeans(canvas, this); 
} 

I wreszcie: znowu

public void onDraw(Canvas canvas, RadarView radarView) { 
    float beanX=0, beanY=0; 
    float radius = 25.0f; 
    final List<PositionBean> copyOfList = Collections.synchronizedList(positionBeans.getPositionBeans()); 
    synchronized(copyOfList){ 
     try { 
      for (final PositionBean pb : copyOfList) 
      { 
       if (panel.getOrientation() == Configuration.ORIENTATION_PORTRAIT) { 
        beanX = (float)pb.getY()*(-1); 
        beanY = (float)pb.getX(); 
       } else { 
        beanX = (float)pb.getY()*(-1); 
        beanY = (float)pb.getX()*(-1); 
       } 
       mPaint.setARGB(255,pb.getRgbColor().getR(), pb.getRgbColor().getG(), pb.getRgbColor().getB()); 
       panel.drawSpot(canvas, beanX, beanY, radius, mPaint); 

       mPaint.setStyle(Paint.Style.STROKE); 
       mPaint.setARGB(255,255,222,1); 
       for (int j = 0; j < selectedBean.size(); ++j) 
       { 
        if(pb.getTrack()==selectedBean.get(j)) { 
         panel.drawSpot(canvas, beanX, beanY, radius+1, mPaint); 
        } 
       } 
       mPaint.setStyle(Paint.Style.FILL); 
      } 

     } catch(Exception e) { 
      Log.e("render", "Exception Drawing Beans: " + e); 
     } 
    } 
} 

Dzięki chłopaki. Chris

+0

da się odpowiedzieć bez widząc gameloop i kod rysowania. – Sebi

+0

Tak jak Sebi powiedział - próbka kodu byłaby pomocna - ale czy brałeś pod uwagę możliwość, że pozycje, które otrzymujesz okazjonalnie są nieprawidłowe? Wystarczy pomyśleć, dlaczego kręgi mogą być "migotliwe", jeśli są tymczasowo umieszczone poza zasięgiem wzroku. Ponownie, bez żadnego kodu nie będzie można na nie odpowiedzieć. – Seidr

+0

Wielkie dzięki za pomocników. Ale tak, jestem pewien, że dane dotyczące pozycjonowania są poprawne. –

Odpowiedz

0

Miałem ten problem. Rozwiązaniem odpowiednim dla mnie jest synchronizacja metody i metody onDraw, która aktualizuje macierz transformacji. Ponieważ istniały ramki, gdy macierz jest identyczna (wartość początkowa nowej macierzy()), aw następnej ramce miała prawidłowe wartości.

0

znalazłem po przeczytaniu trochę o widoku powierzchniowego że jeśli zadzwonisz

getHolder().lockCanvas(); 

Trzeba wyciągnąć wszystko jeszcze raz.

Chyba że podasz brudny obszar.

getHolder().lockCanvas(Rect dirty); 

Jeśli chcesz tylko przerysowanie obszarze wyznaczonym przez Rect

Powiązane problemy