[Collections] Структуры данных: MagicObject
Название MagicObject, имхо, явно лучше E4XMap и подобных названий.
В играх я частенько использую машины состояний и сложные структуры данных (коллекции, карты..) , сильно упрощающие разработку. Что актуально, кстати, не только для игр, но для риа вообще.
Сегодня хочу поделиться простенькой реализацией e4x в Объекте, где основной фишкой является расширение нативного e4x, который не позволяет callDescendants.
Например вот так:
Зачем это нужно?
Допустим, дано:
- 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);
Поясню как работает:
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]();
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();
Создали экземпляр:
Дали ссылку на колбэк:
или так:
magic.notificationCallback = function(changes:Vector.<MagicNode>):void { trace('new changes:', changes); }
.. и мы сразу получаем эти изменения в колбэк.
Собственно сам класс лежит здесь.
Вот пример расширения на деле:
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()); } } }
Комментарии, идеи и замечания очень приветствуются. Надеюсь, кому-то это пригодится.
Всего комментариев 15
Комментарии
29.12.2011 22:02 | |
Не думал ребятам в as3-commons collections написать?
расширения |
29.12.2011 22:18 | |
Нет, пока не думал, но всё возможно. Я as3-commons давно пользуюсь. Думается, они слишком патриотичны, чтоб такую штуку внедрять - у них всё очень Java-style.
Цитата:
расширения
|
|
Обновил(-а) ~~~ 30.12.2011 в 01:35
|
30.12.2011 17:15 | |
Использовать прокси и отлавливать что-либо на этапе компиляции? Не на этой планете.
|
30.12.2011 17:52 | |
Да, очень похоже, что вы правы.
|
31.12.2011 15:36 | |
_notificationCallback && (_notificationCallback.length ? _notificationCallback(changes) : _notificationCallback());
:facepalm: |
01.01.2012 19:35 | |
etc: В чём дело-то, Денис?
|
02.01.2012 01:25 | |
В чем в чем... face palm ) Ну криво написано незя так...
|
02.01.2012 12:50 | |
02.01.2012 13:31 | |
Как в чём, использование непредсказуемого логического оператора в качестве последовательности действий — фейспалм.
|
02.01.2012 13:34 | |
Илюх, ты уточняй из какого классического произведения эта цитата, а то автор не поймет что это и зачем )
|
02.01.2012 21:05 | |
Нет ошибки, есть вредная привычка сокращать выражения из-за бесконечной лени.
|
06.01.2012 20:23 | |
06.01.2012 20:47 | |
главное чтобы в mindFlow не встретился неожиданно end of file
|
Последние записи от ~~~