Как бороться c утечками памяти при загрузке внешних swf-модулей рассказано в блоге Максима Фирсова:
http://snzflash.com/blog/?p=54
http://snzflash.com/blog/?p=54
/** * Рисует 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-движков тоже сгодится.
ping localhost -n <примерное время в секундах>
C:\Project>svn up & ant secureClient & ant
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, на мой взгляд, не лучшим образом отфотканных ракурсов.
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); } }
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Необходимые для конкретного языка шаблоны форматирования хранятся в соответствующих файлах. Вытягивать и хранить это все можно способом описанным в этом посте. Например:
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"); } }
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); } } } }
public class AppOption { public static const REVISION:String = "@revision@"; }
<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>
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; } }
function removeAllChilds(container:DisplayObjectContainer):void { while (container.numChildren) { container.removeChildAt(0); } }
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(); } }
function getClassRef(instance:Object):Class { return getDefinitionByName(getQualifiedClassName(instance)) as Class; }
function getClassRef(instance:Object):Class { return Object(instance).constructor as Class; }
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("а так"); } }