Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Создать экземпляр класса в Pool (http://www.flasher.ru/forum/showthread.php?t=210041)

neonoviiwolf 20.01.2015 06:15

Создать экземпляр класса в Pool
 
Доброго времени суток, возник вопрос, делаю универсальный пул, код ниже

Код AS3:

package package_cl{
        import flash.display.MovieClip;
        import flash.events.Event;
 
        public class VectorPool_cl {
                public var vectorPool: Vector.<MovieClip>;
                private var lengthVector: int;
                private var movieClip: MovieClip;
 
                public function VectorPool_cl(_lengthVector: int, _movieClip: MovieClip) {
                        lengthVector = _lengthVector;
                        movieClip = _movieClip;
                        var i = lengthVector;
                        vectorPool = new Vector.<MovieClip>(i + 1);
                        while (--i > -1){
                                vectorPool[i] = movieClip;
                        }
                }
                public function fn_push_pool (i):void{
                        vectorPool.push(vectorPool[i]);
 
                }
                public function fn_add_pool ():void{
                        var vectorMovieClip = movieClip;
                        vectorPool.push(vectorMovieClip);
                }
        }
}

в функцию VectorPool_cl я передаю длину вектора и мувик(из другого класса), который должен быть в векторе, но при такой реализации я заполняю вектор лишь ссылками на мувик, в следствии проявляется, что одновременно на сцену выводится лишь один экземпляр, как решить данную проблему?

udaaff 20.01.2015 06:49

http://www.flasher.ru/forum/blog.php?b=455

expl 20.01.2015 23:06

Если коротко:
Код AS3:

package package_cl{
        import flash.display.MovieClip;
 
        public class VectorPool_cl {
                // Вектор может динамически расширяться - не надо его пересоздавать под каждый размер
                private var vector:Vector.<MovieClip> = new Vector.<MovieClip>();
                public function VectorPool_cl() {
                }
                pulbic function fn_get():MovieClip{
                        if (vector.length > 0) {
                                // Фишка пула - это не создавать новый экземпляр,
                                // если можно использовать ранее созданный
                                return vector.pop();
                        }
                        // Не создавали раньше ничего - значит всё-таки надо создать
                        return new MovieClip();
                }
                public function fn_push(movieClip:MovieClip):void{
                        vector.push(movieClip);
                }
        }
}

Использование:
Код AS3:

public static var pool:VectorPool_cl = new VectorPool_cl();
...
a = pool.fn_get()
addChild(a);
...
removeChild(a)
// Вторая фишка пула - нужно _вручную_ туда добавлять ставшие ненужными объекты,
// иначе все время будет вызываться new MovieClip(); и от пула не будет никакого толку
pool.fn_push(a);
...
// И только здесь начинается выгода от использования пула,
// b присваивается то, что было в a, без создания MovieClip заново
b = pool.fn_get()

Но вы хотите универсальный пул. Тогда нужно как-то научиться создавать не просто MovieClip, а объект заранее заданного типа внутри пула

Решения:

1. Как в приведённой выше ссылке назначить пулу фабрику объектов
(вместо фабрики подойдет просто функция, создающуя объект, или просто класс объекта)

2. А нужна ли вам универсальность? Просто копипастим класс пула и меняем MovieClip на нужный тип.
Что? Копипаста не всегда является злом:

- С одной стороны - это дублирование двух функций.
Но с другой - это строгая типизация и не надо громоздить фабрик.
Плюс в этих функцях мало что дублируется - там if один всего

- Вы особо и не накопипастите - не будет у вас много пулов.
Вы будете заводить пул только когда:
а) Объекты часто создаются и часто "уничтожаются" (перестают использоваться)
б) Создание экземпляров этих объектов является узким местом в приложении
с) Вы можете сказать, когда объект стал ненужным, т.е. знаете в каком месте написать:
Код AS3:

pool.fn_push(object);


neonoviiwolf 21.01.2015 03:05

expl спасибо большое за объяснение
"универсальный" для моего приложения, у меня в пуле будут либо спрайты, либо мувики, соответственно выбрал мувик.
Меня интересовала, как из класса в класс переслать мувик и наделать его экземпляров, тем самым получить пул, в который я смогу отправить нужный мувик, пулов мне понадобиться около 5-7, вот и заморочился, так то я быстро сделаю для каждого отдельный пул, но хочется красоты)

Добавлено через 1 час 2 минуты
Код AS3:

package package_cl{
        import flash.display.MovieClip;
        import flash.events.Event;
 
        public class Vector_Pool_cl {
                public var vectorPool: Vector.<MovieClip> = new Vector.<MovieClip>;
                private var lengthVector: int;
                private var movieClip: MovieClip;
 
                public function Vector_Pool_cl(_lengthVector: int, _movieClip: MovieClip) {
                        lengthVector = _lengthVector;
                        movieClip = _movieClip;
                        var i = lengthVector;
                        while (--i > -1){
                                vectorPool.push(movieClip); //как тут создать экземпляр класс? Используя параметры этой функции
                        }
                }
                public function fn_push_pool (i):void{
                        vectorPool.push(vectorPool[i]);
 
                }
                public function fn_add_pool ():void{
                        var vectorMovieClip = movieClip;
                        vectorPool.push(vectorMovieClip);
                }
        }
}

Добавлено через 1 час 46 минут
в общем решение нашёл такое, хотя есть вопрос, код до конца не понимаю
Код AS3:

package package_cl{
        import flash.display.MovieClip;
        import flash.events.Event;
        import flash.utils.*;
 
        public class Vector_Pool_cl {
                public var vectorPool: Vector.<MovieClip> = new Vector.<MovieClip>;
                private var lengthVector: int;
                private var movieClip: MovieClip;
 
                public function Vector_Pool_cl(_lengthVector: int, _movieClip: MovieClip) {
                        lengthVector = _lengthVector;
                        movieClip = _movieClip;
                        var i = lengthVector;
//*********************************************************
                        var movieClipDef:Class = MovieClip(movieClip).constructor;
//что мы тут делаем, объясните подробно, кому не сложно,
// что происходит, после объявления типа класс
//мы в итоге получаем экземпляр класса?
//************************************************************
                        while (--i > -1){
                                var movieClipView = new movieClipDef ();
                                vectorPool.push(movieClipView);
                        }
                }
                public function fn_push_pool (i):void{
                        vectorPool.push(vectorPool[i]);
 
                }
                public function fn_add_pool ():void{
                        var movieClipDef:Class = MovieClip(movieClip).constructor;
                        var movieClipView = new movieClipDef ();
                        vectorPool.push(movieClipView);
                }
        }
}


expl 21.01.2015 12:44

Цитата:

//что мы тут делаем, объясните подробно, кому не сложно,
// что происходит, после объявления типа класс
//мы в итоге получаем экземпляр класса?
Можно сам класс передать
Код AS3:

public function Vector_Pool_cl(_lengthVector: int, movieClipDef: Class) {

Использование:
Код AS3:

new Vector_Pool_cl(10, MyMovieClip);

Не понимаю, каким образом вы используете эту функцию, она же просто дублирует ссылку:
Код AS3:

public function fn_push_pool (i):void{
        vectorPool.push(vectorPool[i]);
}

Отсутствует функция добавления отработавших объектов в пул (без создания новых)
А объекты вы вызовом pool.vectorPool.pop() забираете?
Не, может оно так и надо, но это не совсем пул и я не могу понять, что вам нужно от пула

Просто на данный момент ваш класс заменяется следущим кодом:
Код AS3:

public var vectorPool: Vector.<MovieClip> = new Vector.<MovieClip>;
for (int i = 0; i < _lengthVector; i++) {
        vectorPool.push(new MovieClip());
}

Так зачем усложнять?

Котяра 21.01.2015 13:03

Делать пул мувиков бессмысленно.
MovieClip используется только если он сделан во FlashIDE
При динамическом создании через конструктор - всегда создавайте Sprite.
кода
Код AS3:

 var mc:MovieClip = new MovieClip()

не должно быть нигде (разве, что для передачи в кривонаписаный метод с анимациями)

Добавлено через 22 минуты
Xм. Я кажется понял задачу.
API должно быть что-то вроде..
Код AS3:

var customMovieClip:CustomMovieClip = new CustomMovieClip();
// добавляем в пул
Pool.push(customMovieClip);
// берём из пула
Pool.get(CustomMovieClip);

Уже в самом пуле заводим словарик, в качестве ключа - класс, в качестве значений - вектор объектов.

expl 21.01.2015 21:03

Цитата:

Делать пул мувиков бессмысленно
Это скорее надо читать как "создавать пустые, не FlashIDE-шные MovieClip-ы вместо Sprite-тов бессмысленно"
А пулы из тех же FlashIDE-шных MovieClip-ов я видел в логических играх, там это убирало подтормаживание при добавлении/удалении шариков на экране

Цитата:

Уже в самом пуле заводим словарик, в качестве ключа - класс, в качестве значений - вектор объектов.
Это уже заморочки, чтобы использовать один экземпляр пула на все типы объектов, со своими оверхедами/проблемами/спорными моментами.
А тут, я так понял, человеку надо сначала вообще разобраться что такое пул и как его использовать.

Котяра 21.01.2015 22:07

Цитата:

Это уже заморочки, чтобы использовать один экземпляр пула на все типы объектов, со своими оверхедами/проблемами/спорными моментами.
Ну вообще да, ни разу не понадобилось использовать универсальные пулы. Всегда юзал (встречал)
только юз конкретных классов со своими заморочками... как-то очистка перед передачей в пул, установкой максимальной длины пула итп.
Ну именно для задачи топикстартера можно было бы и регать каждый конкретнотипный мувик в своём конкретном пуле, через общую обёртку.
Перед добавлением добавить проверок на то, что он(мувик) остановлен, что у него нет родителя. Что у него нет подписок на события итп

neonoviiwolf 22.01.2015 01:32

Мне пришлось использовать мувик, т.к. класс наследуется от мувика, который нарисован и добавлен в библиотеку. По коду у меня организовано думаю так себе, т.к. писал ровно так, как хватало знаний, я не использую *.pop(не понимаю как его использовать в пуле), сделал проще для себя. Объекты живут разное время, но совсем недолго, просто отживший мувик я удаляю со сцены и кидаю ссылку на новый объект в вектор, увеличивая длину вектора, потом удаляю слушатель для мувика, потом ссылку в null, и убираю из вектора ненужный элемент, перевожу индекс на последний элемент добавленный на сцене, что позволяет при вызове не искать свободный мувик, а сразу вывести.
собственно код, написан некрасива, потихоньку исправляюсь, когда пишу новое
Код AS3:

package package_cl {
        import flash.events.Event;
        import package_cl.global_variable_cl;
 
        public class bullet_cl extends bullet_mc {
                private var gl_variable: global_variable_cl = new global_variable_cl();
 
                public function bullet_cl() {
                        this.addEventListener(Event.ADDED_TO_STAGE, fn_speed);
                }
                public function fn_speed(e: Event): void {
                        x -= gl_variable.speed_bullet * Math.cos(rotation * Math.PI / 180);
                        y -= gl_variable.speed_bullet * Math.sin(rotation * Math.PI / 180);
                }
        }
}

Код AS3:

package package_cl {
        import flash.events.Event;
        import package_cl.Vector_Pool_cl;
        import package_cl.global_variable_cl;
//***************************************************************************************
        public class Control_bullet_cl {
                private var fire_ship_Boolean: Boolean = false;
                private var stageX: int;
                private var stageY: int;
                private var _stage: * ;
                private var vectorBullet: Vector_Pool_cl;
                private var bullet: bullet_cl = new bullet_cl();
                private var gl_variable: global_variable_cl = new global_variable_cl();
 
                public function Control_bullet_cl(stage) {
                        _stage = stage;
                        stageX = _stage.stageHeight - 20; //высота/ширина
                        stageY = _stage.stageWidth - 20;
                        vectorBullet = new Vector_Pool_cl(gl_variable.max_vector_bullet, bullet);
                        _stage.addEventListener(Event.ENTER_FRAME, fn_null_bullet);
                }
//***************************************************************************************
                public function fn_fire_down(_x, _y, _rotation): void {
                        if (gl_variable.index_bullet == vectorBullet.vectorPool.length) {
                                vectorBullet.fn_add_pool();
                                fn_fire_down(_x, _y, _rotation); //рекурсия
                        } else {
                                vectorBullet.vectorPool[gl_variable.index_bullet].x = _x;
                                vectorBullet.vectorPool[gl_variable.index_bullet].y = _y;
                                vectorBullet.vectorPool[gl_variable.index_bullet].rotation = _rotation;
                                _stage.addEventListener(Event.ENTER_FRAME, vectorBullet.vectorPool[gl_variable.index_bullet].fn_speed)
                                _stage.addChild(vectorBullet.vectorPool[gl_variable.index_bullet]);
                                ++gl_variable.index_bullet;
                        }
                }
 
                public function fn_fire_up(_x, _y, _rotation): void {
                        if (gl_variable.index_bullet == vectorBullet.vectorPool.length) {
                                vectorBullet.fn_add_pool();
                                fn_fire_up(_x, _y, _rotation); //рекурсия
                        } else {
                                vectorBullet.vectorPool[gl_variable.index_bullet].x = _x;
                                vectorBullet.vectorPool[gl_variable.index_bullet].y = _y;
                                vectorBullet.vectorPool[gl_variable.index_bullet].rotation = _rotation;
                                _stage.addEventListener(Event.ENTER_FRAME, vectorBullet.vectorPool[gl_variable.index_bullet].fn_speed)
                                _stage.addChild(vectorBullet.vectorPool[gl_variable.index_bullet]);
                                ++gl_variable.index_bullet;
                        }
                }
//***************************************************************************************
                public function fn_null_bullet(e: Event): void {
                        var i = vectorBullet.vectorPool.length;
                        while (--i > -1) {
                                if (vectorBullet.vectorPool[i] != null) {
                                        if (vectorBullet.vectorPool[i].stage != null) {
                                                if (vectorBullet.vectorPool[i].y > stageX || vectorBullet.vectorPool[i].y < 150 || vectorBullet.vectorPool[i].x > stageY || vectorBullet.vectorPool[i].x < 10) {
                                                        _stage.removeEventListener(Event.ENTER_FRAME, vectorBullet.vectorPool[i].fn_speed);
                                                        vectorBullet.fn_push_pool(i);
                                                        _stage.removeChild(vectorBullet.vectorPool[i]);
                                                        vectorBullet.vectorPool[i] = null;
                                                        vectorBullet.vectorPool.splice(i, 1);
                                                        --gl_variable.index_bullet;
                                                }
                                        }
                                }
                        }
                }
        }
}

Код AS3:

package package_cl{
        import flash.display.MovieClip;
        import flash.events.Event;
        import flash.utils.*;
 
        public class Vector_Pool_cl {
                public var vectorPool: Vector.<MovieClip> = new Vector.<MovieClip>;
                private var lengthVector: int;
                private var movieClip: MovieClip;
 
                public function Vector_Pool_cl(_lengthVector: int, _movieClip: MovieClip) {
                        lengthVector = _lengthVector;
                        movieClip = _movieClip;
                        var i = lengthVector;
                        var movieClipDef:Class = MovieClip(movieClip).constructor;
                        while (--i > -1){
                                var movieClipView = new movieClipDef ();
                                vectorPool.push(movieClipView);
                        }
                }
                public function fn_push_pool (i):void{
                        vectorPool.push(vectorPool[i]);
 
                }
                public function fn_add_pool ():void{
                        var movieClipDef:Class = MovieClip(movieClip).constructor;
                        var movieClipView = new movieClipDef ();
                        vectorPool.push(movieClipView);
                }
        }
}


expl 22.01.2015 23:33

Судя по всему у вас пул используется не для оптимизации, а чтобы хранить список объектов, причём как-то странно

Там есть забирание мувиклипов из буфера и набивание _новых_ мувиклипов в буффер(который зовется пулом почему-то), а так, чтобы повторно использовались удалённые с экрана мувиклипы - не нашёл

Как бы оно могло выглядеть вообще БЕЗ пула (логика изменена, т.к. маловато кода для её восстановления, идентификаторы переименованы чисто для себя - у вас слишком суровый стиль кодирования):

Код AS3:

//Пуля та же, только переименования
package package_cl {
        import flash.events.Event;
        import package_cl.GlobalVariables;
        public class Bullet extends bullet_mc {
                private var globalVariables: GlobalVariables = new GlobalVariables();
                public function Bullet() {
                        addEventListener(Event.ADDED_TO_STAGE, onEnterFrame);
                }
                public function onEnterFrame(e: Event): void {
                        x -= globalVariables.speed_bullet * Math.cos(rotation * Math.PI / 180);
                        y -= globalVariables.speed_bullet * Math.sin(rotation * Math.PI / 180);
                }
        }
}
 
package package_cl {
        import flash.events.Event;
        import flash.display.Stage;
        import package_cl.MovieClipPool;
 
        public class BulletsController {
                private var stageX: int;
                private var stageY: int;
                private var _stage: Stage;
 
                private var activeBullets:Vector.<Bullet> = new Vector.<Bullet>();// Это не пул, это просто список
 
                public function BulletsController(stage:Stage) {
                        _stage = stage;
                        stageX = _stage.stageHeight - 20;
                        stageY = _stage.stageWidth - 20;
                        _stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
                }
 
                public function onEnterFrame(e: Event): void {
                        spawnSomeBullets();
                        removeInvisibleBullets();
                }
 
                private function spawnSomeBullets():void {
                        // Вашу задумку не могу угадать, поэтому просто создадим 10 пуль
                        for (var i:int = 0; i < 10; i++) {
                                var bullet:Bullet = new Bullet();
                                bullet.x = _x;
                                bullet.y = _y;
                                bullet.rotation = i * 30;
                                // Не знаю зачем здесь слушатель ещё и на стейдж, но пусть будет
                                _stage.addEventListener(Event.ENTER_FRAME, bullet.onEnterFrame)
                                _stage.addChild(bullet);
                                activeBullets.push(bullet);
                        }
                }
 
                private function removeInvisibleBullets(): void {
                        for (var i:int = activeBullets.length; i-- > 0;) // --> - оператор DownTo :)
                        {
                                Bullet bullet = activeBullets[i];
                                if (bullet != null) {
                                        if (bullet.stage != null) {
                                                if (bullet.y > stageX || bullet.y < 150 || bullet.x > stageY || bullet.x < 10) {
                                                        _stage.removeEventListener(Event.ENTER_FRAME, bullet.onEnterFrame);
                                                        _stage.removeChild(bullet);
                                                        activeBullets.splice(i, 1);
                                                }
                                        }
                                }
                        }
                }
        }
}

А теперь с "нормальным" пулом:
Код AS3:

package package_cl {
        import flash.events.Event;
        import flash.display.Stage;
        import package_cl.MovieClipPool;
 
        public class BulletsController {
                private var stageX: int;
                private var stageY: int;
                private var _stage: Stage;
 
                private var activeBullets:Vector.<Bullet> = new Vector.<Bullet>();// Это не пул, это просто список
                private var pool = new BulletPool();// ИЗМЕНЕНИЕ 1
 
                public function BulletsController(stage:Stage) {
                        _stage = stage;
                        stageX = _stage.stageHeight - 20;
                        stageY = _stage.stageWidth - 20;
                        _stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
                }
 
                public function onEnterFrame(e: Event): void {
                        spawnSomeBullets();
                        removeInvisibleBullets();
                }
 
                private function spawnSomeBullets():void {
                        // Вашу задумку не могу угадать, поэтому просто создадим 10 пуль
                        for (var i:int = 0; i < 10; i++) {
                                var bullet:Bullet = pool.newBullet();// ИЗМЕНЕНИЕ 2
                                bullet.x = _x;
                                bullet.y = _y;
                                bullet.rotation = i * 30;
                                // Не знаю зачем здесь слушатель ещё и на стейдж, но пусть будет
                                _stage.addEventListener(Event.ENTER_FRAME, bullet.onEnterFrame)
                                _stage.addChild(bullet);
                                activeBullets.push(bullet);
                        }
                }
 
                private function removeInvisibleBullets(): void {
                        for (var i:int = activeBullets.length; i-- > 0;) // --> - оператор DownTo :)
                        {
                                Bullet bullet = activeBullets[i];
                                if (bullet != null) {
                                        if (bullet.stage != null) {
                                                if (bullet.y > stageX || bullet.y < 150 || bullet.x > stageY || bullet.x < 10) {
                                                        _stage.removeEventListener(Event.ENTER_FRAME, bullet.onEnterFrame);
                                                        _stage.removeChild(bullet);
                                                        activeBullets.splice(i, 1);
                                                        pool.releaseBullet();// ИЗМЕНЕНИЕ 3
                                                }
                                        }
                                }
                        }
                }
        }
}
 
package package_cl{
        import flash.display.MovieClip;
 
        public class BulletPool {
                private var vector:Vector.<Bullet> = new Vector.<Bullet>();
                public function BulletPool() {
                }
                public function newBullet():Bullet{
                        if (vector.length > 0)
                                return vector.pop();// pop удаляет последний элемент и возвращает его
                        return new Bullet();
                }
                public function releaseBullet(movieClip:Bullet):void{
                        vector.push(movieClip);
                }
        }
}

Код вряд ли рабочий (не проверял), но для чего нужен пул должно стать понятнее


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

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