在AS3中预先排序一个数组

时间:2012-01-30 06:36:40

标签: actionscript-3 sorting multidimensional-array

我正在尝试对使用以下内容添加到数组中的项目数组进行预排序:

draw(texture:LTexture, position:Point, depth:int = 0):void

目前,调用此方法会将纹理添加到队列中。一旦我的队列中的项目准备好呈现,我使用以下内容对我的数组进行排序:

queue.sortOn("depth");

这样可以正常工作,但速度很慢,尤其是当我的队列中有超过2000个纹理被绘制时。


我试图通过在draw()中添加一些新逻辑来预先输出我的数组。基本上我的队列现在是一个2D数组,其中第一层代表深度,其中的每个数组都包含要绘制的纹理。例如:

queue[1] = [texture, texture];
queue[4] = [texture];
queue[2] = [texture, texture, texture, texture];

然后我有一个将这些数组组合成一个新队列的函数:

function collate():Array
{
    var collated:Array = [];

    for each(var i:Array in _block)
        collated = collated.concat(i);

    return collated;
}

这似乎工作正常,但到目前为止存在一些问题:

  1. 当我使用极大变化的深度时,例如517,foreach循环似乎按照它们创建的顺序连接我的内部数组,而不是它们的索引(很奇怪 - 如果我使用更接近的深度,则工作正常)。
  2. 如果指定的深度确实很高和/或变化很大,我的队列最终会有一些空槽,我的foreach循环在连接我的数组时必须包含在迭代过程中,例如:{{1} }
  3. 我怎样才能更好地接近我想要实现的目标?那就是,我希望最终得到一个包含按深度排序的所有纹理的数组。

1 个答案:

答案 0 :(得分:2)

虽然我无法想象有2000个纹理被z排序的原因(看起来非常多),但我想出了这些想法:

  1. 使用linked list代替数组,让纹理在添加它们时找到各自的位置(add()每个新纹理到第一个节点,然后让链接节点传递它直到它到达正确深度的位置)。

    如果您有时间进入链接列表,这可能是我选择的解决方案,因为它允许您保留现有结构并在它们出现时添加或删除纹理,而无需再次对整个列表进行排序试。

  2. 您可以将链表与字典组合:如上所述创建链表,并收集对字典中每个深度的第一个节点的引用(node_dictionary[depth] = node;)。这样,您可以在给定深度添加()新节点,而不必从列表的开头传递它们。

  3. 使用第二个数组仅收集现有的队列索引(每次添加纹理时按下索引)并对该简单数组进行排序以消除空槽。

    var index_array : Array = [];
    ...
    queue[17].push(texture);
    index_array.push (17);
    ...
    queue[1].push(texture);
    index_array.push (1);
    ...
    queue[17].push(texture); // probably more than one texture for each index
    index_array.push (17);
    
    index_array.sort(Array.NUMERIC|Array.UNIQUESORT);
    
    var i:int = -1;
    while (++i < index_array.length) drawTextures(queue[i]);