2012-04-05 9 views
5

Obecnie eksperymentuję z bardzo prostym rysunkiem graficznym ... "silnika" (chyba można to tak nazwać). Istota tego:budowa małego graficznego silnika: widoczny vs. addChild/removeChild

  1. Istnieje FrontController, który zostaje trafiony przez żądania użytkownika; Każdy wniosek ma uid
  2. każdy uid (czytaj „strona”) posiada deklarację komponentów („modułów”), które są obecne na nim
  3. komponenty są Sprite podklasy i, w istocie, są unikalne

Naturalnie potrzebuję sposobu na ukrycie/pokazanie tych duszków. Obecnie mam go tak, jak Flex ma domyślnie - w sposób "jeśli jesteśmy w miejscu, w którym jest widoczny komputer, stwórz go, przechowuj w pamięci podręcznej i używaj ponownie za każdym razem, gdy jest znowu widoczny".

Pytanie brzmi - który byłby bardziej odpowiedni i skuteczny sposób ukrywania się i pokazywania - za pomocą addChild/removeChild lub przełączania visible.

Według mnie jest to, że:

  • visible jest szybki i brudny (na pierwszych testach)
  • visible nie tworzy łańcuch zdarzeń propagacji jak Event.ADDED lub Event.REMOVED
  • niewidocznych elementów don Zdarzenia myszy:

Więc removeChild byłby czymś, co zadzwoniłbym, gdybym Na pewno, że komponent nie będzie już potrzebny na ekranie (lub na przykład pamięć podręczna jest zbyt duża)

Co sądzą stackoverflow'ers/AS3-szaleńcy?

Aktualizacja: Oto good read (zapomniałem o Google).

Będę trzymać się visible; wydaje się, że lepiej pasuje do mojego zadania; instrukcja "OPTYMALIZACJA WYDAJNOŚCI DLA PLATFORMY FLASH" autorstwa Adobe na str. 69 dało mi jeszcze więcej pewności siebie.

oto fragment kodu i umieścić do testowania rzeczy dla tych, którzy są zainteresowani:

package 
{ 
import flash.display.Sprite; 
import flash.display.Stage; 
import flash.events.Event; 
import flash.events.KeyboardEvent; 
import flash.ui.Keyboard; 
import flash.utils.getTimer; 

/** 
* Simple benchmark to test alternatives for hiding and showing 
* DisplayObject. 
* 
* Use: 
* <code> 
* new DisplayBM(stage); 
* </code> 
* 
* Hit: 
* - "1" to addChild (note that hitting it 2 times is expensive; i think 
* this is because the player has to check whether or not the comp is 
* used elsewhere) 
* - "q" to removeChild (2 times in a row will throw an exception) 
* - "2" to set visible to true 
* - "w" to set visible to false 
* 
* @author Vasi Grigorash 
*/  
public class DisplayBM{ 
    public function DisplayBM(stage:Stage){ 
     super(); 

     var insts:uint = 5000; 
     var v:Vector.<Sprite> = new Vector.<Sprite>(insts); 
     var i:Number = v.length, s:Sprite 
     while (i--){ 
      s = new Sprite; 
      s.graphics.beginFill(Math.random() * 0xFFFFFF); 
      s.graphics.drawRect(
       Math.random() * stage.stageWidth, 
       Math.random() * stage.stageHeight, 
       10, 
       10 
      ); 
      s.graphics.endFill(); 
      v[i] = s; 
     } 

     var store:Object = {}; 
     store[Event.ADDED] = null; 
     store[Event.REMOVED] = null; 
     var count:Function = function(e:Event):void{ 
      store[e.type]++; 
     } 
     var keydown:Function = function (e:KeyboardEvent):void{ 
      var key:String 
      //clear event counts from last run 
      for (key in store){ 
       store[key] = 0; 
      } 

      stage.addEventListener(Event.ADDED, count); 
      stage.addEventListener(Event.REMOVED, count); 

      var s0:uint = getTimer(), op:String; 
      var i:Number = v.length; 
      if (e.keyCode === Keyboard.NUMBER_1){ 
       op = 'addChild'; 
       while (i--){ 
        stage.addChild(v[i]); 
       } 
      } 
      if (e.keyCode === Keyboard.Q){ 
       op = 'removeChild'; 
       while (i--){ 
        stage.removeChild(v[i]); 
       } 
      } 
      if (e.keyCode === Keyboard.NUMBER_2){ 
       op = 'visibile'; 
       while (i--){ 
        v[i].visible = true; 
       } 
      } 
      if (e.keyCode === Keyboard.W){ 
       op = 'invisibile'; 
       while (i--){ 
        v[i].visible = false; 
       } 
      } 
      if (op){ 
       //format events 
       var events:Array = []; 
       for (key in store){ 
        events.push(key + ' : ' + store[key]) 
       } 

       trace(op + ' took ' + (getTimer() - s0) + ' ' + events.join(',')); 
      } 

      stage.removeEventListener(Event.ADDED, count); 
      stage.removeEventListener(Event.REMOVED, count); 
     } 

     //autodispatch 
     stage.addEventListener(KeyboardEvent.KEY_DOWN, keydown); 
    } 
} 
} 
+1

Jeśli to, co trzeba, aby ukryć/pokazać zużywa dużo zasobów, zwykle będę removeChild/addChild nad ustawieniami jej widoczność. Jeśli jej coś mniejszego lub mniej skomplikowanego, jak grafika lub pole tekstowe, ustawię jego widoczność lub alfa. Wszystko zależy od tego, co musisz ukryć/pokazać – Ronnie

+0

@Ronnie removeChild usuwa tylko przedmiot z listy wyświetlania - nic więcej. –

+0

Przepraszam, ustawiłem go również na wartość zerową i odtwarzam, kiedy tego potrzebuję. – Ronnie

Odpowiedz

2

Widoczne sens więcej do mnie (ponieważ usunięcie dziecka wskazuje na celowość) i to, co staram się wykorzystywać w moje własne projekty podczas pokazywania/ukrywania.

Założę się, że addChild ma nieco mniej wydajności, ale nie wykonałem żadnych testów.

EDYCJA: Właśnie natknąłem się na ten artykuł Adobe http://help.adobe.com/en_US/as3/mobile/WS5d37564e2b3bb78e5247b9e212ea639b4d7-8000.html, który określa, że ​​podczas korzystania z trybu renderowania GPU ustawienie tylko visible = false może mieć wpływ na wydajność, ponieważ istnieje koszt rysowania nakładających się obiektów (nawet jeśli nie są one widoczne).Zamiast tego zaleca się całkowite usunięcie dziecka:

Unikaj przerysowywania, gdy tylko jest to możliwe. Napełnianie polega na nakładaniu wielu elementów graficznych, aby zasłaniały się nawzajem. Przy pomocy oprogramowania renderującego każdy piksel jest rysowany tylko raz. Dlatego w przypadku renderowania oprogramowania aplikacja nie ponosi żadnej kary za wydajność, niezależnie od tego, ile elementów graficznych pokrywa się ze sobą w tym miejscu w pikselach . Natomiast sprzętowy renderer rysuje każdy piksel dla każdego elementu, niezależnie od tego, czy inne elementy zaciemniają ten obszar, czy nie. Jeśli dwa prostokąty zachodzą na siebie, renderer sprzętowy narysuje dwukrotnie nałożony region , podczas gdy renderer oprogramowania rysuje tylko jeden region regionu .

Dlatego na pulpicie, które korzysta z renderera oprogramowania, zwykle nie zauważasz wpływu overdraw. Jednak wiele nachodzących na siebie kształtów może negatywnie wpłynąć na wydajność urządzeń korzystających z GPU w przypadku urządzeń . Najlepszą praktyką jest usuwanie obiektów z listy wyświetlania , a nie ich ukrywanie.

+0

. Tak też myślę. Dla gracza łatwiej jest pracować w kategoriach "draw/not draw" niż "dodaj do listy wyświetlania, zaktualizuj listę wyświetlania, spawn i bubble, remis" i drogę powrotną. Pierwsze proste testy (a nie test jednostkowy) pokazują, że interfejs jest bardziej responsywny podczas manipulowania nim za pomocą 'visible'; Będę musiał jednak bardziej się go pogłębić. –

1

Usunąć dziecko jest lepiej ograniczyć przypadki, zdarzeń i zwolnić pamięć z filmu flash, może się okazać, że po raz skrzaty mogą celu każde other.From jak są rysowane lub tam listneres, także zbieranie śmieci generaly przychodzi do gry, gdy ta metoda jest zaimplementowana, dzięki czemu można ekstremalnie podkręcić swoją aplikację

Widoczny nadal ma ikonkę w pamięci, jej aktualnie nie jest narysowana. Możesz również zapisać ikonkę, a następnie ją usunąć, a następnie wczytać ponownie, gdy zajdzie taka potrzeba. być idealnym rozwiązaniem dla wszystkich rozwiązań. używanie tablic do przechowywania danych to inne rozwiązanie, ponieważ zależy to od implementacji aplikacji, trudno powiedzieć, ponieważ nie wiemy, lol

Dodanie wydajności dla dzieci powiedziałbym, że jest mniejszym obciążeniem, ponieważ jej wciąż tylko element dodaje vs wielokrotności, które są ukryte. Również w tych ukrytych dzieciach "ich właściwości są przechowywane w pamięci wraz ze słuchaczami.

+0

Jak zauważył @Pixel Elephant - 'removeChild' nie zmniejszy twoich instancji, usunie odniesienia. Jeśli zdarza się, że są to jedyne odniesienia wskazujące na obiekt - będą one gc'ed, a tym samym zwolnią pamięć. Nie przetestowałem go dokładnie, ale z punktu widzenia użytkownika - "widoczny" działa szybciej niż 'addChild' i' removeChild'. Nie są również rozgrywane żadne wydarzenia. Słuchacze mogą zostać rozbrojeni wraz z "widocznością" (tak jak przywrócono). –

+0

tak, żebyś mi powiedział, że jeśli mam stworzyć pętlę dodając 500 obiektów do sceny z listerami, kiedy są niewidoczne, listy po prostu znikną? Są one nadal przywoływane w pamięci, dopóki nie staną się widoczne, ale usunięcie elementów zniszczy wszystkie ich zasoby z pamięci – joshua

+0

nie dokładnie; 'removeChild' lub' visible = false' na 500 obiektach - słuchacze nadal tam będą. Jedyną różnicą w kompilacjach 'visible = false' i' removeChilded' jest to, że pierwszy dostaje zdarzenia na scenie; drugi - nie. Co rozumiem przez "żadne wydarzenia nie zostały stworzone" - jest to, że 'niewidzialne = fałsz' nie odradza niczego. 'addChild' i' removeChild' - tworzą zdarzenia odradzania. –