平滑地放大瓷砖地图?

Scaling up a tile-map smoothly?

我正在为某个游戏制作一个 mod,我正在使用一个基础图块地图,我希望它可以扩展到更大的地图。但是,当我只使用 "nearest-neighbour" 一种缩放时,地图将具有硬方形边缘。我想阻止这种情况。

所以我有一个 tilemap,像这样:

- - X -
- X X X
X X X X
X X - -

根据我当前的缩放比例,我得到类似的东西:

- - - - X X - -
- - - - X X - -
- - X X X X X X 
- - X X X X X X
X X X X X X X X
X X X X X X X X
X X X X - - - -
X X X X - - - - 

如您所见,它有一些硬边。我希望他们更顺利:

- - - - X X - -
- - - X X X X -
- - X X X X X X 
- X X X X X X X
X X X X X X X X
X X X X X X X X
X X X X X X - -
X X X X - - - - 

我不知道该怎么称呼它,所以我的搜索结果并不多。

我怎样才能做这样的事情?

请注意,有几种不同类型的图块,没有介于两者之间的图块类型。

所以我自己试了一下,发现了一些似乎工作得很好的东西。

这是我的做法 (Lua):

--First get the cells you're between (x and y are real numbers, not ints)
local top = math.floor(y)
local bottom = (top + 1)
local left = math.floor(x)
local right = (left + 1)
--Then calculate weights. These are basically 1 - the distance. The distance is scaled to be between 0 and 1.
local sqrt2 = math.sqrt(2)
local w_top_left = 1 - math.sqrt((top - y)*(top - y) + (left - x)*(left - x)) / sqrt2
local w_top_right = 1 - math.sqrt((top - y)*(top - y) + (right - x)*(right - x)) / sqrt2
local w_bottom_left = 1 - math.sqrt((bottom - y)*(bottom - y) + (left - x)*(left - x)) / sqrt2
local w_bottom_right = 1 - math.sqrt((bottom - y)*(bottom - y) + (right - x)*(right - x)) / sqrt2
--Then square these weights, which makes it look better
w_top_left = w_top_left * w_top_left
w_top_right = w_top_right * w_top_right
w_bottom_left = w_bottom_left * w_bottom_left
w_bottom_right = w_bottom_right * w_bottom_right
--Now get the codes (or types) of the surrounding tiles
local c_top_left = decompressed_map_data[top % height][left % width]
local c_top_right = decompressed_map_data[top % height][right % width]
local c_bottom_left = decompressed_map_data[bottom % height][left % width]
local c_bottom_right = decompressed_map_data[bottom % height][right % width]
--Next calculate total weights for codes
-- So add together the weights of surrounding tiles if they have the same type
local totals = {}
add_to_total(totals, w_top_left, c_top_left) --see below for this helper func
add_to_total(totals, w_top_right, c_top_right)
add_to_total(totals, w_bottom_left, c_bottom_left)
add_to_total(totals, w_bottom_right, c_bottom_right)
--Lastly choose final code, which is the tile-type with the highest weight
local code = nil
local weight = 0
for _, total in pairs(totals) do
    if total.weight > weight then
        code = total.code
        weight = total.weight
    end
end
return terrain_codes[code]

-- Helper function
local function add_to_total(totals, weight, code)
    if totals[code] == nil then
        totals[code] = {code=code, weight=weight}
    else
        totals[code].weight = totals[code].weight + weight
    end
end

瞧。这 select 是任何 x/y 值的精确图块类型,即使它们不是整数,因此可以缩放您的网格。我不确定是否有更好的方法,但它有效并且看起来不错。最后,我还为权重添加了一些随机数,使边缘不那么直,这在 Factorio 中缩放非常高时看起来更好。