diff --git a/door.lua b/door.lua index 4a08c20..3eb96a6 100644 --- a/door.lua +++ b/door.lua @@ -8,7 +8,11 @@ function Door:initialize(x, y) y = y, color = "white", collision = "unmoveable", - sprite = sprites.door["green"] --doesn't matter for now which we put here b/c, we override the draw function neway + sprites = { + red = sprites.door.red, + green = sprites.door.green, + blue = sprites.door.blue, + }, }) self.locked = true @@ -16,26 +20,19 @@ function Door:initialize(x, y) for _, color in pairs({"red", "green", "blue"}) do self.colors[color] = true --these are currently loc_ed end + self:refreshSprites() end -function Door:draw() - if self.locked then - for color, active in pairs(self.colors) do - if active then - love.graphics.setColor(gColor[color]:set()) - local p = self:getDrawPos() - love.graphics.draw(sprites.door[color], p.x + self.drawOffset.x, p.y + self.drawOffset.y, 0, drawScale, drawScale) - end +-- keep the per-channel sprite map in sync with lock state so the shared +-- Entity:draw(channel) renders the door with no door-specific draw code +function Door:refreshSprites() + self.sprites = {} + for _, c in ipairs({"red", "green", "blue"}) do + if self.locked then + if self.colors[c] then self.sprites[c] = sprites.door[c] end + else + self.sprites[c] = sprites.door.unlocked end - love.graphics.setColor(gColor.white:set()) - local p = self:getDrawPos() - love.graphics.draw(sprites.door["white"], p.x + self.drawOffset.x, p.y + self.drawOffset.y, 0, drawScale, drawScale) - else - for color, active in pairs(self.colors) do - love.graphics.setColor(gColor[color]:set()) - local p = self:getDrawPos() - love.graphics.draw(sprites.door["unlocked"], p.x + self.drawOffset.x, p.y + self.drawOffset.y, 0, drawScale, drawScale) - end end end @@ -56,6 +53,8 @@ function Door:setColors(colors) else if not self.locked then self:lock() end end + + self:refreshSprites() end function Door:unlock() diff --git a/entity.lua b/entity.lua index 2d8bc88..8a36a5b 100644 --- a/entity.lua +++ b/entity.lua @@ -2,13 +2,19 @@ Entity = class("Entity") function Entity:initialize(t) self.x, self.y = t.x, t.y - self.spriteSize = {w = t.sprite:getWidth(), h = t.sprite:getHeight()} + -- sprites keyed by channel ("red"/"green"/"blue"). Single-color entities pass + -- t.sprite + t.color and get one entry; multi-channel ones (doors) pass + -- t.sprites directly. The renderer draws only the channels the player has, so + -- no entity decides its own visibility (see Room:draw). + self.sprites = t.sprites or { [t.color] = t.sprite } + local repSprite = t.sprite or (t.sprites and select(2, next(t.sprites))) + self.spriteSize = {w = repSprite:getWidth(), h = repSprite:getHeight()} self.size = {w = self.spriteSize.w / 16, h = self.spriteSize.h / 16} self.cellShape = t.cellShape or self:cellShapeFromBox(self.size) self.name = t.name self.color = Color:new(t.color) self.collision = t.collision --"none", "moveable", "unmoveable" - self.sprite = t.sprite + self.sprite = repSprite self.shaAmount = t.sha or 1 self.onBump = t.onBump or function(self) return true end self.tick = t.tick or function(self) return true end @@ -108,10 +114,12 @@ function Entity:tick() return self.tick() end -function Entity:draw() - love.graphics.setColor(self.color:set()) +function Entity:draw(channel) + local sprite = self.sprites[channel] + if not sprite then return end + love.graphics.setColor(gColor[channel]:set()) local p = self:getDrawPos() - love.graphics.draw(self.sprite, p.x + self.drawOffset.x, p.y + self.drawOffset.y, 0, drawScale, drawScale) + love.graphics.draw(sprite, p.x + self.drawOffset.x, p.y + self.drawOffset.y, 0, drawScale, drawScale) end function Entity:canMove() diff --git a/room.lua b/room.lua index 24a86ff..7fc629f 100644 --- a/room.lua +++ b/room.lua @@ -124,41 +124,20 @@ end function Room:draw() - -- you only perceive the color channels the player actually has: with only a - -- red copy, only the red layer is drawn (a stacked r+g+b wall shows as red, - -- not white). Doors span all channels, so dedupe and draw them once. - local visible = {} - for _, c in ipairs(self.colorsPlayerHas) do visible[c] = true end + -- draw only the channels the player has. Each object just exposes sprites per + -- channel via Entity:draw(channel); a door registered on all three channels + -- naturally draws its red sprite on the red pass, etc. No per-object logic. + local has = {} + for _, channel in ipairs(self.colorsPlayerHas) do + has[channel] = true + if self.player[channel] then self.player[channel]:draw(channel) end + for _, entity in pairs(self.collideables[channel]) do entity:draw(channel) end + for _, switch in pairs(self.switches[channel]) do switch:draw(channel) end + end - for color, player in pairs(self.player) do - if visible[color] then player:draw() end - end - local drawnDoors = {} - for color, entityArray in pairs(self.collideables) do - if visible[color] then - for _, entity in pairs(entityArray) do - if entity:isInstanceOf(Door) then - if not drawnDoors[entity] then - drawnDoors[entity] = true - entity:draw() - end - else - entity:draw() - end - end - end - end - for color, switchArray in pairs(self.switches) do - if visible[color] then - for _, switch in pairs(switchArray) do - switch:draw() - end - end - end - -- npcs (old "sages") are just markers for now: draw a "?" in their cell, - -- tinted to only the channels the player has (never a white pixel) + -- npcs (old "sages") are markers for now: a "?" tinted to the player's channels local cellW, cellH = width / gridWidth, height / gridHeight - love.graphics.setColor(visible.red and 255 or 0, visible.green and 255 or 0, visible.blue and 255 or 0) + love.graphics.setColor(has.red and 255 or 0, has.green and 255 or 0, has.blue and 255 or 0) for _, npc in ipairs(self.npcs) do love.graphics.print("?", (npc.x - 1) * cellW + cellW * 0.3, (npc.y - 1) * cellH + cellH * 0.1, 0, 2, 2) end