Difference between revisions of "TileMerging (日本語)"

m
(そのほかの言語)
 
(One intermediate revision by the same user not shown)
Line 122: Line 122:
 
{{#set:Description=タイルマップ上にある特定の種類のタイルに全て対応する長方形を生成します。}}
 
{{#set:Description=タイルマップ上にある特定の種類のタイルに全て対応する長方形を生成します。}}
 
== そのほかの言語 ==
 
== そのほかの言語 ==
{{i18n|Tile Merging}}
+
{{i18n|TileMerging}}

Latest revision as of 13:07, 21 June 2023

このアルゴリズムは 2D のタイルマップ用です。アルゴリズムは特定の種類のタイルに全て対応する長方形 (うまくいけば) の最小一式を生成します。

これはタイル壁の全てに対応した長方形を生成できるため、これは物理演算で有用です。単体タイルごとに対して物理学上の物体を作成する代わりに、複数のタイル壁の全てに対応する物理学上の物体を作成できます。

-- タイル壁ならば map_width および map_height は
-- マップ is_wall_f を確認するための寸法です。

local rectangles = {} -- 長方形ごとにタイル壁の格子にカバーします。

for x = 0, map_width - 1 do
    local start_y
    local end_y

    for y = 0, map_height - 1 do
        if is_wall_f(x, y) then
            if not start_y then
                start_y = y
            end
            end_y = y
        elseif start_y then
            local overlaps = {}
            for _, r in ipairs(rectangles) do
                if (r.end_x == x - 1)
                  and (start_y <= r.start_y)
                  and (end_y >= r.end_y) then
                    table.insert(overlaps, r)
                end
            end
            table.sort(
                overlaps,
                function (a, b)
                    return a.start_y < b.start_y
                end
            )

            for _, r in ipairs(overlaps) do
                if start_y < r.start_y then
                    local new_rect = {
                        start_x = x,
                        start_y = start_y,
                        end_x = x,
                        end_y = r.start_y - 1
                    }
                    table.insert(rectangles, new_rect)
                    start_y = r.start_y
                end

                if start_y == r.start_y then
                    r.end_x = r.end_x + 1

                    if end_y == r.end_y then
                        start_y = nil
                        end_y = nil
                    elseif end_y > r.end_y then
                        start_y = r.end_y + 1
                    end
                end
            end

            if start_y then
                local new_rect = {
                    start_x = x,
                    start_y = start_y,
                    end_x = x,
                    end_y = end_y
                }
                table.insert(rectangles, new_rect)

                start_y = nil
                end_y = nil
            end
        end
    end

    if start_y then
        local new_rect = {
            start_x = x,
            start_y = start_y,
            end_x = x,
            end_y = end_y
        }
        table.insert(rectangles, new_rect)

        start_y = nil
        end_y = nil
    end
end

ここでは物理演算に対して長方形がどの様に使用されるかの一例です。

-- 物理剛体を作成するために長方形の中身を使用します。
-- phys_world は世界であり、 wall_rects は一覧です...
-- ウォールの長方形

for _, r in ipairs(rectangles) do
    local start_x = r.start_x * TILE_SIZE
    local start_y = r.start_y * TILE_SIZE
    local width = (r.end_x - r.start_x + 1) * TILE_SIZE
    local height = (r.end_y - r.start_y + 1) * TILE_SIZE

    local x = start_x + (width / 2)
    local y = start_y + (height / 2)

    local body = love.physics.newBody(phys_world, x, y, 0, 0)
    local shape = love.physics.newRectangleShape(body, 0, 0,
      width, height)

    shape:setFriction(0)

    table.insert(wall_rects, {body = body, shape = shape})
end

寄贈者


そのほかの言語