【问题标题】:Sort multiple lists lua排序多个列表lua
【发布时间】:2016-02-14 21:34:44
【问题描述】:

如何对 2 个列表 y 位置(地图图块和人员)进行排序,并按照 y 的相关顺序绘制它们。我想使用 2 个列表:

map = {}
map.y = {60,10,40,80}
map.t = {0,0,1,1} -- type

people = {}
people.y = {0,100}
people.t = {0,1} -- type

我目前可以排序和绘制一个英雄和盒子列表。 排序/绘制代码:

box1 = love.graphics.newImage("box1.png")
box2 = love.graphics.newImage("box2.png")
box3 = love.graphics.newImage("box3.png")
hero = love.graphics.newImage("hero.png")

object = {
    x = {0, 50,100,200},
    y = {0,200, 50,100},
    g = {0,1,2,3}
}
function sortIndex(item)
    local i
    local id = {}       -- id list
    for i = 1, #item.x do   -- Fill id list (1 to length)
        id[i] = i
    end
--  print( unpack(id) ) -- Check before
    table.sort(id,sortY)-- Sort list
--  print( unpack(id) ) -- Check after
    item.sort = id      -- List added to object.sort
--  Sort id, using item values
    function sortY(a,b)
        return item.y[a] < item.y[b]
    end
end
function drawObject()
    local i,v, g,x,y
    for i = 1, #object.x do
        v = object.sort[i] -- Draw in order
        x = object.x[v]
        y = object.y[v]
        g = object.g[v]
        if      g == 0 then g = hero -- set to an image value
        elseif  g == 1 then g = box1
        elseif  g == 2 then g = box2
        elseif  g == 3 then g = box3
        end
        love.graphics.draw(g,x,y,0,7,7)
    end
end

更新排序:

sortIndex(object)

我的函数对id 列表进行排序,比较y 位置列表。 id 用于按照对象y 的顺序绘制对象。如何将 2 个 id 列表排序在一起,比较 2 个 y 位置列表,然后按顺序绘制它们?

也许在绘制时,从地图图块切换到依赖y 的人,但我不知道如何。

【问题讨论】:

    标签: sorting lua draw


    【解决方案1】:

    可能和你之前的问题有很大关系:Returning A Sorted List's Index in Lua

    我假设如果您的高度可以是 1,2 和 3(1 在顶部),您首先要渲染 Y1 处的所有图块,然后是 Y1 处的所有人,然后是 Y2 和 Y3。为此,您必须创建一个组合列表并对其进行排序:

    map = {}
    map.y = {60,10,40,80}
    map.t = {0,0,1,1} -- type
    
    people = {}
    people.y = {0,100}
    people.t = {0,1} -- type
    
    local all = {}
    local map_y = map.y
    local offset = #map_y
    local people_y = people.y
    -- Fill the list with map tiles
    for i=1,offset do
        all[i] = {1,i,map_y[i]} --{type,index,y}
    end
    -- Fill the list with people
    for i=1,#people_y do
        all[i+offset] = {2,i,people_y[i]}
    end
    -- Do the sorting
    -- It works a bit like your previous question:
    -- 'all' contains "references":
    --    They tell us is it's from map/people + the index
    -- We sort the references using the third element in it:
    --    The 'y' variable we put there during the first 2 loops
    table.sort(all,function(a,b)
        return a[3] < b[3]
    end)
    -- Printing example
    -- The references are sorted using the 'y' field of your objects
    --    With v[1] we know if it's from map/people
    --    The v[2] tells us the index in that ^ table
    --    The v[3] is the 'y'-field. No real need to remove it
    for k,v in pairs(all) do
        print(v[1] == 1 and "Map" or "Person",v[2],"with y being",v[3])
    end
    

    输出:

    Person 1 with y being 0
    Map 2    with y being 10
    Map 3    with y being 40
    Map 1    with y being 60
    Map 4    with y being 80
    Person 2 with y being 100
    

    我想补充两点,与我的回答问题无关:

    • 如果每个元素都有一个表格可能会更容易。 您的人员将是 {0,0} 和 {100,1},这可能更容易操作。
    • 如果你希望你的东西总是排序,你可能想要使用这个:Sorted List。如果您保留所有对象的排序列表,则不必在每次添加/删除元素时对列表进行排序,或者更糟糕的是,每次渲染时。 (取决于人是否移动)如果您计划拥有大量地图/人物对象,这可能有助于提高性能。 (排序列表可能对您当前的数据系统有用,但也适用于 {y=1,t=1} 之一)

    【讨论】:

    • 简单易用。做我想做的。非常感谢您提供 cmets。我正在研究组合列表进行排序,但我无法解决我的问题(仍在学习有关 lua 的重要信息)
    【解决方案2】:
    function sortIndex(...)
      sorted = {}  -- global
      local arrays_order = {}
      for arr_index, array in ipairs{...} do
        arrays_order[array] = arr_index
        for index = 1, #array.y do
          table.insert(sorted, {array = array, index = index})
        end
      end
      table.sort(sorted,
        function (a,b)
          local arr1, arr2 = a.array, b.array
          local ind1, ind2 = a.index, b.index
          return arr1.y[ind1] < arr2.y[ind2] or
            arr1.y[ind1] == arr2.y[ind2] and arrays_order[arr1] < arrays_order[arr2]
        end)
    end
    
    function drawAll()
      for _, elem_info in ipairs(sorted) do
        local array = elem_info.array
        local index = elem_info.index
        local x = array.x[index]
        local y = array.y[index]
        if array == map then
          -- draw a map tile with love.graphics.draw()
        elseif array == people then
          -- draw a human with love.graphics.draw()
        end
      end
    end
    
    sortIndex(map, people)  -- to draw map tiles before people for the same y
    

    【讨论】:

    • 你能解释一下这个答案,而不是勺子喂食代码吗?
    • @warspyking - 请在您的批评中更具建设性:我的回答中究竟需要解释什么?您不清楚答案的哪一部分?
    • @Egor 我不知道你的代码是做什么的,也许能解释一下你在做什么?
    • 简单易用。做我想做的。非常感谢您的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 2014-11-27
    • 1970-01-01
    • 2010-10-28
    • 2014-10-13
    • 1970-01-01
    相关资源
    最近更新 更多