Структуры данных: MagicObject
source:
Название MagicObject, имхо, явно лучше E4XMap и подобных названий.
Intro.
В играх я частенько использую машины состояний и сложные структуры данных (коллекции, карты..) , сильно упрощающие разработку. Что актуально, кстати, не только для игр, но для риа вообще.
Сегодня хочу поделиться простенькой реализацией e4x в Объекте, где основной фишкой является расширение нативного e4x, который не позволяет callDescendants.
Например вот так:
object..method(args)
Зачем это нужно?
Допустим, дано:
- StateMachine и сложное дерево состояний;
- Анимация игрового объекта завязана на состояния, точнее, на смены состояний;
- Есть VO (ValueObjects) и есть рендеры, которые визуализируют изменения в VO;
- Рендеры имеют сложную иерархию, уровни вложенности.
Как происходит изменение состояния и отображение изменений при использовании MagicObject:
- Изменяем состояние в StateMachine;
- При удачном изменении состояния обновляем данные в VO;
- Вызываем обновление во всех рендерах внутри игрового уровня:
// magic = MagicObject instance // magic[keyA] = Renderer instance // magic[keyB] = Renderer instance // magic[keyB][keyC] = Renderer instance - sub-renderer // magic.subMagic.[keyD] = Renderer instance - sub-renderer (magic..update)(); // или так: (magic..update)(magic.changes);
Метод update() вызовется последовательно у всех объектов, имеющих этот метод.
Поясню как работает:
magic..update достаёт со всех уровней вложенности значения всех полей с именем update. Если там есть экземпляры класса Function, то всё это хозяйство оборачивается noname-фукцией, а ей задаются все свойства массива (для итеративного пробега) и пары, типа ключ-значение, где значение - каждое найденое поле с именем update.
На примере:
const result:Object = magic..update; // можно вызвать: result(); // or result(args); // можно получить определённый элемент: for(var key:String in magic) trace('in', magic, ':', key, '=', magic[key]), // или вызвать: magic[key] is Function && magic[key]();
History tracking:
const magic:MagicObject = new MagicObject(); magic.x = 0; magic.x = 1; // вернёт все изменения на первом уровней вложенности: trace(magic.changes); // :Vector.<MagicNode> // вернёт все изменения на всех уровнях вложенности: trace(magic..changes); // [:Vector.<MagicNode>,..] или Vector.<MagicNode> если элемент один. // чистим историю изменений: magic.clearChanges(); // or magic..clearChanges();
Уведомления об изменениях:
Создали экземпляр:
const magic:MagicObject = new MagicObject();
Дали ссылку на колбэк:
magic.notificationCallback = function():void { trace('new changes:', magic.changes); }
или так:
magic.notificationCallback = function(changes:Vector.<MagicNode>):void { trace('new changes:', changes); }
сдели какие-то изменения:
magic.x = 0; magic.x = 1;
.. и мы сразу получаем эти изменения в колбэк.
Собственно сам класс лежит здесь.
Вот пример расширения на деле:
package ru.kozlovskij.game.objects.data { import ru.kozlovskij.utils.data.MagicNode; import ru.kozlovskij.utils.data.MagicObject; /** * @author Aleksandr Kozlovskij (created: Dec 27, 2011) */ public dynamic class GameObjectData extends MagicObject { protected static const PRIVATE_ACCESSOR_PREFIX:String = '_'; private var _notificationCallback:Function; //------------ constructor ------------// public function GameObjectData() { super(); super.notificationCallback = __notificationCallback; } //------------ initialize ------------// //--------------- ctrl ---------------// //------------ get / set -------------// public function get selected():Boolean { return this._selected; } public function set selected(value:Boolean):void { this._selected = value; } override public function get notificationCallback():Function { return _notificationCallback; } override public function set notificationCallback(value:Function):void { _notificationCallback = value; } //------- handlers / callbacks -------// protected function __notificationCallback(changes:Vector.<MagicNode>):void { const ns:Namespace = nodeResetNS; for each(var node:MagicNode in changes) { const property:String = node.public::property; if(property.charAt() == PRIVATE_ACCESSOR_PREFIX) node.ns::property = property.substr(1); } // finally: _notificationCallback && (_notificationCallback.length ? _notificationCallback(changes) : _notificationCallback()); } } }
Получилось несколько сумбурно и возможно что-то забыл упомянуть.
Комментарии, идеи и замечания очень приветствуются. Надеюсь, кому-то это пригодится.
TexturePacker
Открыл для себя прекрасный генератор атласов тектур под OS X. Зовут "TexturePacker".
Бесплатен. И Про-версию раздают.
Фичи многообещающи.

Определятор статуса, типа и представления экранной клавиатуры.
Приветствую, коллеги.
Коротко о главном:
В комбинации AIR + iOS + {желание работать с текстом, клавой} есть одна большая проблема - это и есть большая проблема.
Предлагаю вам, товарищи, мой детектор статуса, типа и представления экранной клавиатуры. Только для iOS. Актуализирован для работы под iOS 5.0.

Он скажет вам:
Note:
Работает с обычными текстовыми полями и с новеньким StageText.
В симуляторе не работает и не должно, ибо он крив и только лживо симулирует. Только iOS.
Это не ANE. Only pure AS3.
Да, только библиотека SWC + демо-проект + дока.
Wallaby prerelease
Вышел обещанный н MAX'e фрэймворк для конвертации Flash-контента в HTML5.
На самом деле это AIR-приложение, сыренькое. Конвертируются только .FLA, состряпанные в Flash Pro CS5.
Link on labs. Help.
Adobe Flash Player 10.3 Beta
Flash Player 10.3 for Windows, Mac, and Linux introduces new developer features and enhanced user privacy protection, such as:
- Media Measurement
- Acoustic Echo Cancellation
- Integration with browser privacy control for local storage
- Native Control Panel
- Auto-Update Notification for Mac OS
Apple снимает ограничения для Flash – разработчиков.
Сегодня Apple сообщили, что ограничения в использовании средств разработки под iOS будут сняты.
"Мы снимаем все ограничения которые касаются средств разработки используемые для создания приложений под iOS, запрещенным остается только загрузка дополнительного кода созданным приложением. Это предоставит разработчикам больше свободы в выборе инструментов, в которых они нуждаются. В то же время безопасность приложений останется на том же уровне."
I’m alive. FlashImp too.
В последнее время я сильно погряз в болоте работы, сроки сдачи которой давно проебал. Собственно, в болоте этом я сижу все время, но обычно не больше чем по колено, а тут накрывает с головой. Тем не менее, я отчаянно барахтаюсь в попытке выбраться из отвратительной трясины лени и безответственности.
В скором времени начну выкладывать некоторые наработки, эксперименты, идеи.
UINativeWindow
package ru.kozlovskij.air { import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.NativeWindow; import flash.display.NativeWindowInitOptions; import flash.events.Event; import mx.core.IUIComponent; import mx.events.FlexEvent; import mx.managers.WindowedSystemManager; /** * Composition of <code>NativeWindow</code> and <code>IUIComponent</code>. * * @author Aleksandr.Kozlovskiy */ public class UINativeWindow extends NativeWindow { protected var systemManager:WindowedSystemManager; protected var childDisplayObject:IUIComponent; protected var rootDisplayObject:IUIComponent; /** * After initialization <code>childDisplayObject</code> added to <code>systemManager</code>'s displaylist. * * * @param initOptions:NativeWindowInitOptions - Analogically NativeWindow initOptions. * @param rootDisplayObject:IUIComponent - Root Application or other IUIComponent implementation. Mast extends DisplayObject. * @param childDisplayObject:IUIComponent - Container. Child Application or other IUIComponent implementation. Mast extends DisplayObject. * */ public function UINativeWindow(initOptions:NativeWindowInitOptions, rootDisplayObject:IUIComponent, childDisplayObject:IUIComponent) { super(initOptions); this.rootDisplayObject = rootDisplayObject; this.childDisplayObject = childDisplayObject; addChildren(); stage.addEventListener(Event.RESIZE, stageResizeHandler); } protected function addChildren():void { childDisplayObject.addEventListener(FlexEvent.CREATION_COMPLETE, childCreationCompleteHandler, false, 0, true); (stage.addChild(systemManager = new WindowedSystemManager(rootDisplayObject)) as DisplayObjectContainer) .addChild(childDisplayObject as DisplayObject); stageResizeHandler(); } protected function childCreationCompleteHandler(e:FlexEvent):void { childDisplayObject.removeEventListener(FlexEvent.CREATION_COMPLETE, childCreationCompleteHandler); stageResizeHandler(); } // ------------------ resize ----------------------- // protected function stageResizeHandler(e:Event = null):void { childDisplayObject.width = stage.stageWidth; childDisplayObject.height = stage.stageHeight; } } }

RAFPUG
UAFPUG
