we're back baby

This commit is contained in:
Your Name 2026-08-07 01:57:48 -04:00
parent febaaaacc7
commit e065ab83de
3 changed files with 575 additions and 577 deletions

View file

@ -2,53 +2,33 @@ require "entity"
Door = class("Door", Entity) Door = class("Door", Entity)
function Door:initialize(x, y) function Door:initialize(x, y, color)
self.doorColor = color
Entity.initialize(self, { Entity.initialize(self, {
x = x, x = x,
y = y, y = y,
color = "white", color = color,
collision = "unmoveable", collision = "unmoveable",
sprites = { sprite = loadSprite("art/game/door_" .. color:sub(1, 1) .. ".png"),
red = loadSprite("art/game/door_r.png"),
green = loadSprite("art/game/door_g.png"),
blue = loadSprite("art/game/door_b.png"),
},
}) })
self.locked = true self.locked = true
self.colors = {}
for _, color in pairs({"red", "green", "blue"}) do
self.colors[color] = true --these are currently loc_ed
end
self:refreshSprites() self:refreshSprites()
end end
-- keep the per-channel sprite map in sync with lock state so the shared -- A door is one normal, colour-layered entity. The editor can therefore place,
-- Entity:draw(channel) renders the door with no door-specific draw code -- delete, and serialize its red/green/blue instances independently.
function Door:refreshSprites() function Door:refreshSprites()
self.sprites = {} local sprite
for _, c in ipairs({"red", "green", "blue"}) do if self.locked then
if self.locked then sprite = loadSprite("art/game/door_" .. self.doorColor:sub(1, 1) .. ".png")
if self.colors[c] then self.sprites[c] = loadSprite("art/game/door_" .. c:sub(1, 1) .. ".png") end else
else sprite = loadSprite("art/game/door_unlocked.png")
self.sprites[c] = loadSprite("art/game/door_unlocked.png")
end
end end
self.sprites = { [self.doorColor] = sprite }
end end
function Door:setColors(colors) function Door:setColors(colors)
local offColors = {} if colors[self.doorColor] then
for color, off in pairs(colors) do
if off then
if self.colors[color] then self.colors[color] = false end
table.insert(offColors, color)
else
if not self.colors[color] then self.colors[color] = true end
end
end
if #offColors == 3 then
if self.locked then self:unlock() end if self.locked then self:unlock() end
else else
if not self.locked then self:lock() end if not self.locked then self:lock() end
@ -65,4 +45,4 @@ end
function Door:lock() function Door:lock()
self.locked = true self.locked = true
self.collision = "unmoveable" self.collision = "unmoveable"
end end

View file

@ -23,7 +23,7 @@ function Room:initialize(t)
if t.name then if t.name then
print("loaded!!") print("loaded!!")
self:load(t.name) -- registers objects (and any saved players) from the .sav self:load(t.name, t.runtime) -- registers objects (and any saved players) from the .sav
print(t.name) print(t.name)
if t.player then if t.player then
@ -423,10 +423,6 @@ function Room:tick()
for _, door in pairs(self.doors) do for _, door in pairs(self.doors) do
door:setColors(setDoorColors) door:setColors(setDoorColors)
end end
-- Door:setColors can change collision from unmoveable to none. Rebuild once
-- more after that state change so an open-looking door is passable on the
-- very next input, rather than leaving the previous tick's solid cell here.
self:createCollideablesMatrix()
self:nextRoomCheck() self:nextRoomCheck()
end end
@ -541,8 +537,16 @@ function Room:createEntity(class, color, x, y)
local entity local entity
if behavior == "door" then if behavior == "door" then
entity = Door:new(x, y) -- Old migrated rooms stored a colourless shared door. Expand that legacy
self:registerDoor(entity) -- record into ordinary colour-layer door objects on load.
if not color then
for _, doorColor in ipairs({"red", "green", "blue"}) do
if props.sprites[doorColor] then self:createEntity(class, doorColor, x, y) end
end
return
end
entity = Door:new(x, y, color)
self:registerDoor(entity, color)
elseif behavior == "switch" then elseif behavior == "switch" then
entity = Switch:new(x, y, color) entity = Switch:new(x, y, color)
self:registerSwitch(entity, color) self:registerSwitch(entity, color)
@ -571,9 +575,9 @@ function Room:registerCollidable(entityPointer, colorArray)
end end
end end
function Room:registerDoor(entityPointer) function Room:registerDoor(entityPointer, color)
table.insert(self.doors, entityPointer) table.insert(self.doors, entityPointer)
self:registerCollidable(entityPointer, {"red", "green", "blue"}) self:registerCollidable(entityPointer, color)
end end
function Room:registerSwitch(entityPointer, color) function Room:registerSwitch(entityPointer, color)
@ -607,6 +611,7 @@ function Room:attemptDelete(mouseX, mouseY, color)
colors = {color} colors = {color}
end end
local removedEntities = {}
for _, c in ipairs(colors) do for _, c in ipairs(colors) do
-- player -- player
if self.player[c] and self.player[c]:occupiesCell(cell) then if self.player[c] and self.player[c]:occupiesCell(cell) then
@ -620,6 +625,7 @@ function Room:attemptDelete(mouseX, mouseY, color)
local entityArray = self.collideables[c] local entityArray = self.collideables[c]
for index = #entityArray, 1, -1 do for index = #entityArray, 1, -1 do
if entityArray[index]:occupiesCell(cell) then if entityArray[index]:occupiesCell(cell) then
removedEntities[entityArray[index]] = true
table.remove(entityArray, index) table.remove(entityArray, index)
end end
end end
@ -631,6 +637,11 @@ function Room:attemptDelete(mouseX, mouseY, color)
end end
end end
end end
-- Behaviour registries hold references to the same objects as the colour
-- layers. Clean references by identity; no class gets bespoke delete rules.
for index = #self.doors, 1, -1 do
if removedEntities[self.doors[index]] then table.remove(self.doors, index) end
end
self:tick() self:tick()
end end
@ -656,11 +667,13 @@ function Room:attemptPlace(name, props, mouseX, mouseY, color)
self:tick() self:tick()
end end
function Room:load(name) function Room:load(name, preferRuntime)
-- Runtime rooms are game state: let LÖVE resolve them from its save -- Editor/startup loads must use the project source level. Runtime saves are
-- directory, where Room:save writes autosaves. Source files remain the -- only consulted for an in-progress room-to-room game transition, otherwise
-- shipped/editor versions until the editor explicitly saves one. -- an old runtime autosave can hide an editor Save after restart.
local room = love.filesystem.read("rooms/" .. name .. ".sav") local room
if preferRuntime then room = love.filesystem.read("rooms/" .. name .. ".sav") end
if not room then room = readFromSource("rooms/" .. name .. ".sav") end
if not room then if not room then
-- no save yet: start with a blank room to build in the editor -- no save yet: start with a blank room to build in the editor
print("no save for '" .. name .. "', starting blank") print("no save for '" .. name .. "', starting blank")
@ -704,19 +717,9 @@ function Room:serialize()
emit("player", color, player) emit("player", color, player)
end end
-- collideables hold walls/static_walls/generics on one color each, plus
-- doors registered across all three colors -> dedupe doors, emit once
local seenDoor = {}
for color, collideableArray in pairs(self.collideables) do for color, collideableArray in pairs(self.collideables) do
for _, collideable in pairs(collideableArray) do for _, collideable in pairs(collideableArray) do
if collideable:isInstanceOf(Door) then emit(collideable.saveClass or "unmoveable", color, collideable)
if not seenDoor[collideable] then
seenDoor[collideable] = true
emit("door", nil, collideable)
end
else
emit(collideable.saveClass or "unmoveable", color, collideable)
end
end end
end end
@ -758,6 +761,7 @@ function nextRoom(pos)
-- A placed neighbour gets the same carried player state at its opposite edge. -- A placed neighbour gets the same carried player state at its opposite edge.
currentRoom = Room:new{ currentRoom = Room:new{
name = nextName or currentName, name = nextName or currentName,
runtime = true,
player = { player = {
x = newPos.x, y = newPos.y, activeColors = currentRoom:getActiveColors() x = newPos.x, y = newPos.y, activeColors = currentRoom:getActiveColors()
} }

File diff suppressed because it is too large Load diff