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

Matrix 具有拉伸值的Lua比例矩阵放大,matrix,lua,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}

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

我使用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}}

有几种可能性:

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

    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
    
    如果法术强度的实际计算很繁重,并且扩散不经常改变(比如说只有当经验增加一定的增量时),那么选择1更好。如果排列变化很快(比如说法术生效时的每一个时间帧),并且法术强度像高斯一样简单,那么选择2更好。因为在两种情况之间,这取决于你必须同时尝试这两种方法。但是#2更简单,所以我更喜欢它,除非你能证明它是一个性能瓶颈

    此外,无论房间/面积的形状如何,公式(选项2)都很容易应用。如果敌人在i1,j1,施法者在i2,j2,你可以通过距离(i1-i2,j1-j2)立即知道i1,j1的法术强度,无论房间的形状如何。你也可以相当容易地组合多个法术的效果,比如敌人的抵抗法术(相同的距离公式)

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

  • 将旧矩阵缩放为新矩阵:

    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
    
    但希望你能完成剩下的工作:)


  • 我认为这取决于你为什么要放大矩阵:它是用来表示距离施法者更远的咒语(就像鹅卵石碰到水时的涟漪效应),还是因为你需要更多的细节(插值)?还有,每秒会放大多少次?你好,Scholliii,非常感谢您抽出时间。我正在扩大矩阵以使法术效果区域更大,它对我来说有很多用途,例如,在不需要编程的情况下,以顺序创建5个区域并以不同的延迟执行它们的情况下,为它的增长制作动画。非常感谢!我马上测试一下。。如果矩阵不是对称的,这会起作用吗?对不起,我忘了提一下,但有些区域可能是wave格式和其他特殊格式。。。像波浪、横梁、十字架等。对不起,即使是圆形区域,我也没能让它工作。。看来有什么不对劲。谢谢你抽出时间!实际上没有。。但可能是我在开玩笑。对于第二个选项,我不太明白如何使用它。。同样,我对这种矩阵低级操作没有经验。我将我的答案扩展到非循环情况。如前所述,我将坚持选择2。选项2不使用矩阵,这样您就不需要矩阵。如果你发布你尝试过的内容(扩展你的问题),可能会有所帮助。顺便说一句,你可以通过建议编辑其他问题(每接受一次编辑,你可以得到2分)来清除打字错误等,这对所有读者都很有用,这样你就可以投票了。哦,我明白了。。但在我的例子中,我必须有一个结果矩阵,以便将其传递给执行函数。执行函数是这样的:executeInArea(playerPosition,area,func,funcArgs)我不知道这些点,非常感谢您提供的信息,它非常有用。
    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
    
    function round(x)
        return math.floor(num + 0.5)
    end