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

Вернуться   Форум Flasher.ru > Flash > ActionScript 3.0

Версия для печати  Отправить по электронной почте    « Предыдущая тема | Следующая тема »  
Опции темы Опции просмотра
 
Создать новую тему Ответ
Старый 17.03.2016, 11:01
a7s1h1 вне форума Посмотреть профиль Отправить личное сообщение для a7s1h1 Найти все сообщения от a7s1h1
  № 1  
Ответить с цитированием
a7s1h1

Регистрация: Oct 2013
Сообщений: 126
Post проверьте, пожалуйста, пул

Здравствуйте!
Я наконец-то созрел для применения объектного пула. Проверьте, пожалуйста, пул ли у меня получился вообще и если да, правильно ли всё сделал?

Итак, есть объект "блок", вот его класс:
Код AS3:
package Objects  {
	import animation.AntActor;
	import flash.display.Sprite;
	import flash.events.Event;
	import rc.MyMath;
	import rc.TF;
	//@author 7_11
 
	public class Block extends Sprite {
 
		private var _img:AntActor
		private var _tree:AntActor;
		private var _text:TF;
 
		public var type:uint; // тип блока
 
		// CONSTRUCTOR
		public function Block() {
			_img = new AntActor(); // картинка блока
			_img.addAnimFromCache('Block_s') // присваивает изображение
			addChild(_img) //добавляем картинку
			// текстовое поле
			_text = new TF(40, 40, '' + type, 12 + type * 3, 'center', 0xffffff);
			addChild(_text);
 
			// ни объект, ни его дети не взаимодействуют с мышью
			mouseEnabled = false; 
			mouseChildren = false;
 
			addEventListener(Event.ADDED_TO_STAGE, init); // инициализация
			addEventListener(Event.REMOVED_FROM_STAGE, reset); // обнуление параметров при удалении со сцены
		};
 
		//INIT
		private function init(e:Event): void {
			// c вероятностью 15% создаём деревце
			if (MyMath.randomRange(0, 100) < 15) {
				_tree = new AntActor();
				_tree.addAnimFromCache('Tree_s');
				_tree.x = 40;
				addChild(_tree)
			}
			// обновляем текст, т.к. мог измениться тип блока (присваивается родителем, поэтому переменная type публичная)
			_text.update( '' + type);
		}
 
		// ОБНУЛЯЕМ ПАРАМЕТРЫ (при удалении со сцены)
		private function reset(e:Event): void {	
			// обнуляем параметры
			type = 0; // тип по умолчанию 0
                        // если есть деревце - удаляем его
			if (_tree) {
				_tree.free();
				//removeChild(_tree); // удалять дерево как ребёнка не нужно, метод free() заставил его удалиться само
				_tree=null;
			}
		};
 
		//CLEANUP (окончательная чистка при удалении со сцены родителя)
		public function cleanup(): void {
			// чистим слушателей
			removeEventListener(Event.ADDED_TO_STAGE, init);
			removeEventListener(Event.REMOVED_FROM_STAGE, reset);
                       // чистим акторов
			_img.free();
			_tree.free();
			// удаляем детей
			removeChildren();
			// обнуляем ссылки
			_img = null;
			_tree = null;
			_text = null;
		}
	};
};
В классе "world", который является родителем для всего, что находится и происходит в мире игры, есть два массива: с блоками, которые на сцене, и с пулом:
Код AS3:
private var _blocks:Vector.<Block>; 	// массив с блоками
private var _blocksPool:Vector.<Block>; // пул с блоками
При инициализации "мира" эти массивы создаются:
Код AS3:
_blocks = new Vector.<Block>(); 		// создаём массив блоков
_blocksPool = new Vector.<Block>(); 	// создаём пул блоков
в кадре проверяются все блоки на сцене и удаляются (переносятся в пул) те, которые оказались за краем. Вот кусок кода с удалением блока:
Код AS3:
...
put_block(b); // суём блок в пул
removeChild(b); // удаляем блок со сцены (при этом срабатывает внутренний метод блока reset() для обнуления параметров, но тех своих детей, которые нужны блоку всегда, он не удаляет)
_blocks.splice(i, 1); // удаляем блок 
...
А это кусок кода с добавлением блока из пула на сцену:
Код AS3:
...
var block:Block = get_block(); 		//берём последний блок из пула (в пуле его удаляем)
// присваиваем блоку координаты и тип
block.x = sx + BlockW * (b + 1);
block.y = GL;
block.type = _waves[wl][b];
// добавляем новый блок в масcив и на сцену
_blocks.push(addChild(block));
...
А это сами методы пула, которые я позаимствовал у Zebestov из вот этой темы:

Код AS3:
// Берём блок из пула
private function get_block():Block { 
	// если в пуле есть блоки - берём их оттуда, если нет - создаём
	return (_blocksPool.length) ? (_blocksPool.pop()) : (new Block());
}
 
// Кладём блок в пул
	private function put_block(block:Block):void {
_blocksPool[_blocksPool.length] = block;
}
Ну и наконец, чистка вектора и пула блоков при удалении со сцены класса "мира":
Код AS3:
// чистим массивы
var bl:int = _blocks.length;
for (var bi:uint = 0; bi < bl; bi++ ) { _blocks[bi].cleanup() };
_blocks.splice(0, _blocks.length);
var bpl:int = _blocksPool.length;
for (var bpi:uint = 0; bpi < bpl; bpi++ ) { _blocksPool[bpi].cleanup() };
_blocksPool.splice(0, _blocksPool.length);
_blocks = null;
_blocksPool = null;
Подскажите, пожалуйста, верно ли я понял принцип пула и насколько удачно его реализовал? (на глаз работает так же, как при создании-удалении экземпляров).


Последний раз редактировалось a7s1h1; 17.03.2016 в 13:26.
Старый 17.03.2016, 14:12
КорДум вне форума Посмотреть профиль Отправить личное сообщение для КорДум Найти все сообщения от КорДум
  № 2  
Ответить с цитированием
КорДум
 
Аватар для КорДум

блогер
Регистрация: Jan 2008
Адрес: syktyvkar
Сообщений: 3,803
Записей в блоге: 10
А зачем плодить темы? Писали бы в той своей, так как эта имеет к первой непосредственное отношение.

1. пул должен быть выделен в отдельный класс, его методы должны быть инкапсулированы. Это отдельная логика, она должна выставлять наружу только методы управления собой, такие как "взять", "удалить" и еще что-то по вкусу.

2. вызов метода reset я бы сделал руками в логике пула и убрал подписку на removeFromStage. Равно как и init. В текущей реализации хендлер addedToStage вообще не нужен, его можно сделать публичным и дернуть в нужный момент (но это нужно смотреть по общей архитектуре и логике приложения)

3. почитайте про конвенции именования методов (get_block не является правильным именем).

4. посмотрите на свои комментарии, они бессмысленны. Комментарий не должен отвечать на вопрос "что?", он должен отвечать на вопрос "почему?" в большинстве случаев.

Цитата:
return (_blocksPool.length) ? (_blocksPool.pop()) : (new Block());
Все скобки вокруг операндов лишние.
__________________
тут я

Старый 17.03.2016, 16:34
a7s1h1 вне форума Посмотреть профиль Отправить личное сообщение для a7s1h1 Найти все сообщения от a7s1h1
  № 3  
Ответить с цитированием
a7s1h1

Регистрация: Oct 2013
Сообщений: 126
В одном ответе сразу столько полезного, большое спасибо! По первым трём замечаниям исправления внёс.

Цитата:
Сообщение от КорДум Посмотреть сообщение
посмотрите на свои комментарии, они бессмысленны.
Позвольте с вами не согласиться. Полагаю, что бессмысленными они кажутся вам из-за того, что ваш уровень владения AS3.0 делает их очевидными. Я же, находясь в процессе созидательного обучения, леплю комментарии где только можно, чтобы лучше запомнить, где что находится и как всё работает.

Цитата:
Сообщение от КорДум Посмотреть сообщение
Все скобки вокруг операндов лишние.
Это как-то влияет на процесс выполнения кода или просто эстетический момент? Просто так ведь проще группировать условия. Например, если у нас два условия (простых, которые незачем расписывать через if-else), то можно написать
Код AS3:
var a:uint = (b > 3)?((b > 6)?(2):(1)):(0)
, а как это будет выглядеть без скобок, я даже представить не могу.

Старый 17.03.2016, 17:53
Wolsh вне форума Посмотреть профиль Отправить личное сообщение для Wolsh Найти все сообщения от Wolsh
  № 4  
Ответить с цитированием
Wolsh
Нуб нубам
 
Аватар для Wolsh

модератор форума
Регистрация: Jan 2006
Адрес: Бердск, НСО
Сообщений: 6,445
От того, что всё в скобках, легче не становится. Оставьте одни, если так Вам проще.
Код AS3:
var a:uint = b > 3 ? (b > 6 ? 2 : 1) : 0;
__________________
Reality.getBounds(this);

Старый 17.03.2016, 18:23
undefined вне форума Посмотреть профиль Отправить личное сообщение для undefined Найти все сообщения от undefined
  № 5  
Ответить с цитированием
undefined

Регистрация: Oct 2006
Сообщений: 2,281
имхо ифом будет много понятнее.

Старый 17.03.2016, 18:34
a7s1h1 вне форума Посмотреть профиль Отправить личное сообщение для a7s1h1 Найти все сообщения от a7s1h1
  № 6  
Ответить с цитированием
a7s1h1

Регистрация: Oct 2013
Сообщений: 126
Простите, скобочки, мы с вами так долго были вместе, но теперь придётся расстаться. Ничего личного, просто без вас реально лучше. Постараюсь поскорее от вас отвыкнуть

Добавлено через 2 минуты
Цитата:
Сообщение от undefined Посмотреть сообщение
имхо ифом будет много понятнее.
разумеется

Старый 17.03.2016, 19:23
Zebestov вне форума Посмотреть профиль Отправить личное сообщение для Zebestov Посетить домашнюю страницу Zebestov Найти все сообщения от Zebestov
  № 7  
Ответить с цитированием
Zebestov
Lorem ipsum
 
Аватар для Zebestov

модератор форума
Регистрация: May 2001
Адрес: Одесса
Сообщений: 4,869
Записей в блоге: 4
Цитата:
Сообщение от КорДум Посмотреть сообщение
пул должен быть выделен в отдельный класс, его методы должны быть инкапсулированы
В защиту своего пула должен напомнить, что он мною позиционируется исключительно как "ленивый пул", который работает в том же классе )
__________________
Поймай яблоко 2!

Старый 17.03.2016, 20:23
КорДум вне форума Посмотреть профиль Отправить личное сообщение для КорДум Найти все сообщения от КорДум
  № 8  
Ответить с цитированием
КорДум
 
Аватар для КорДум

блогер
Регистрация: Jan 2008
Адрес: syktyvkar
Сообщений: 3,803
Записей в блоге: 10
Бестыч, я ничего против ленивого пула не имею
Хочется показать новичку, что пул — обособленная логическая связующая сущность, ее нужно выделить в отдельный класс и пользоваться экземпляром. Так будет меньше кода в основном классе, плюс уйдут в инкапсуляцию "лишние" ссылки на массивы.

Да, скобочки несут только эстетическую пользу в данном случае.

По поводу вложенных тернарных условий: советую также забыть и об этом. Не нужно экономить строчки, это не туалетная бумага. Код должен быть простым, нужно взглянуть на него и сказать, что здесь творится то-то (поэтому комментарии "что здесь происходит?" и не нужны). Тернарные операторы хороши, если операнды в них небольшие.

Цитата:
var a:uint = b > 3 ? (b > 6 ? 2 : 1) : 0;
Даже в этом облегченном от скобок варианте я не могу в течение первой-двух секунд понять логическую нагрузку этого кода.

Вы еще учитесь и нет ничего страшного, просто запомните мои слова, а пока пишите код так, как как пишется. Прислушиваясь по возможности к более опытным товарищам, конечно же.

И еще заметил только сейчас:
Цитата:
for (var bpi:uint = 0; bpi < bpl; bpi++ ) { _blocksPool[bpi].cleanup() };
Вновь неоправданная экономия строк. И ни о чем не говорящие переменные с именами bpi и bpl. Да, я могу вернуться по коду выше и посмотреть, что вроде как они переводятся block panel index и length соответственно. Но я должен возвращаться обратно для этого. И любой другой, посмотрев этот код, начнет его изучение с рефакторинга таких мест. Чтобы в дальнейшем, если он вернется к этому куску кода, больше не чесал репу и не разберался, что за bpi.
А и да, эта конструкция заменятся на for-each цикл.
__________________
тут я

Старый 17.03.2016, 20:29
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 9  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Из явно зацепивших мой взгляд могу выделить пару моментов.
Я бы не стал делать того, что происходит в
Код AS3:
// ОБНУЛЯЕМ ПАРАМЕТРЫ (при удалении со сцены)
function reset(e:Event){}
Мне так кажется, что процедура удаления и добавления на сцену никак не связана с помещением в пул или извлечением этого объекта из него соответственно. Операции с дисплейлистом часто требуют добавления или удаление одного и того же объекта, ожидая, что с ним ничего не случится при этих операциях. Однако, вы заставляете себя писать код, который фактически заново должен будет проинициализировать ваше дите, единожды уже побывавшее в дисплейлисте. Ваш type исчезает после удаления экземпляра Block со сцены. Вот если бы кто-то решал, что этот экземпляр действительно не нужен, то можно как раз применить метод clean (его именуют dispose обычно) и отправлять объект в пул.
Пул для одного типа объектов считаю рациональным объявлять в самом классе объекта.
__________________
Воспитан в TimeZero. Работаю в Mail.ru.

Старый 17.03.2016, 21:32
a7s1h1 вне форума Посмотреть профиль Отправить личное сообщение для a7s1h1 Найти все сообщения от a7s1h1
  № 10  
Ответить с цитированием
a7s1h1

Регистрация: Oct 2013
Сообщений: 126
большое спасибо всем! Что смог - исправил сразу по вашим советам, над остальным работаю)

Создать новую тему Ответ Часовой пояс GMT +4, время: 20:35.
Быстрый переход
  « Предыдущая тема | Следующая тема »  
Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


 


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


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