2016-12-15 25 views
0

Я делаю мод для какой-то игры, и я использую базовую карту плитки, которую я хочу быть масштабируемой для большей карты. Однако, когда я просто использую масштабирование «ближайшего соседа», карта будет иметь жесткие квадратные края. Я хочу предотвратить это.Масштабирование плитки-карты плавно?

Так что у меня 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 - - - - 

Я не был уверен, что это назвать, так что мой поиск не оказаться много.

Как я могу сделать что-то подобное?

Обратите внимание, что существует несколько различных видов плиток, и между ними нет промежуточных типов плитки.

ответ

0

Так что я немного поиграл сам и нашел что-то, что, кажется, работает очень хорошо.

Вот что я делаю (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 

И вуаля. Это позволяет выбрать точный тип плитки для любого значения x/y, даже если они не являются целыми числами, что позволяет масштабировать сетку. Я не уверен, есть ли лучшие способы, но он работает и выглядит хорошо. В конце я также добавил случайное число к весам, чтобы сделать края немного менее прямыми, что выглядит лучше в Factorio при масштабировании очень высоко.

+1

Хорошая работа, получающая то, что работает. Я подумал, что вам может быть интересно [посмотреть на некоторые алгоритмы масштабирования, разработанные для пиксельного искусства] (https://en.wikipedia.org/wiki/Pixel_art_scaling_algorithms), поскольку приложение похоже похоже. – plast1k