Replace box variants with a moveable adhesion property

Collapse the spiky/sticky/skewer box-variant assets into a single per-
instance `adhesion` property on any moveable block, chosen in the editor
via a dropdown next to the colour picker and stored in the .sav alongside
the class.

- spiky -> sticky: soft grab on every true edge (goopy shader)
- skewer -> gluey: rigid weld on every true edge (spiked outline)
- old trailing-face sticky is removed; its saves fold into new sticky

Move the spike geometry + drawGlueySprite into shaders.lua, fold drawing
and the adhesion flag into GenericMoveable, and delete the three
Generic{Sticky,Spiky,Skewer} classes and box_variants.lua. Room:createEntity
normalises legacy spiky_/skewer_/sticky_ class prefixes so old saves load,
and serialization emits `adhesion`. World/map previews and the movement
proxy follow the rename.

Backfill rooms/*.sav to the new format via tools/backfill_adhesion.lua
(41 objects across 8 files). Update tests to the two-mode model; the two
tests asserting the removed lateral-shear limitation are dropped and a
legacy-load migration test added. 27/27 pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-08-21 16:34:01 -04:00
parent c348b81a93
commit 7d84f595e4
25 changed files with 4010 additions and 3797 deletions

View file

@ -637,8 +637,7 @@ function World:movementContext(room, color)
function proxy:canMove() return self.entity:canMove() end
function proxy:canPassOver() return self.entity:canPassOver() end
function proxy:isSticky() return self.entity:isSticky() end
function proxy:isSkewer() return self.entity:isSkewer() end
function proxy:isSpiky() return self.entity:isSpiky() end
function proxy:isGluey() return self.entity:isGluey() end
function proxy:bump() return self.entity:bump() end
function proxy:getOccupiedCells(offset)
offset = offset or {x = 0, y = 0}
@ -1110,14 +1109,13 @@ function World:drawRoomPreview(name, x, y, size, roomData)
if path then
love.graphics.setColor(gColor[color]:set())
local sprite = loadSprite(path)
if props.goopy and drawGoopySprite then
drawGoopySprite(sprite, x + (object.x - 1) * 16 * scale, y + (object.y - 1) * 16 * scale, scale)
elseif props.skewer and drawSkewerSprite then
drawSkewerSprite(sprite, props.cells and props.cells[color], x + (object.x - 1) * 16 * scale, y + (object.y - 1) * 16 * scale, scale)
elseif props.spiky and drawSpikySprite then
drawSpikySprite(sprite, props.cells and props.cells[color], x + (object.x - 1) * 16 * scale, y + (object.y - 1) * 16 * scale, scale)
local dx, dy = x + (object.x - 1) * 16 * scale, y + (object.y - 1) * 16 * scale
if object.adhesion == "gluey" and drawGlueySprite then
drawGlueySprite(sprite, props.cells and props.cells[color], dx, dy, scale)
elseif object.adhesion == "sticky" and drawGoopySprite then
drawGoopySprite(sprite, dx, dy, scale)
else
love.graphics.draw(sprite, x + (object.x - 1) * 16 * scale, y + (object.y - 1) * 16 * scale, 0, scale, scale)
love.graphics.draw(sprite, dx, dy, 0, scale, scale)
end
end
end