From 7f41f323f553e917048322a69d818c3a191553e2 Mon Sep 17 00:00:00 2001 From: DramaticShape Date: Mon, 27 Jul 2026 03:06:27 -0400 Subject: [PATCH] one standing clump per grass tile; ledge pillars at ledge height Grass: each 8x8 tile is one whole clump, so it stands as ONE full-height slab at its own depth. The first cut split every tile again into its top and bottom four art rows and stood those at two different depths, which cut each blade in half -- two 4px stubs 4px apart rather than a tuft. A cell's 2x2 tiles still stand independently, so the player walks between the north and south rows. Ledges: $34 is the cliff slope's foot AND the pillar between hop-down segments. Pinned `wall` with the rest of the slope chain it stood 16px beside a 6px lip, breaking the ledge line with blocks nearly three times its height. At ledge height the run reads continuous, and the Diglett mound is unchanged -- its foot row reads as the talus it is drawn as. --- data/voxel_heights.lua | 30 ++++++++----- lib/Structures.lua | 100 ++++++++++++++++++++++------------------- 2 files changed, 73 insertions(+), 57 deletions(-) diff --git a/data/voxel_heights.lua b/data/voxel_heights.lua index 6f10a89..77e2b21 100644 --- a/data/voxel_heights.lua +++ b/data/voxel_heights.lua @@ -111,7 +111,15 @@ return { -- the hop-down edges named by data.field.ledges' ledgeTile: their -- art is a ground lip seen from above, which the detector would -- otherwise raise as a wall - ledge = { 13, 29, 39, 54, 55 }, + -- $34 is the cliff slope's FOOT, and it also punctuates the ledge + -- rows: the hop-down runs are set into the cliff face and this + -- tile is the pillar between segments. It was `wall` with the + -- rest of the slope chain, which stood those pillars 16px beside + -- a 6px lip -- the ledge line came out interrupted by blocks + -- nearly three times its height. At ledge height the run reads + -- as one continuous lip, and the mound loses nothing: its foot + -- row simply reads as the talus it is drawn as. + ledge = { 13, 29, 39, 52, 54, 55 }, -- trees are drawn ROUND -- the lone canopy (42/43/58/59) and the -- border tree wall (64/65/80/81, blockset $0F). Boxes and per-pixel -- cutouts both read wrong for them; the cylinder archetype carves @@ -129,15 +137,17 @@ return { -- fence-textured tower. `post` extracts each cell alone, so these -- render as the same thin posts, marching north post = { 14, 85 }, - -- the cliff-mound's dark east slope and its corners ($02 the NE - -- corner, $24 the slope column, $34 the slope-to-rim seat). Their - -- drawn runs span the whole mound drawing, so the detector raised - -- them to 32px towers -- the rock pillar beside Diglett's Cave -- - -- and the doorway column, which adopts its REGION's height, - -- inherited the same 32 and put the cave entrance a block above - -- the mound around it. Pinned to one 16px course they match the - -- plateau body, and the doorway drops with them. - wall = { 2, 36, 52 }, + -- the cliff-mound's dark east slope and its NE corner ($24 the + -- slope column, $02 the corner). Their drawn runs span the whole + -- mound drawing, so the detector raised them to 32px towers -- + -- the rock pillar beside Diglett's Cave -- and the doorway + -- column, which adopts its REGION's height, inherited the same 32 + -- and put the cave entrance a block above the mound around it. + -- Pinned to one 16px course they match the plateau body, and the + -- doorway drops with them. ($34, the slope's foot, is `ledge` + -- instead -- see there.) + wall = { 2, 36 }, + -- the cuttable bush ($2D/$2E/$3D/$3E, the four tiles Cut deletes -- -- across the whole tileset they appear only in the five -- cut-tree blocks): a standing per-pixel cutout 5 voxels deep, diff --git a/lib/Structures.lua b/lib/Structures.lua index 8162040..6ff85f7 100644 --- a/lib/Structures.lua +++ b/lib/Structures.lua @@ -2091,14 +2091,21 @@ end -- ---- tall grass ---- --- A tall-grass tile draws its four tuft segments in two ROWS: the art's --- top half is one row of grass, the bottom half another. Each row stands --- as a thin per-pixel slab at its own drawn depth inside the tile, over --- the flat grass base the tile already renders -- so the player walks --- BETWEEN rows, and the southern row occludes their feet the way the 2D --- grass overdraw did. Transparency respected: only the tuft strokes stand. --- Runs of adjacent pixels merge into single quads, and one template per --- grass tile id is stamped across the map (grass comes in fields). +-- A tall-grass CELL is four tufts: 2x2 tiles, and each 8x8 tile is one +-- whole clump of grass. Each tile stands as its own thin per-pixel slab +-- at ITS OWN depth -- the cell's north tile row in the north half of the +-- cell, the south row in the south half -- over the flat grass base the +-- tile already renders. So the player walks BETWEEN the two rows, and +-- the southern row occludes their feet the way the 2D grass overdraw +-- did. Transparency respected: only the tuft strokes stand. Runs of +-- adjacent pixels merge into single quads, and one template per grass +-- tile id is stamped across the map (grass comes in fields). +-- +-- One tile is ONE standing piece, full height. The first cut split each +-- tile again into its top and bottom four art rows and stood those at +-- two different depths, which cut every blade that runs down the tile +-- clean in half -- the two halves ended up 4px tall and 4px apart in +-- depth, so a clump read as two stubs rather than one tuft. local GRASS_THICK = 2 local function grassTemplate(map, data, tileId) @@ -2115,49 +2122,48 @@ local function grassTemplate(map, data, tileId) end local quads = {} - for half = 0, 1 do - local rowBase = half * 4 - local zMid = half == 0 and 2.5 or 6.5 - local zB, zF = zMid - GRASS_THICK / 2, zMid + GRASS_THICK / 2 - for iy = 0, 3 do - local yTop = 4 - iy - local yBot = yTop - 1 - local ix = 0 - while ix < 8 do - if opaque(ix, rowBase + iy) then - local ix2 = ix - while ix2 + 1 < 8 and opaque(ix2 + 1, rowBase + iy) do - ix2 = ix2 + 1 - end - local u0 = (ax0 + ix + 0.05) / atlasW - local u1 = (ax0 + ix2 + 0.95) / atlasW - local v0 = (ay0 + rowBase + iy + 0.05) / atlasH - local v1 = (ay0 + rowBase + iy + 0.95) / atlasH - quads[#quads + 1] = { -- front - { ix, yBot, zF }, { ix2 + 1, yBot, zF }, + -- the slab stands across the middle of its own tile, so the two tile + -- rows of a cell are half a cell apart in depth + local zMid = 4 + local zB, zF = zMid - GRASS_THICK / 2, zMid + GRASS_THICK / 2 + for iy = 0, 7 do + local yTop = 8 - iy + local yBot = yTop - 1 + local ix = 0 + while ix < 8 do + if opaque(ix, iy) then + local ix2 = ix + while ix2 + 1 < 8 and opaque(ix2 + 1, iy) do + ix2 = ix2 + 1 + end + local u0 = (ax0 + ix + 0.05) / atlasW + local u1 = (ax0 + ix2 + 0.95) / atlasW + local v0 = (ay0 + iy + 0.05) / atlasH + local v1 = (ay0 + iy + 0.95) / atlasH + quads[#quads + 1] = { -- front + { ix, yBot, zF }, { ix2 + 1, yBot, zF }, + { ix2 + 1, yTop, zF }, { ix, yTop, zF }, + uv = { { u0, v1 }, { u1, v1 }, { u1, v0 }, { u0, v0 } }, + shade = 1, + } + quads[#quads + 1] = { -- back + { ix2 + 1, yBot, zB }, { ix, yBot, zB }, + { ix, yTop, zB }, { ix2 + 1, yTop, zB }, + uv = { { u1, v1 }, { u0, v1 }, { u0, v0 }, { u1, v0 } }, + shade = 0.68, + } + -- blade tips: a top strip where the row above is clear + if not opaque(ix, iy - 1) then + quads[#quads + 1] = { + { ix, yTop, zB }, { ix2 + 1, yTop, zB }, { ix2 + 1, yTop, zF }, { ix, yTop, zF }, - uv = { { u0, v1 }, { u1, v1 }, { u1, v0 }, { u0, v0 } }, + uv = { { u0, v0 }, { u1, v0 }, { u1, v0 }, { u0, v0 } }, shade = 1, } - quads[#quads + 1] = { -- back - { ix2 + 1, yBot, zB }, { ix, yBot, zB }, - { ix, yTop, zB }, { ix2 + 1, yTop, zB }, - uv = { { u1, v1 }, { u0, v1 }, { u0, v0 }, { u1, v0 } }, - shade = 0.68, - } - -- blade tips: a top strip where the row above is clear - if not opaque(ix, rowBase + iy - 1) then - quads[#quads + 1] = { - { ix, yTop, zB }, { ix2 + 1, yTop, zB }, - { ix2 + 1, yTop, zF }, { ix, yTop, zF }, - uv = { { u0, v0 }, { u1, v0 }, { u1, v0 }, { u0, v0 } }, - shade = 1, - } - end - ix = ix2 + 1 - else - ix = ix + 1 end + ix = ix2 + 1 + else + ix = ix + 1 end end end