Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Регистрация Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > FlashImp

Оценить эту запись

[Collections] Структуры данных: MagicObject

Запись от ~~~ размещена 29.12.2011 в 19:35
Обновил(-а) ~~~ 30.12.2011 в 01:41 (грамматика)

Название MagicObject, имхо, явно лучше E4XMap и подобных названий.

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

Сегодня хочу поделиться простенькой реализацией e4x в Объекте, где основной фишкой является расширение нативного e4x, который не позволяет callDescendants.

Например вот так:
Код AS3:
object..method(args)
Зачем это нужно?
Допустим, дано:
- StateMachine и сложное дерево состояний;
- Анимация игрового объекта завязана на состояния, точнее, на смены состояний;
- Есть VO (ValueObjects) и есть рендеры, которые визуализируют изменения в VO;
- Рендеры имеют сложную иерархию, уровни вложенности.

Как происходит изменение состояния и отображение изменений при использовании MagicObject:
- Изменяем состояние в StateMachine;
- При удачном изменении состояния обновляем данные в VO;
- Вызываем обновление во всех рендерах внутри игрового уровня:
Код AS3:
// 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.
На примере:
Код AS3:
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:

Код AS3:
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();
Уведомления об изменениях:
Создали экземпляр:
Код AS3:
const magic:MagicObject = new MagicObject();
Дали ссылку на колбэк:
Код AS3:
magic.notificationCallback = function():void
	{
		trace('new changes:', magic.changes);
	}
или так:
Код AS3:
magic.notificationCallback = function(changes:Vector.<MagicNode>):void
	{
		trace('new changes:', changes);
	}
сделали какие-то изменения:
Код AS3:
magic.x = 0;
magic.x = 1;
.. и мы сразу получаем эти изменения в колбэк.

Собственно сам класс лежит здесь.

Вот пример расширения на деле:
Код AS3:
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 Отправить другу ссылку на эту запись
Всего комментариев 15

Комментарии

Старый 29.12.2011 22:02 fljot вне форума
fljot
Не думал ребятам в as3-commons collections написать?

расширения
Старый 29.12.2011 22:18 ~~~ вне форума
~~~
 
Аватар для ~~~
Нет, пока не думал, но всё возможно. Я as3-commons давно пользуюсь. Думается, они слишком патриотичны, чтоб такую штуку внедрять - у них всё очень Java-style.

Цитата:
расширения
Косяк. Меня вот этот гад в заблуждение ввёл. Спасибо, поправил.
Обновил(-а) ~~~ 30.12.2011 в 01:35
Старый 30.12.2011 17:07 dimarik вне форума
dimarik
 
Аватар для dimarik
Кстати, как там дела с типизацией и отловом досадных недоразумений в compile time? Я просто очень рассеянный и не очень люблю синтаксический сахар.

Цитата:
расширения
Это неграмотная братия заблудилась на два порядка. Сравните в гугле количество совпадений для "с" и "з".
Старый 30.12.2011 17:15 crazyone вне форума
crazyone
 
Аватар для crazyone
Использовать прокси и отлавливать что-либо на этапе компиляции? Не на этой планете.
Старый 30.12.2011 17:52 dimarik вне форума
dimarik
 
Аватар для dimarik
Да, очень похоже, что вы правы.
Старый 31.12.2011 15:36 etc вне форума
etc
 
Аватар для etc
_notificationCallback && (_notificationCallback.length ? _notificationCallback(changes) : _notificationCallback());

:facepalm:
Старый 01.01.2012 19:35 ~~~ вне форума
~~~
 
Аватар для ~~~
etc: В чём дело-то, Денис?
Старый 02.01.2012 01:25 in4core вне форума
in4core
 
Аватар для in4core
В чем в чем... face palm ) Ну криво написано незя так...
Старый 02.01.2012 12:50 mayakwd вне форума
mayakwd
 
Аватар для mayakwd
Код AS3:
private function getFrameByNumber(num:uint):Frame {
	for (var i:int = 0; i < this.framesCount; i++) {
		if (this._vFrames[i].number == num) return this._vFrames[i];
	}
	return null;
}
Старый 02.01.2012 13:31 etc вне форума
etc
 
Аватар для etc
Как в чём, использование непредсказуемого логического оператора в качестве последовательности действий — фейспалм.
Старый 02.01.2012 13:34 cleptoman вне форума
cleptoman
 
Аватар для cleptoman
Илюх, ты уточняй из какого классического произведения эта цитата, а то автор не поймет что это и зачем )
Старый 02.01.2012 18:07 ~~~ вне форума
~~~
 
Аватар для ~~~
Цитата:
непредсказуемого логического оператора в качестве последовательности действий
Что тут непредсказуемого? function.length - всегда есть количество аргументов, за исключением ситуации f(...rest:Array) - тогда f.length = 0. Прошу подробнее, блин, указать на ошибку.
Старый 02.01.2012 21:05 etc вне форума
etc
 
Аватар для etc
Нет ошибки, есть вредная привычка сокращать выражения из-за бесконечной лени.
Старый 06.01.2012 20:23 ~~~ вне форума
~~~
 
Аватар для ~~~
2 ect: OK. Я уж думал косяк где.. Лень - двигатель прегресса. Лет через незнаю сколько, но мы до этого доживём, мы будем писать что-то вроде:
Код AS3:
compiller.readMyMind(mindFlow);
Старый 06.01.2012 20:47 Jewelz вне форума
Jewelz
 
Аватар для Jewelz
главное чтобы в mindFlow не встретился неожиданно end of file
 

 


Часовой пояс GMT +4, время: 07:21.


Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.