具有拉伸值的Lua比例矩阵放大

时间:2014-02-03 21:00:37

标签: matrix lua

我目前正在使用游戏拼写系统,我想知道是否有人知道一种简单的方法来放大矩阵及其值,就像图像拉伸一样。

我使用2D矩阵来表示受法术影响的区域,因此下面的矩阵代表起始法术效果点及其效果区域。

示例:

local area = {{0, 0, 1, 0, 0},
              {0, 1, 1, 1, 0},
              {1, 1, 3, 1, 1},
              {0, 1, 1, 1, 0},
              {0, 0, 1, 0, 0}}

其中:     3:原点(施放咒语的地方)     1:相对于原点的受影响区域。

考虑到这一点,我想开发一个扩大矩阵的功能。

function matrix.enlarge(mtx, row, col) ... end

以下函数的抽象和结果将显示一个区域的示例,如下所示:

local enlarged_matrix = matrix.enlarge(area, 2, 2)
matrix.print(enlarged_matrix)

--output
--local area = {{0, 0, 0, 1, 0, 0, 0},
--              {0, 0, 1, 1, 1, 0, 0},
--              {0, 1, 1, 1, 1, 1, 0},
--              {1, 1, 1, 3, 1, 1, 1},
--              {0, 1, 1, 1, 1, 1, 0},
--              {0, 0, 1, 1, 1, 0, 0},
--              {0, 0, 0, 1, 0, 0, 0}}

1 个答案:

答案 0 :(得分:0)

几种可能性:

  1. 暴力:创建新矩阵,将其复制到旧矩阵中:

    function matrix.enlarge(area, horiz, vert)
        local vertNow = #vert
        local horizNow = #horiz
        local newVert = vertNow + vert
        local newHoriz = horizNow + horiz
        -- create table of zeros
        local newMatrix = {}
        for i=1,newVert do
            tt = {}
            newMatrix[i] = tt
            for j=1,newHoriz do
                if i > vert/2 and i < vertNow + vert/2 and j > horiz/2 and j < horizNow + horiz/2 then
                    tt[j] = area[i][j]
                else
                    tt[j] = 0
                end
            end
        end
    end
    
  2. 使用公式:你有圆对称所以只需要半径,不需要存储值:

    function distance(i,j) 
         return math.sqrt(i*i+j*j)
    end
    local dissip = 2 -- at a distance of "2", spell is e^(-0.5) of center
    function getSpellStrength(dist) -- gaussian
         return 3*math.exp(-math.pow(dist/dissip, 2))
    end
    val = getSpellStrength(distance(i,j))
    

    如果法术强度的实际计算很重,并且传播不会经常变化(例如,只有当经验增加某个增量时),则选项1更好。如果传播变化很快(比如拼写生效时每个时间段),并且法术强度像高斯一样简单,则选项2更好。对于中间案例,这取决于你必须尝试两者。但#2更简单,所以除非你能证明它是性能瓶颈,否则我会赞成它。

    此外,无论房间/区域的形状如何,公式(选项2)都是微不足道的。如果敌人在i1,j1和c2处于i2,j2,你可以通过距离(i1-i2,j1-j2)立即知道i1,j1的法术强度,无论房间的形状如何。你也可以很容易地组合多个法术的效果,比如敌人的抵抗法术(相同的距离公式)。

    如果你真的必须使用矩阵,它必须适用于任何形状,那么这可能是最好的选择:

  3. 将旧矩阵缩放为新矩阵:

    function enlarge(area, deltaX, deltaY)
        sizeX = #(area[1])
        sizeY = #area -- number of rows
        scaleX = (sizeX + deltaX)/sizeX 
        scaleX = (sizeY + deltaY)/sizeY
        newArea = {}
        for iY=1, sizeY do
            newRow = {}
            newArea[iY] = newRow
            fromY = round(iY/scaleY)
            for jX=1, sizeX do
                fromX = round(jX/scaleX)
                if fromY < 1 or fromX < 1 or fromY > sizeY or fromX > sizeX then 
                    val = 0
                else
                    val = area[fromY][fromX]
                end
                newRow[jX] = val
            end
        end
        return newArea
    end
    

    在这里,您基本上创建了原始(插值)的缩放版本。警告:没有调试,所以你必须按摩一下(比如在一些地方可能会丢失+ -1,你应该声明你的vars本地等)。而round()就像是

    function round(x)
        return math.floor(num + 0.5)
    end
    

    但希望你能完成剩下的工作:)