使用拉伸值的 Lua 比例矩阵扩展

我目前正在开发一个游戏中的咒语系统,我想知道是否有一种简单的方法来扩大矩阵及其值,几乎就像图像拉伸一样。我正在使用2D矩阵来表示咒语影响区域,下面的矩阵表示起始咒语影响点及其影响区域。其中:3:原点(施放咒语的位置)1:相对于原点的影响区域。考虑到这一点,我想开发一个函数来扩大矩阵。function matrix.enlarge(mtx, row, col) ... end这个函数的抽象和结果,采用了一个区域的示例,如下所示:

点赞
用户869951
用户869951

以下有几种可能性:

  1. 暴力方法:创建新矩阵,将旧矩阵复制到其中:
function matrix.enlarge(area, horiz, vert)
    local vertNow = #vert
    local horizNow = #horiz
    local newVert = vertNow + vert
    local newHoriz = horizNow + horiz
    -- 创建零表
    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. 使用公式:因为你有圆形对称性,所以只需要半径,无需存储该值:
function distance(i,j)
    return math.sqrt(i*i+j*j)
end
local dissip = 2 -- 在“2”的距离处,咒语的强度为中心点的e^(-0.5)。
function getSpellStrength(dist) -- 高斯分布
    return 3*math.exp(-math.pow(dist/dissip, 2))
end
val = getSpellStrength(distance(i,j))

如果实际的咒语强度计算较复杂,并且传播不经常更改(例如仅当经验增加一定值时),则选项1更好。如果传播变化很快(例如每帧当咒语生效时),并且咒语强度像高斯分布一样简单,则选项2更好。对于中间情况,需要尝试两种方案。但是选项2更简单,因此除非可以证明它是性能瓶颈,否则我会支持它。

此外,公式(选项2)很容易应用于任何房间或区域的形状。如果敌人在i1,j1处,而施法者在i2,j2处,则可以通过距离(i1-i2,j1-j2)立即知道i1,j1处的咒语强度,无论房间的形状如何。您还可以相当容易地组合多个咒语的效果,例如抵抗敌人的咒语(相同的距离公式)。

如果您确实需要使用矩阵,并且它必须适用于任何形状,则可能是最佳选择:

  1. 将旧矩阵缩放到新矩阵中:
function enlarge(area, deltaX, deltaY)
    sizeX = #(area[1])
    sizeY = #area -- 行数
    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的地方缺失,应将变量声明为局部变量,等等)。 round()应该是像这样的:

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

但是希望您可以完成其余的工作 :)

2014-02-04 02:43:11