Форум Flasher.ru

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

zCHESNOKz 02.12.2015 14:33

Как сделать связь между Y и ChildIndex мувиклипа? (Z-последовательность) #Решено
 
Всем привет! Помогите кому не лень)

Есть массив с клипами которые добавляются поочередно и также по ходу дела могут быть удалены. Мне же нужно что бы было так: чем больше у клипа Y тем меньше его позиция индекса в списке дочерних элементов относительно всех остальных клипов в массиве.

Как это реализовать?

#Решено! Спасибо callme

Код AS3:

 
addChild(clip);
plant_arr.push(clip);
 
clip_arr.sortOn("y", Array.NUMERIC);
 
for (var i:int = 0; i < clip_arr.length; i++)
{
        addChild(clip_arr[i]);
}

Если же у нас имеется вместо Array - Vector, в котором есть только .sort() можем написать свою сортировку:

Код AS3:

                        vector.sort(sorter);  
 
                        function sorter(a:T, b:T):Number
                        {
                                if(a > b) {
                                        return 1;
                                }
                                else if(a < b) {
                                        return -1;
                                }
                                else {
                                        return 0;
                                }
                        }


Tails 02.12.2015 14:54

Если массив имеется ввиду обычный массив или вектор, то у них есть метод sort, куда можно передать нужную функцию для сортировки.
Если надо сортировать детей DisplayObjectContainer, то придётся написать алгоритм сортировки самостоятельно. Пригодится метод swapChildrenAt.

zCHESNOKz 02.12.2015 19:33

Цитата:

Сообщение от Tails (Сообщение 1189346)
Если массив имеется ввиду обычный массив или вектор, то у них есть метод sort, куда можно передать нужную функцию для сортировки.
Если надо сортировать детей DisplayObjectContainer, то придётся написать алгоритм сортировки самостоятельно. Пригодится метод swapChildrenAt.

сортировка клипов: чем больше у клипа Y тем выше он в списке отображения.

только как?(

callme 02.12.2015 22:49

Код AS3:

var clips:Array = new Array();
 
var clip1:MovieClip = new MovieClip();
clip1.y = 10;
 
var clip2:MovieClip = new MovieClip();
clip2.y = 70;
 
var clip3:MovieClip = new MovieClip();
clip3.y = 50;
 
clips.push(clip1);
clips.push(clip2);
clips.push(clip3);
 
clips.sortOn('y', Array.NUMERIC);
 
for (var i:int = 0; i < clips.length; i++)
{
    addChild(clips[i]);
}


Tails 03.12.2015 10:15

callme,
Скорее всего, человеку нужно сортировать динамический список отображения, поэтому такой хитрый план с отдельным массивом не подойдёт. :)

zCHESNOKz,
Вам просто нужно обойти список отображения особым способом. То есть, используя один из алгоритмов сортировок. Готового решения у меня нету.

caseyryan 03.12.2015 10:25

Цитата:

Скорее всего, человеку нужно сортировать динамический список отображения, поэтому такой хитрый план с отдельным массивом не подойдёт.
Ну а что мешает обойти список и затолкать все в массив? А лучше вообще у контейнера, в который все это складывается, переопределить addChild / removeChild и добавлять / удалять всех детей стразу в массив сортировки

Tails 03.12.2015 10:35

Так и думал, что просто так от этого "лёгкого пути" не откажутся. :)
Список отображения уже является массивом. Зачем плодить ещё? Всё это будут костыли только ради использования нативного sort. Так код усложнится, потребление памяти и цп вырастет.

Правильным решением будет написать всего одну функцию, в которой реализовать подходящий алгоритм сортировки, с минимальными ресурсозатратами. Она потом на всю жизнь пригодится.

zCHESNOKz 03.12.2015 10:40

Цитата:

Сообщение от Tails (Сообщение 1189379)
callme,
Скорее всего, человеку нужно сортировать динамический список отображения, поэтому такой хитрый план с отдельным массивом не подойдёт. :)

zCHESNOKz,
Вам просто нужно обойти список отображения особым способом. То есть, используя один из алгоритмов сортировок. Готового решения у меня нету.

Именно, вы меня как раз таки поняли.

Это получается как в изометрии. Или там как то проще все считается?

Tails 03.12.2015 10:48

В изометрии ещё бывает, что к y прибавляют x. То есть сортируется как: 1.x + 1.y > 2.x + 2.y Это нужно для того, чтоб объекты стоящие на одинаковой y не "скакали" в списке отображения.

В играх код никогда не был простым.
Самое простое решение это сортировать элементы "каждый с каждым". Но понятное дело, что с такой сортировкой вы сможете показать на экране совсем не много объектов, перед тем как приложение начнёт фризить и виснуть. Поэтому, я дал вам ссылку на вики, где описываются различные алгоритмы сортировок. Нужно прочитать, изучить, выбрать самый оптимальный вариант под свои конкретные нужды и реализовать.

zCHESNOKz 03.12.2015 10:53

Цитата:

Сообщение от callme (Сообщение 1189368)
Код AS3:

var clips:Array = new Array();
 
var clip1:MovieClip = new MovieClip();
clip1.y = 10;
 
var clip2:MovieClip = new MovieClip();
clip2.y = 70;
 
var clip3:MovieClip = new MovieClip();
clip3.y = 50;
 
clips.push(clip1);
clips.push(clip2);
clips.push(clip3);
 
clips.sortOn('y', Array.NUMERIC);
 
for (var i:int = 0; i < clips.length; i++)
{
    addChild(clips[i]);
}



Я понял. Я тоже сортировал массив по 'y'. А дальше, как относительно положения в (отсортированном) массиве расположить графические объекты с нужным положением глубины отображения?

caseyryan 03.12.2015 12:38

Цитата:

писок отображения уже является массивом. Зачем плодить ещё?
Затем, что у тебя нет доступа к массиву списка отображения и ты не можешь его сортировать напрямую.

callme 03.12.2015 12:58

Цитата:

Сообщение от zCHESNOKz (Сообщение 1189385)
Я понял. Я тоже сортировал массив по 'y'. А дальше, как относительно положения в (отсортированном) массиве расположить графические объекты с нужным положением глубины отображения?


Каждый раз после сортировки надо выполнять вот этот код:
Код AS3:

for (var i:int = 0; i < clips.length; i++) 
{
    addChild(clips[i]);
}


Bletraut 03.12.2015 18:19

Когда я создавал подобные игры, я не использовал сортировку дисплей листа ибо это влияет на производительность, но взамен этого я каждый раз генерировал дисплей лист. Мой метод заключался в следующем.

Создается двумерный массив, в первом массиве хранится индекс массива который определяется по сортируемой величине, второй массив хранит объекты имеющие данную величину. Код примерно следующий

Код AS3:

var container:Sprite = new Sprite(); //допустим это какой-то контейнер в котором нужно сортировать всех детей по Y.
 
var sortChildList:Array = new Array(); //наш двумерный массив со списком отображения
 
//перебираем всех детей и записываем их в массив
var i:int = container.numChildren;
while(i--)
{
    var j:Sprite = container.getChildAt(i);
    if (sortChildList[Math.floor(j.y)] == undefined)
    {
        var na:Array = new Array(j);
        sortChildList[Math.floor(j.y)] = na;
    }
    else
    {
        sortChildList[Math.floor(j.y)].push(j);
    }
}
 
container.removeChildren(); //удаляем всех детей из списка отображения
 
//добавляем всех детей заново
for (i = 0; i < sortChildList.length; i++)
{
    if (sortChilList[i] == undefined) continue;
    for (var j:int = 0; j < sortChilList[i].length; j++)
    {
        container.addChild(sortChilList[i][j]);
    }
}

Опытных гуру прошу оценить и прокомментировать мой способ, есть ли у него преимущества перед сортировочным?

ObOs 03.12.2015 18:41

Код AS3:

container.removeChildren(); //удаляем всех детей из списка отображения

это писать не обязательно.

caseyryan 04.12.2015 08:33

Цитата:

я не использовал сортировку дисплей листа ибо это влияет на производительность, но взамен этого я каждый раз генерировал дисплей лист. Мой метод заключался в следующем.
Мм.. ну, как бы тут очевидно, что этот метод гораздо тормознее. Тут происходит то же самое, только 2 раза.
Готов поспорить, что сортировка предложенная callme, будет работать гораздо быстрее

zCHESNOKz 04.12.2015 11:23

Цитата:

Сообщение от callme (Сообщение 1189388)
Каждый раз после сортировки надо выполнять вот этот код:
Код AS3:

for (var i:int = 0; i < clips.length; i++) 
{
    addChild(clips[i]);
}


Тоже мелькало в голове. Большое спасибо это именно то что мне нужно было)

И в правду, насколько это будет пагубно влиять на производительность? Если допустим объектов будит до 30, не говорю уже больше 100. А можно ли это использовать в изометрии? Там ведь тоже много объектов. Или в изометрии все как то иначе?

caseyryan 04.12.2015 11:47

и 30 и 100 объектов - это ничто. У меня в игре сортировалось около тысячи объектов при 30 кадрах в секунду. При этом fps не проседал (хотя сортировка у меня была выборочная, алгоритм ниже), учитывая даже то, что там еще и постоянное взаимодействие с сервером и бокс2д (который, как известно, довольно тупой)
Игрушка браузерная. Для мобил могут быть затупы при таких объемах как у меня. Но если использовать старлинг, то у него есть уже встроенный метод sortChildren(), который работает довольно быстро

Код AS3:

children.sortOn("y", Array.NUMERIC);
i = children.length;
while (i--) {
        var childIndex:int = _container.getChildIndex(children[i]);
        if (childIndex != i) {
                _container.setChildIndex(children[i], i);
        }
}

А сам массив children, как я уже говрил, собирается при переопределении методов addChild() / removeChild()

zCHESNOKz 04.12.2015 12:12

Цитата:

Сообщение от caseyryan (Сообщение 1189418)
и 30 и 100 объектов - это ничто.


Только хотел спросить, может лучше писать:
Код AS3:

_container.setChildIndex(children[i], i);

вместо
Код AS3:

 addChild(clips[i]);

?

Вот еще нашел в сети называется - Z-последовательность

Код AS3:

 
function sortZ(){
    var arrayOfStuff:Vector<DisplayObject> = new Vector<DisplayObject>();
 
    var i:int;
    for(i=0;i<foreground.numChildren;i++){
        arrayOfStuff.push(foreground.getChildAt(i));
    }
 
    arrayOfStuff.sort(sortArrayByY);
 
    for(i=0;i<arrayOfStuff.length;i++){
        foreground.setChildIndex(arrayOfStuff[i],i);
    }
}
 
function sortArrayByY(valA:DisplayObject, valB:DisplayObject):int {
    if(valA.y == valB.y) return 0;
    if(valA.y > valB.y) return 1;
    return -1;
}

Как насчет использовать вектор? Он же быстрее чем Array?

Bletraut 04.12.2015 17:29

Цитата:

и 30 и 100 объектов - это ничто.
Согласен, на таких объемах париться не стоит.


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

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