Просмотр полной версии : Как сделать связь между Y и ChildIndex мувиклипа?
zCHESNOKz
02.12.2015, 14:33
Всем привет! Помогите кому не лень)
Есть массив с клипами которые добавляются поочередно и также по ходу дела могут быть удалены. Мне же нужно что бы было так: чем больше у клипа Y тем меньше его позиция индекса в списке дочерних элементов относительно всех остальных клипов в массиве.
Как это реализовать?
#Решено! Спасибо callme (http://www.flasher.ru/forum/member.php?u=404016)
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() можем написать свою сортировку:
vector.sort(sorter);
function sorter(a:T, b:T):Number
{
if(a > b) {
return 1;
}
else if(a < b) {
return -1;
}
else {
return 0;
}
}
Если массив имеется ввиду обычный массив или вектор, то у них есть метод sort, куда можно передать нужную функцию для сортировки.
Если надо сортировать детей DisplayObjectContainer, то придётся написать алгоритм сортировки самостоятельно. Пригодится метод swapChildrenAt.
zCHESNOKz
02.12.2015, 19:33
Если массив имеется ввиду обычный массив или вектор, то у них есть метод sort, куда можно передать нужную функцию для сортировки.
Если надо сортировать детей DisplayObjectContainer, то придётся написать алгоритм сортировки самостоятельно. Пригодится метод swapChildrenAt.
сортировка клипов: чем больше у клипа Y тем выше он в списке отображения.
только как?(
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]);
}
callme,
Скорее всего, человеку нужно сортировать динамический список отображения, поэтому такой хитрый план с отдельным массивом не подойдёт. :)
zCHESNOKz,
Вам просто нужно обойти список отображения особым (https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8) способом. То есть, используя один из алгоритмов сортировок. Готового решения у меня нету.
caseyryan
03.12.2015, 10:25
Скорее всего, человеку нужно сортировать динамический список отображения, поэтому такой хитрый план с отдельным массивом не подойдёт.
Ну а что мешает обойти список и затолкать все в массив? А лучше вообще у контейнера, в который все это складывается, переопределить addChild / removeChild и добавлять / удалять всех детей стразу в массив сортировки
Так и думал, что просто так от этого "лёгкого пути" не откажутся. :)
Список отображения уже является массивом. Зачем плодить ещё? Всё это будут костыли только ради использования нативного sort. Так код усложнится, потребление памяти и цп вырастет.
Правильным решением будет написать всего одну функцию, в которой реализовать подходящий алгоритм сортировки, с минимальными ресурсозатратами. Она потом на всю жизнь пригодится.
zCHESNOKz
03.12.2015, 10:40
callme,
Скорее всего, человеку нужно сортировать динамический список отображения, поэтому такой хитрый план с отдельным массивом не подойдёт. :)
zCHESNOKz,
Вам просто нужно обойти список отображения особым (https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8) способом. То есть, используя один из алгоритмов сортировок. Готового решения у меня нету.
Именно, вы меня как раз таки поняли.
Это получается как в изометрии. Или там как то проще все считается?
В изометрии ещё бывает, что к y прибавляют x. То есть сортируется как: 1.x + 1.y > 2.x + 2.y Это нужно для того, чтоб объекты стоящие на одинаковой y не "скакали" в списке отображения.
В играх код никогда не был простым.
Самое простое решение это сортировать элементы "каждый с каждым". Но понятное дело, что с такой сортировкой вы сможете показать на экране совсем не много объектов, перед тем как приложение начнёт фризить и виснуть. Поэтому, я дал вам ссылку на вики, где описываются различные алгоритмы сортировок. Нужно прочитать, изучить, выбрать самый оптимальный вариант под свои конкретные нужды и реализовать.
zCHESNOKz
03.12.2015, 10:53
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
писок отображения уже является массивом. Зачем плодить ещё?
Затем, что у тебя нет доступа к массиву списка отображения и ты не можешь его сортировать напрямую.
Я понял. Я тоже сортировал массив по 'y'. А дальше, как относительно положения в (отсортированном) массиве расположить графические объекты с нужным положением глубины отображения?
Каждый раз после сортировки надо выполнять вот этот код:
for (var i:int = 0; i < clips.length; i++)
{
addChild(clips[i]);
}
Bletraut
03.12.2015, 18:19
Когда я создавал подобные игры, я не использовал сортировку дисплей листа ибо это влияет на производительность, но взамен этого я каждый раз генерировал дисплей лист. Мой метод заключался в следующем.
Создается двумерный массив, в первом массиве хранится индекс массива который определяется по сортируемой величине, второй массив хранит объекты имеющие данную величину. Код примерно следующий
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]);
}
}
Опытных гуру прошу оценить и прокомментировать мой способ, есть ли у него преимущества перед сортировочным?
container.removeChildren(); //удаляем всех детей из списка отображения
это писать не обязательно.
caseyryan
04.12.2015, 08:33
я не использовал сортировку дисплей листа ибо это влияет на производительность, но взамен этого я каждый раз генерировал дисплей лист. Мой метод заключался в следующем.
Мм.. ну, как бы тут очевидно, что этот метод гораздо тормознее. Тут происходит то же самое, только 2 раза.
Готов поспорить, что сортировка предложенная callme, будет работать гораздо быстрее
zCHESNOKz
04.12.2015, 11:23
Каждый раз после сортировки надо выполнять вот этот код:
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(), который работает довольно быстро
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
и 30 и 100 объектов - это ничто.
Только хотел спросить, может лучше писать:
_container.setChildIndex(children[i], i);
вместо
addChild(clips[i]); ?
Вот еще нашел в сети называется - Z-последовательность
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 объектов - это ничто.
Согласен, на таких объемах париться не стоит.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.