我目前正在使用游戏拼写系统,我想知道是否有人知道一种简单的方法来放大矩阵及其值,就像图像拉伸一样。
我使用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}}
答案 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
使用公式:你有圆对称所以只需要半径,不需要存储值:
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的法术强度,无论房间的形状如何。你也可以很容易地组合多个法术的效果,比如敌人的抵抗法术(相同的距离公式)。
如果你真的必须使用矩阵,它必须适用于任何形状,那么这可能是最好的选择:
将旧矩阵缩放为新矩阵:
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
但希望你能完成剩下的工作:)