среда, 21 декабря 2011 г.

LoaderContext, утечки памяти (ActionScript)

Как бороться c утечками памяти при загрузке внешних swf-модулей рассказано в блоге Максима Фирсова:
http://snzflash.com/blog/?p=54

Программное создание transparency grid, check-текстуры/заливки (ActionScript)

Преамбула:
Частенько, для проверки объектов с прозрачностью, нужно было подкладывать что то пёстрое под них для того, чтобы лучше их визуально оценить. Приходилось каждый раз делать каляки-маляки в graphics низлежащего Shape/Sprite-а.
Не соврать, подобные каляки называются "transparency grid" или check-текстурой/заливкой в случае 3D-контекста.

Проблема:
Не заморачиваясь, легко и задорно создавать "transparency grid" в поданном на вход экземпляр Graphics.

Решение:
Не мудрствуя лукаво, решил сделать "transparency grid" как в фотошопе + задать возможность кастомизации параметров этой текстуры (на всякий случай).

Конечный результат приведенного ниже кода:

transparency grid
/**
 * Рисует check-текстуру
 * @param   canvas - экземпляр класса Graphics
 * @param   width - ширина требуемой текстуры
 * @param   height - высота требуемой текстуры
 * @param   cellSize - размер ячейки
 * @param   cellColors - массив с цветами для нечетной и четной ячеек в формате RGBA
 * @param   lineColor - цвет линии между ячейками в формате RGBA
 */
public function drawCheckFill(canvas:Graphics, width:Number, height:Number, cellSize:Number, cellColors:Array = null, lineColor:uint = 0x080808FF):void
{
   var colors:Array = cellColors || [0x111111FF, 0x202020FF];
   colors = colors.slice(0, 2);
   
   var cols:int = int(width / cellSize);
   var rows:int = int(height / cellSize);
   var color:uint = 0;
   for (var i:int = 0; i < cols; i++) 
   {
      for (var j:int = 0; j < rows; j++) 
      {
         color = colors[(i + j) % 2];
         canvas.beginFill(color >> 8, (color & 0x000000FF) / 0xFF);
         canvas.drawRect(i * cellSize, j * cellSize, cellSize, cellSize);
      }
   }
   canvas.endFill();

   canvas.lineStyle(1, lineColor >> 8, (lineColor & 0x000000FF) / 0xFF, true, LineScaleMode.NORMAL, CapsStyle.NONE);
   for (i = 0; i < cols; i++) 
   {
      canvas.moveTo(i * cellSize, 0);
      canvas.lineTo(i * cellSize, rows * cellSize);
   }
   
   for (i = 0; i < rows; i++) 
   {
      canvas.moveTo(0, i * cellSize);
      canvas.lineTo(cols * cellSize, i * cellSize);
   }
}      

var shape:Shape = new Shape();
drawCheckFill(shape.graphics, 170, 170, 8, [0XFFFFFFFF, 0xCCCCCCFF], 0);
P.S.: Кстати для создания текстур для материалов 3D-движков тоже сгодится.

воскресенье, 18 декабря 2011 г.

Пара приемов для windows-консоли (Windows, console)

Прием #1

Преамбула:
Как то давно стояла задача со следующей последовательностью действий:
  1. В БД Oracle запускался по шедулеру таск который брал файл(ы) из определенной директории, парсил их и складывал данные в таблицы, после чего запускался bat-файл который выполнял пункты ниже.
  2. Перенос файлов в zip/rar-архив.
  3. Перенос архивов в бекапную папку.
Так вот, экспериментальным путем было установлено, что надо делать небольшую паузу между п.2 и п.3 (видимо архиватор к моменту запуска п.3 не успевал "отпустить" архив).

Проблема:
Сделать паузу скушать твикс между задачами в bat-файле.

Решение:
Т.к. для паузы в батнике я ничего стандартного не нашел (какойнить wait, delay, sleep), то применил вот такой финт ушами:
ping localhost -n <примерное время в секундах>

Прием #2

Преамбула:
Есть задача со следующей последовательностью действий:
  1. Обновить проект (на тему появления новых строковых и графических ресурсов).
  2. Пройтись обфускатором по уже откомпеленному клиенту. (task secureClient)
  3. Залить клиента и ресурсы на сервер. (task upload)
п.2 и п.3 прописаны в ant-товском build.xml наряду с дугой кучей тасков.
Дефолтный таск = upload.
Т.к. описанные выше действия выполняются редко (максимум один раз в 1-2 недели по N-раз в день), то отчего то не хотелось отдавать это ant-у и без того замусоренного.

Проблема:
Выполнить последовательность действий одним "телодвижением".

Решение:
C:\Project>svn up & ant secureClient & ant

четверг, 23 июня 2011 г.

Scale9 (slice9) для растровых изображений во Flash IDE

Преамбула:
...и это должно было произойти. Понадобилось сделать универсальную кнопку с тянущимся битмапным фоном, но не тут то было. Как оказалось на битмапы scale9 увы не работает.

Проблема:
Сделать так, чтобы мувик фона для кнопки с битмапным содержимым тянулся так же как и с векторным.

Решение:
Как зачастую бывает, помог наш добрый-умный интернет, тов. gskinner и его пост в блоге в частности. За что ему большое спасибо, gand thanks, muchos gracias, ...

Пост: http://gskinner.com/blog/archives/2010/04/bitmapslice9_sc.html
Пример: http://gskinner.com/blog/assets/BitmapSlice9/BitmapSlice9.zip
Наглядный пример:
slice9

пятница, 15 апреля 2011 г.

Использование карты прозрачности (ActionScript)

Преамбула:
Заказали как то раз сварганить флешку назначение которой было простое: обеспечить возможность всестороннего разглядывания новой упаковки, с достаточно фотореалистичным отображением. Т.к. нужен всесторонний обзор, решено было крутить-вертеть упаковку в 3D пространстве.

В качестве движка заюзал, всеми горячо любимый (особенно после нового лицензионного соглашения, разрешающего свободное его использование), движек Alternativa3D. Особенно кстати пришлась вышедшая, к началу работы над проектом, версия 7.7. Где были добавлены новые материалы, свет и проч.

Модель во флешке собирается в рантайме, т.е. подгружаются/вкоприливаются необходимые ресурсы (3DS-модель + текстуры), средствами движка парсится модель, на основе текстур создаются соответствующие материалы, все это накладывается/состыковывается.

Встала проблема с прозрачностью некоторых материалов, а именно материала покрывающего большую часть модели (упаковка полупрозрачная). В библиотеке движка есть такой полезный класс как MaterialLoader, которому нужно скормить Vector из экземпляров класса TextureMaterial или его потомков с предварительно заполненными полями (урл дифузной текстуры, урл текстуры карты прозрачности, ...). Т.к. создание материалов идет "вручную", то MaterialLoader мне показался плохим помощником. В башке зародилась мысля, а что если в качестве дифузной текстуры скормить предварительно подготовленную текстуру с наложенной картой прозрачности. Осталось дело за малым - наложить эту самую карту прозрачности.

Проблема:
Применить к текстуре карту прозрачности.

Решение:
Родился единственный метод который эту карту накладывает.
private function overlayOpacityMap(texture:BitmapData, opacityMap:BitmapData):BitmapData
{
   if (!opacityMap)
      return texture;
   
   var retval:BitmapData = new BitmapData(texture.width, texture.height, true, 0xffffffff);
   
   retval.copyPixels(texture, new Rectangle(0, 0, texture.width, texture.height), new Point());
   
   var textureColor:uint;
   var opacityColor:uint;
   for (var px:int = 0; px < retval.width; px++) 
   {
      for (var py:int = 0; py < retval.height; py++) 
      {
         textureColor = retval.getPixel32(px, py);
         opacityColor = opacityMap.getPixel(px, py);
         
         opacityColor &= 0x0000ff;
         textureColor &= 0x00ffffff;
         textureColor |= (0xff - opacityColor) << 24; 
         
         retval.setPixel32(px, py, textureColor);
      }
   }
   
   return retval;
}
В результате волшебных пассов результат получился достаточно достойным и фотореалистичным, жаль заказчик не понял всю "тяжесть, степень, глубину" и в финальной стадии разработки принял решение заменить 3D на секвенцию из 30, на мой взгляд, не лучшим образом отфотканных ракурсов.
В дополнение к выше сказанному привожу скриншот демо-проектика(used FlashDevelop) демонстрирующего наложение карты прозрачности на изображение.

В ходе написания данного поста, вспомнил, что видел где-то данный подход для эмуляции (назову её так) изображений в формате PNG с прозрачностью, и это надо сказать очень эффективно в плане трафика и места для хранения изображений аля png, по другим параметрам может и уступает.

По использованным в демо-проекте изображениям картина выглядит так:
  1. исходное изображение (jpg) + серая карта прозрачности (jpg) = 29.8 + 15.7 = 45.4 Кб
  2. исходное изображение (png) = 155.8 Кб

Простая схема защиты от "кидалова" со стороны заказчика/клиента (ActionScript)

Преамбула:
Буквально на днях закончил один прожект который делался конечному клиенту через посредника веб-студию. Т.к. с моим непосредственным заказчиком (веб-студией) я имел первый опыт (мозготрах) работы, то зародились сомнения, а не кинут ли (тьфу х3, пока такого ни разу не случалось).
В общем решил хоть как то предохранится от возможного конфуза.

Проблема:
По быстрому/простому включить в проект блокировку, в случае если клиент не расплатится за заказ в оговоренный с ним срок или прихватизирует проект на финальном этапе разработки.

Решение:
Идея думаю далеко не нова, но как говорится, свой "велосипед" ближе к телу :) (давно хочу обзавестись железным великом, да все никак да не эдак).
Решил включить код, который бы обращался по определенному адресу и запрашивал определенный ресурс и исходя из полученного результата "блокировал" флешку.
Вначале хотел запрашивать URLLоader-ом в качестве ресурса текстовый файл или php-скрипт который выдавал например слово "trusted", но из-за танцев вокруг секьюрности решил отказаться от этой затеи и воспользоватся "добрым" Lоader-ом.

Итого:
1. ресурс - gif-файл 1х1 пиксель (35 байт);
2. хостинг - публичная папка Dropbox-а (если решите воспользоватся этим сервисом, могу прислать инвайт на регпочту, обоим к положенным 2 гигам по 250 метров накинут);
3. выбрана схема блокировки по наличию ресурса, а не по его отсутствию (т.к. флешку могут просматривать локально, внутри ethernet, проблемы с хостингом и т.п.).

Реализация:
public class TrustChecker
{
   private var _stage:Stage;
   
   public function TrustChecker(stage:Stage) 
   {
      _stage = stage;
      
      var loader:Loader = new Loader();
      loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
      loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
      loader.load(new URLRequest("http://myurl.com/trust.gif?" + (new Date().getTime())));
   }
   
   private function onError(e:Event):void 
   {
      var target:LoaderInfo = e.target as LoaderInfo;
      target.removeEventListener(Event.COMPLETE, onComplete);
      target.removeEventListener(IOErrorEvent.IO_ERROR, onError);
   }
   
   private function onComplete(e:Event):void 
   {
      var target:LoaderInfo = e.target as LoaderInfo;
      target.removeEventListener(Event.COMPLETE, onComplete);
      target.removeEventListener(IOErrorEvent.IO_ERROR, onError);
      
      // вот тут то можно дать волю своей фантазии для донесения мысли заказчику
      var shape:Shape = new Shape();
      shape.graphics.beginFill(0x000000);
      shape.graphics.drawRect(0, 0, _stage.stageWidth, _stage.stageHeight);
      shape.graphics.endFill();
      _stage.addChild(shape);
   }
   
}

Защита достаточно тривиальна и прошаренный заказчик её в 5 сек обойдет, отредактировав байт код или декомпилировав флеху (от этого может в какой то степени спасти укус хорошего обфускатора secureSWF).

понедельник, 21 февраля 2011 г.

Форматирование даты/времени (ActionScript)

Преамбула:
От так вот неожиданно случилось, что в приложении стало необходимо выводить дату в формате диктуемым языком интерфейса (почти как в случае с настройками локали). Проблема скажем тривиальная. Есть наверняка куча всяких форматтеров, из которых на скоряк попался флексовый (была идея портировать явовский, но там тоже как то все мутно). Но т.к. приложение на чистом ас3, то очень не хотелось таки цеплять флексовые либы и прочее, тем более флексовый форматтер юзает еще какие то классы из либ. Был бы он "сам в себе" взял бы не раздумывая, но увы и ах...

Проблема:
Применять разное форматирование даты/времени в зависимости от языковых настроек интерфейса.

Решение:
По сути требовалось форматирование даты в нашем и буржуйском формате (например: 21.02.2011 или 02/21/2011) и время в 24-часовом формате для всех языков оставить (пока).
Долго не мудрствуя родился ниже приведенный класс с несложной, но готовой к расширению, функциональностью.

public class DateFormatter
{
  private static const MAP_TOKENS:Object = new Object();
  
  private static const DATE:Date = new Date();

  /// метод форматирования №1
  public static function formatDate(date:Date, pattern:String):String
  {
    DATE.setTime(date.getTime());
    return format(DATE, pattern);
  }
  
  /// метод форматирования №2
  public static function formatTimestamp(timestamp:Number, pattern:String):String
  {
    DATE.setTime(timestamp);
    return format(DATE, pattern);
  }
  
  private static function format(date:Date, pattern:String):String
  {
    DATE.setTime(date.getTime());
    
    var tokens:Array = [];
    
    for (var token:String in MAP_TOKENS) 
    {
      if (pattern.indexOf(token) != -1)
         tokens.push(token);
    }
    
    
    var retval:String = pattern;
    for each (token in tokens) 
    {
      retval = retval.replace(token, (MAP_TOKENS[token] as Function).apply());
    }
    
    return retval;
  }
  
  private static function formatSeconds():String
  {
    return leadZero(DATE.getSeconds());
  }
  
  private static function formatMinutes():String
  {
    return leadZero(DATE.getMinutes());
  }
  
  private static function formatHours():String
  {
    return leadZero(DATE.getHours());
  }
  
  private static function formatFullYear():String
  {
    return leadZero(DATE.getFullYear());
  }
  
  private static function formatDay():String
  {
    return leadZero(DATE.getDate());
  }
  
  private static function formatMonth():String
  {
    var month:int = DATE.getMonth() + 1;
    return leadZero(month);
  }
  
  private static function leadZero(value:int):String
  {
    return (value < 10 ? "0" : "") + value.toString();
  }
  
  
  // блок статической инициализации
  {
    MAP_TOKENS["MM"] = formatMonth;
    MAP_TOKENS["DD"] = formatDay;
    MAP_TOKENS["YYYY"] = formatFullYear;
    MAP_TOKENS["hh"] = formatHours;
    MAP_TOKENS["mm"] = formatMinutes;
    MAP_TOKENS["ss"] = formatMinutes; 
  }
}
Пример использования:
var sysdate:Date = new Date();
trace(DateFormatter.formatDate(sysdate, "DD.MM.YYYY"); // 21.02.2011
trace(DateFormatter.formatDate(sysdate, "MM/DD/YYYY"); // 02/21/2011
trace(DateFormatter.formatDate(sysdate, "MM/DD/YYYY hh:mm:ss"); // 02/21/2011 14:26:01
trace(DateFormatter.formatDate("hh:mm:ss"); // 14:26:01
// или так можно, но только осторожно
trace(DateFormatter.formatDate("Today is DD.MM.YYYY"); // Today is 21.02.2011
Необходимые для конкретного языка шаблоны форматирования хранятся в соответствующих файлах. Вытягивать и хранить это все можно способом описанным в этом посте. Например:

   
 

   
    

   
 

понедельник, 7 февраля 2011 г.

Загрузка параметров приложения в зависимости от языковых настроек (ActionScript)

Преамбула:
Для мультиязыкового приложения наверняка многие пользовались классом fl.lang.Locale с помощью которого в приложение подгружаются строковые ресурсы на нужном языке. Возникла необходимость аналогично строковым, сохранять и в последствии подгружать койкакие настройки приложения в зависимости от языка, например: имя дефолтного шрифта или имя метки кадра для фона главного экрана.

Проблема:
Использование различных настроек приложения в зависимости от языка.

Решение:
За основу взят все тот же класс fl.lang.Locale, т.к. обладает всем необходимым функционалом. Более того его можно было использовать для решения данной проблемы, но я отказался от него по 2-м причинам: 1. в проекте уже используется этот класс для подгрузки строковых, 2. модель ключ-значение превращает xml-"конфиг" в одну сплошную кучу.
И так, немного поработав напильником, появился класс (не претендующий на оригинальность или что то еще в этом духе) LocaleSettings (заранее прошу прощения за мусор в комментариях, остались от Locale).

Пример xml-я который кушает этот класс:


      
         Arial
       

      
         bg_en
       

      
         BTN_ACCEPT;BTN_OK;BTN_CANCEL
       

      
         BTN_BUY;BTN_CANCEL
       


Пример использования:
const DEFAULT_LANG:String = "ru";

LocaleSettings.setDefaultLang(DEFAULT_LANG);
LocaleSettings.addXMLPath(DEFAULT_LANG, "settings/set_" + DEFAULT_LANG + ".xml"); // связываем язык с путем xml-файла

var language:String = (loaderInfo.parameters.lang ? loaderInfo.parameters.lang : DEFAULT_LANG);

LocaleSettings.addXMLPath(language, "settings/set_" + language + ".xml");
LocaleSettings.loadSettingsXML(language, languageXMLLoaded); // запускаем загрузку файла с настройками

...

private function languageXMLLoaded(success:Boolean):void
{
   if (LocaleSettings.checkXMLStatus())
   {
      // пользуем загруженные настройки
      mainScreen.setBg(LocaleSettings.loadSetting("client", "bg_frame_label");
   }
}

Примечания:
  1. Файл с настройкам для языка по умолчанию 100% должен быть (на то он и по умолчанию)
  2. В случае если для заданного языка не нашлось настоечного файла (как по причине его фактического отсутствия так и в случае ошибки в именовании языкового кода), будет загружен файл для языка по умолчанию.

четверг, 3 февраля 2011 г.

Трансляция видео mjpeg-потока (ActionScript, MJPEG)

Преамбула:
Наклевывался как то один заказик от охранной конторы. Типа забубенить плеер для показа видео с камер наблюдения с возможностью просмотра видео как в режиме он-лайн, так и в офф-лайн. В офф-лайн было все понятно, просто гнать с сервера записанное видео, проблема встала с режимом он-лайн трансляции. У заказчика использовались ip-камеры, которые отдают видео в виде mjpeg-потока и решение проблемы трансляции mjpeg-потока я таки нарыл.

Проблема:
Трансляция mjpeg-потока в flash-приложении.

Решение:
Помощники: flasher.ru, codeproject.com
package  
{
   import flash.display.*;
   import flash.events.Event;
   import flash.events.ProgressEvent;
   import flash.net.*;
   import flash.utils.*;

   public class VideoMJPEG extends Sprite
   {
      private var _stream:URLStream = new URLStream();
      private var _loader:Loader = new Loader()
      private var _buffer:ByteArray;
      private var _write:Boolean = false;   
      private var _markerDetection:Boolean = false;   
      private var _request:URLRequest = new URLRequest("http://146.176.65.10/axis-cgi/mjpg/video.cgi");

      public function VideoMJPEG()
      {
         mouseEnabled = false;
         mouseChildren = false;
         addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
      }
      
      private function onAddedToStage(e:Event):void 
      {
         removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
         
         addChild(_loader);
         
         _stream.load(_request);
         _stream.addEventListener(ProgressEvent.PROGRESS, onProgress);
      }
      
      private function onProgress(event:ProgressEvent):void
      {
         var byte:int;

         // Если есть доступные байты - обработать их 
         while(_stream.bytesAvailable > 0)
         {
            byte = _stream.readUnsignedByte();
            if(_write) _buffer.writeByte(byte);
            if(_markerDetection)
            {
               switch(byte)
               {
                  case 0xD8:
                     _write = true;
                     _buffer = new ByteArray();
                     _buffer.writeByte(0xFF);
                     _buffer.writeByte(0xD8);
                  break;
                  case 0xD9:
                     _write = false;
                     _buffer.writeByte(0xD9);
                     _loader.loadBytes(_buffer);
                  break;
               }
 
            }
            _markerDetection = (byte == 0xFF);
         } 
      }
   }
}

Прим.: используемый в примере url реальный, можно прям в браузере видео-поток посмотреть.

UPD: Был как то случай с получением mjpeg-потока с камеры которая требовала базовую авторизацию, как это сделать описано в посте Доступ к ресурсам защищенным Basic authentication.

среда, 2 февраля 2011 г.

Сохранение номера ревизии в приложении (ActionScript, SVN)

Ниже описанный подход применён в контексте ActionScript-проекта находящемуся под контролем SVN. "Не ActionScript-ом единым жив программист", это подход может пригодится в других проектах с другими CSV-системами.

Проблема:
При достаточно частых обновлениях приложения в сети, хочется визуально видеть какая версия флешки перед тобой, т.е. получить подобную картинку:



Решение:
  1. Определить место, где будет сохранятся номер ревизии, например отдельный класс с настройками приложения или одно из полей уже существующего класса
    Пример класса для первого варианта:
    public class AppOption 
    {
       public static const REVISION:String = "@revision@";
    }
    
  2. Описать ant-овский task в build.xml
    <target name="buildClient">
       <!-- копируем оригинал файла где будет производится замена строки -->
       <copy file="${src}/AppOption.as" tofile="${projectDir}/AppOption.as" overwrite="true" verbose="false" />
    
       <!-- впечатываем номер ревизии по-вкусу, в данном случае последней закомиченой-->
       <property name="revision" value="COMMITTED"/>
       <exec executable="svn" outputproperty="svnlog.out">   
          <arg line="log -r ${revision} -q"/>
       </exec>
       
       <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
       <propertyregex property="revision.number" input="${svnlog.out}" select="\2">
          <regexp pattern="(r)([0-9]*)"/>
       </propertyregex>
       <replace file="${src}/AppOption.as" token="@revision@" value="${revision.number}"/>
    
    <!-- компилируем клиента -->
    
       <!-- перемещаем оригинал файла на родину -->
       <move file="${projectDir}/AppOption.as" tofile="${src}/AppOption.as" overwrite="true" verbose="false"/>
    </target>
    
  3. И наконец использовать номер ревизии
    public class Main extends Sprite 
    {
       private var _contextMenu:ContextMenu;
    
       public Main()
       {
          addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
       }
       
       private function onAddedToStage(e:Event):void
       {
          removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
          _contextMenu = new ContextMenu();
          var menuItem:ContextMenuItem = new ContextMenuItem("Version " + AppOption.REVISION);
          _contextMenu.customItems.push(menuItem);
          contextMenu = _contextMenu;
          
       }
    }
    
Номер ревизии можно использовать не только для визуального контроля версии приложения, но и в качестве антикеша ("http://anysite.com/logo.png?" + AppOption.REVISION) при подгрузке внешних ресурсов, которые могут быть изменены при публикации новой версии приложения.
P.S.: Очень полезно про автоматизацию с испольщованием ant-а см. на http://anykeytocreate.blogspot.com/2011/08/1-ant-flash-faq.html

вторник, 1 февраля 2011 г.

Отправка сообщений в Skype через консоль

Лень – двигатель прогресса.

Есть такой техпроцесс:

  • скомпилить проект
  • залить скомпиленую флешку и подгружаемые в неё ресурсы на сервера
  • оповестить через Skype всех заинтересованных пряников, что мол "приложение выложено на кудыкину гору и гору где рак вот вот свистнет" 

Исполняет все это, кроме последнего пункта, наш дорогой и все еще горячо любимый ant.

Время занимаемое этим процессом колеблется от 5 до 20 минут (в зависимости от количества серверов куда выкладывается контент и того насколько давно обновлялся этот самый контент). В общем в один прекрасный солнечный денек начались сильные ломки по поводу последней стадии процесса, а именно, оповещения об окончании выкладки. Немного поискав в интернетах, я не нашел подходящего решения как это можно было бы заделать. Но нарыв в сети небольшой мешочек нужных библиотек, заваял простенькое консольное java-приложение.

Обитает оно на гуглокоде.
Пользоваться можно как отдельно в консоли, так и в качестве антовского task-а.

Удаление всех дочерних DisplayObject-ов в DisplayObjectContainer-е (ActionScript)

function removeAllChilds(container:DisplayObjectContainer):void
{
   while (container.numChildren)
   {
      container.removeChildAt(0);
   }
}

Для того чтобы удаляемые объекты не засирали память, не оставалось покинутых листенеров и запущенных таймеров, а так же другого мусора, рекомендую во всех классах расширяющих DisplayObject реализовать следующий интерфейс:
public interface IDisposable 
{
   function dispose():void;
}

В этом единственном методе можно заключить блок кода который бы делал предсмертные операции по освобождению занятых ресурсов.
Если вы не намерены повторно использовать удаляемые объекты то можно воспользоватся немного модифицированным циклом очистки.
function removeAllChilds(container:DisplayObjectContainer):void
{
   var removableObject:DisplayObject;
   while (container.numChildren)
   {
      removableObject = container.removeChildAt(0);
      if (removableObject is IDisposable)
         (removableObject as IDisposable).dispose();
   }
}

Получение ссылки на класс объекта по его экземпляру (ActionScript)

Получить ссылку на класс можно одним из способов описанных ниже.


  1. function getClassRef(instance:Object):Class
     {
      return getDefinitionByName(getQualifiedClassName(instance)) as Class;
     }
    

  2. function getClassRef(instance:Object):Class
     {
      return Object(instance).constructor as Class;
     }
    
Второй вариант хоть и не документирован адобами, но имеет право на жизнь (уж не знаю на долгую ли, по крайней мере в последнем флешплеере она все еще фурычит).

Теперь по производительности...
Вариант №2 примерно в 4 раза быстрее (проверено на 100'000 итерациях), да и выглядит как то краше и без лишних вызовов.

Эту возможность я использовал в проекте в месте, где в зависимости от поданного экземпляра объекта нужно произвести те или иные действия, пример:
function polymorphAction(instance:Object):void
{
 var clazz:Class = Object(instance).constructor as Class;
 switch (clazz)
 {
  case Friend:
   trace("друг");
   break;
   
  case Enemy:
   trace("враг");
   break;
  default:
   trace("а так");
 }
}

И так, поехали!

Дорогой читатель!
Как водится/обычно/часто/иногда, первое сообщение являет собой текст аля "Здравствуйте! Меня зовут Эммануил Гидэоныч, я анонимный алкоголик. (жидкие аплодисменты, редкие томные вздохи в зале)". Не отступлю и я от этого обычая.

По стечению маловероятных обстоятельств, я - программист, да да это тот человек который руководит, хоть и косвенно, прибором который  намагничивает быстро вращающиеся диски.
В этом мне помогают товарищи: as3, java, action script, flash, sql, pl/sql, postgresql db, oracle db, oracle forms, delphi, бубен, вера в чистое-доброе-мягкое and more.

Частью адреса этого блога (profdiletant...) хочу признать, что отношу себя к легиону профессиональных дилетантов (неплохое мне кажется определеньице).
В настоящий момент тружусь на ниве ActionScript 3 программирования. После НГ решил освежить в себе знания по такой мегаштуке как  Java.

Данный блогнот завел исключительно в целях сохранения битов информации, которые будут полезны как писателю этих строк (т.е. для меня), так, я надеюсь, и для читателя (т.е. для тебя) этих же строк. Писать буду как на связанные с намагничиванием быстро вращающихся дисков, так и не связанные с этим темы.

За русский/орфографию/пунктуацию/стилистику сильно не бранить, ибо и во ибо, у меня не твердая 4ка по русскому ;)

– До скорых встреч! - сказал он, всматриваясь через яркий свет софитов, в черную пустоту не видя адресатов.